@smarterplan/ngx-smarterplan-locations 0.3.4 → 0.4.2

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.
Files changed (82) hide show
  1. package/esm2022/lib/components/carousel/carousel.component.mjs +30 -0
  2. package/esm2022/lib/components/chevron/chevron.component.mjs +18 -0
  3. package/esm2022/lib/components/detail-location/detail-location.component.mjs +183 -0
  4. package/{esm2020 → esm2022}/lib/components/form-location/form-location.component.mjs +254 -237
  5. package/esm2022/lib/components/images/images.component.mjs +120 -0
  6. package/esm2022/lib/components/locations/locations.component.mjs +157 -0
  7. package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +72 -0
  8. package/esm2022/lib/components/locations/map/map.component.mjs +92 -0
  9. package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +49 -0
  10. package/esm2022/lib/components/plans/calibration/calibration.component.mjs +494 -0
  11. package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +350 -0
  12. package/{esm2020 → esm2022}/lib/components/plans/plans.component.mjs +243 -225
  13. package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +43 -0
  14. package/esm2022/lib/components/visits/visits.component.mjs +294 -0
  15. package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +250 -0
  16. package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +333 -0
  17. package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +81 -0
  18. package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +518 -0
  19. package/esm2022/lib/components/zones/zones.component.mjs +291 -0
  20. package/{esm2020 → esm2022}/lib/helper.service.mjs +133 -133
  21. package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +50 -0
  22. package/esm2022/lib/ngx-smarterplan-locations.module.mjs +124 -0
  23. package/esm2022/lib/ngx-smarterplan-locations.service.mjs +15 -0
  24. package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +29 -0
  25. package/esm2022/lib/radio-button/radio-button.component.mjs +28 -0
  26. package/{esm2020 → esm2022}/public-api.mjs +8 -8
  27. package/{esm2020 → esm2022}/smarterplan-ngx-smarterplan-locations.mjs +4 -4
  28. package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-locations.mjs +3959 -3738
  29. package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
  30. package/index.d.ts +5 -5
  31. package/lib/components/carousel/carousel.component.d.ts +12 -12
  32. package/lib/components/chevron/chevron.component.d.ts +9 -9
  33. package/lib/components/detail-location/detail-location.component.d.ts +55 -55
  34. package/lib/components/form-location/form-location.component.d.ts +45 -45
  35. package/lib/components/images/images.component.d.ts +33 -33
  36. package/lib/components/locations/locations.component.d.ts +51 -51
  37. package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
  38. package/lib/components/locations/map/map.component.d.ts +21 -22
  39. package/lib/components/plan-legend/plan-legend.component.d.ts +14 -14
  40. package/lib/components/plans/calibration/calibration.component.d.ts +140 -140
  41. package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -55
  42. package/lib/components/plans/plans.component.d.ts +63 -63
  43. package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
  44. package/lib/components/visits/visits.component.d.ts +63 -63
  45. package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -63
  46. package/lib/components/zones/add-zone/add-zone.component.d.ts +69 -69
  47. package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -44
  48. package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +107 -107
  49. package/lib/components/zones/zones.component.d.ts +73 -73
  50. package/lib/helper.service.d.ts +53 -53
  51. package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -7
  52. package/lib/ngx-smarterplan-locations.module.d.ts +36 -36
  53. package/lib/ngx-smarterplan-locations.service.d.ts +6 -6
  54. package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -10
  55. package/lib/radio-button/radio-button.component.d.ts +12 -12
  56. package/package.json +13 -19
  57. package/public-api.d.ts +4 -4
  58. package/esm2020/lib/components/carousel/carousel.component.mjs +0 -28
  59. package/esm2020/lib/components/chevron/chevron.component.mjs +0 -18
  60. package/esm2020/lib/components/detail-location/detail-location.component.mjs +0 -168
  61. package/esm2020/lib/components/images/images.component.mjs +0 -107
  62. package/esm2020/lib/components/locations/locations.component.mjs +0 -145
  63. package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +0 -66
  64. package/esm2020/lib/components/locations/map/map.component.mjs +0 -91
  65. package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +0 -47
  66. package/esm2020/lib/components/plans/calibration/calibration.component.mjs +0 -468
  67. package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +0 -324
  68. package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +0 -41
  69. package/esm2020/lib/components/visits/visits.component.mjs +0 -275
  70. package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +0 -230
  71. package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +0 -315
  72. package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +0 -77
  73. package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +0 -502
  74. package/esm2020/lib/components/zones/zones.component.mjs +0 -268
  75. package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +0 -49
  76. package/esm2020/lib/ngx-smarterplan-locations.module.mjs +0 -123
  77. package/esm2020/lib/ngx-smarterplan-locations.service.mjs +0 -14
  78. package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +0 -27
  79. package/esm2020/lib/radio-button/radio-button.component.mjs +0 -26
  80. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +0 -3983
  81. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
  82. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
@@ -1,3983 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, Component, Output, Input, ViewChild, Pipe, HostListener, NgModule } from '@angular/core';
3
- import { __awaiter } from 'tslib';
4
- import * as i2 from '@smarterplan/ngx-smarterplan-core';
5
- import { enumToArray, LevelStatus, textValidator, noEmptyValidator, floatValidator, uploadFileToS3, deleteFromS3, PropertyType, getSignedImageUrlForSpace, SearchObjectType, SpaceStatus, getMetaForImage, getSignedFile, downloadFileAsObject, downloadBlob, CaptureViewer, showScanPointsOnPlanInDiv, getCoefficientsForImage, CommentType, SpModule, wait, InventoryStatus, NgxSmarterplanCoreModule } from '@smarterplan/ngx-smarterplan-core';
6
- import * as i1 from '@angular/router';
7
- import { RouterModule } from '@angular/router';
8
- import * as i4$1 from '@ng-bootstrap/ng-bootstrap';
9
- import { ModalDismissReasons, NgbModule, NgbAlertModule } from '@ng-bootstrap/ng-bootstrap';
10
- import * as i4 from '@angular/common';
11
- import { CommonModule } from '@angular/common';
12
- import * as i3 from '@ngx-translate/core';
13
- import { TranslateModule } from '@ngx-translate/core';
14
- import { icon, Marker, tileLayer, latLng, marker, latLngBounds, point } from 'leaflet';
15
- import * as i1$1 from '@asymmetrik/ngx-leaflet';
16
- import { LeafletModule } from '@asymmetrik/ngx-leaflet';
17
- import * as i1$2 from '@angular/forms';
18
- import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
19
- import { Subject, takeUntil } from 'rxjs';
20
- import * as i4$2 from '@angular/cdk/clipboard';
21
- import { ClipboardModule } from '@angular/cdk/clipboard';
22
- import { getDocument } from 'pdfjs-dist';
23
- import panzoom from 'panzoom';
24
- import { PdfViewerModule } from 'ng2-pdf-viewer';
25
-
26
- class NgxSmarterplanLocationsService {
27
- constructor() { }
28
- }
29
- NgxSmarterplanLocationsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30
- NgxSmarterplanLocationsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsService, providedIn: 'root' });
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsService, decorators: [{
32
- type: Injectable,
33
- args: [{
34
- providedIn: 'root'
35
- }]
36
- }], ctorParameters: function () { return []; } });
37
-
38
- class TabNavigationComponent {
39
- constructor(router) {
40
- this.router = router;
41
- this.onGoBack = new EventEmitter();
42
- this.menuItems = [];
43
- }
44
- onClick(url, parameter, index) {
45
- if (index === this.menuItems.length - 1) {
46
- return;
47
- }
48
- if (url) {
49
- const newURL = `/dashboard${url}`;
50
- if (this.router.url !== newURL) {
51
- console.log('new url', newURL);
52
- this.router.navigate([newURL]);
53
- }
54
- else {
55
- this.onGoBack.emit(parameter);
56
- }
57
- }
58
- else {
59
- this.onGoBack.emit(parameter);
60
- }
61
- }
62
- }
63
- TabNavigationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TabNavigationComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
64
- TabNavigationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: { menuItems: "menuItems" }, outputs: { onGoBack: "onGoBack" }, ngImport: i0, template: "<span class=\"menu\">\r\n <span *ngFor=\"let item of menuItems; let index = index;\">\r\n <span class=\"item\" [ngClass]=\"{'current':index === menuItems.length - 1}\"\r\n (click)=\"onClick(item.url,item.back, index)\">{{item.label | translate}}</span> <span\r\n *ngIf=\"index !== menuItems.length - 1\" class=\"separator\">></span>\r\n </span>\r\n</span>\r\n", styles: [".item{font-size:1.35em;color:var(--smarterplan-primary);cursor:pointer}.current{color:var(--smarterplan-primary)!important;cursor:default!important;text-decoration:none!important}.separator{font-size:1.4em;margin-left:10px;margin-right:10px;color:var(--smarterplan-primary)}.item:hover{text-decoration:underline}.menu{margin-top:15px;margin-bottom:20px}\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: "pipe", type: i3.TranslatePipe, name: "translate" }] });
65
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TabNavigationComponent, decorators: [{
66
- type: Component,
67
- args: [{ selector: 'lib-tab-navigation', template: "<span class=\"menu\">\r\n <span *ngFor=\"let item of menuItems; let index = index;\">\r\n <span class=\"item\" [ngClass]=\"{'current':index === menuItems.length - 1}\"\r\n (click)=\"onClick(item.url,item.back, index)\">{{item.label | translate}}</span> <span\r\n *ngIf=\"index !== menuItems.length - 1\" class=\"separator\">></span>\r\n </span>\r\n</span>\r\n", styles: [".item{font-size:1.35em;color:var(--smarterplan-primary);cursor:pointer}.current{color:var(--smarterplan-primary)!important;cursor:default!important;text-decoration:none!important}.separator{font-size:1.4em;margin-left:10px;margin-right:10px;color:var(--smarterplan-primary)}.item:hover{text-decoration:underline}.menu{margin-top:15px;margin-bottom:20px}\n"] }]
68
- }], ctorParameters: function () { return [{ type: i1.Router }]; }, propDecorators: { onGoBack: [{
69
- type: Output
70
- }], menuItems: [{
71
- type: Input
72
- }] } });
73
-
74
- class MapPopupComponent {
75
- constructor(router, ngZone) {
76
- this.router = router;
77
- this.ngZone = ngZone;
78
- this.isOnPopup = false;
79
- this.isMuseumUser = true;
80
- }
81
- ngOnInit() {
82
- this.marker.on("click", () => this.onClickVisitFirst());
83
- this.marker.on("mouseover", () => {
84
- this.isOnPopup = true;
85
- if (!this.marker.isPopupOpen()) {
86
- this.openPopup();
87
- }
88
- });
89
- }
90
- openPopup() {
91
- this.marker.openPopup();
92
- this.isOnPopup = false;
93
- this.popuparea = document.querySelector(".leaflet-popup");
94
- this.popuparea.addEventListener("mouseleave", () => {
95
- this.closePopup();
96
- });
97
- this.popuparea.addEventListener("mouseover", () => {
98
- this.isOnPopup = true;
99
- });
100
- this.marker.on("mouseout", () => {
101
- this.closePopup();
102
- });
103
- }
104
- closePopup() {
105
- this.isOnPopup = false;
106
- /** We want to wait to avoid glitch */
107
- setTimeout(() => {
108
- if (!this.isOnPopup) {
109
- this.marker.closePopup();
110
- }
111
- }, 100);
112
- }
113
- onClickVisitFirst() {
114
- if (this.space.visits.length === 0) {
115
- console.log("No space to visit !");
116
- }
117
- else {
118
- this.onVisitClick(this.space.visits[0]);
119
- }
120
- }
121
- onVisitClick(visit) {
122
- return __awaiter(this, void 0, void 0, function* () {
123
- this.ngZone.run(() => {
124
- this.router.navigate(["visit", this.space.id], {
125
- queryParams: { model3D: visit.model3d },
126
- });
127
- });
128
- });
129
- }
130
- }
131
- MapPopupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MapPopupComponent, deps: [{ token: i1.Router }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
132
- MapPopupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: MapPopupComponent, selector: "lib-map-popup", ngImport: i0, template: "<div id=\"map-popup\">\r\n <div class=\"map-popup-header\" (click)=\"onClickVisitFirst()\" [style.cursor]=\"'pointer'\">\r\n <img [src]=\"space.annexes\" />\r\n </div>\r\n <div class=\"map-popup-details\">\r\n <h1 (click)=\"onClickVisitFirst()\" [style.cursor]=\"'pointer'\">{{space.name}}</h1>\r\n <span class=\"map-popup-address\">{{space.addresses}}</span>\r\n <span *ngFor=\"let visit of space.visits\" class=\"map-popup-visit\" (click)=\"onVisitClick(visit)\"\r\n [style.cursor]=\"'pointer'\">\u27A4 {{ visit.name ? visit.name : space.name}}</span>\r\n </div>\r\n</div>\r\n", styles: [".map-popup-header{height:120px;overflow:hidden;border-top-right-radius:20px;border-top-left-radius:20px}.map-popup-header img{width:100%;position:relative;top:50%;transform:translateY(-50%)}.map-popup-details{padding:5px 10px 10px;border-bottom-left-radius:20px;border-bottom-right-radius:20px;background-color:#fff;color:#000}.map-popup-details{display:flex;flex-direction:column}.map-popup-details h1{font-size:1.5rem;font-weight:700;margin-bottom:0;color:var(--smarterplan-primary)}.map-popup-address{align-self:flex-end;margin-bottom:10px}.map-popup-visit{color:var(--smarterplan-primary);font-size:1.15rem}.map-popup-visit:hover{color:var(--smarterplan-primary)}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
133
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MapPopupComponent, decorators: [{
134
- type: Component,
135
- args: [{ selector: 'lib-map-popup', template: "<div id=\"map-popup\">\r\n <div class=\"map-popup-header\" (click)=\"onClickVisitFirst()\" [style.cursor]=\"'pointer'\">\r\n <img [src]=\"space.annexes\" />\r\n </div>\r\n <div class=\"map-popup-details\">\r\n <h1 (click)=\"onClickVisitFirst()\" [style.cursor]=\"'pointer'\">{{space.name}}</h1>\r\n <span class=\"map-popup-address\">{{space.addresses}}</span>\r\n <span *ngFor=\"let visit of space.visits\" class=\"map-popup-visit\" (click)=\"onVisitClick(visit)\"\r\n [style.cursor]=\"'pointer'\">\u27A4 {{ visit.name ? visit.name : space.name}}</span>\r\n </div>\r\n</div>\r\n", styles: [".map-popup-header{height:120px;overflow:hidden;border-top-right-radius:20px;border-top-left-radius:20px}.map-popup-header img{width:100%;position:relative;top:50%;transform:translateY(-50%)}.map-popup-details{padding:5px 10px 10px;border-bottom-left-radius:20px;border-bottom-right-radius:20px;background-color:#fff;color:#000}.map-popup-details{display:flex;flex-direction:column}.map-popup-details h1{font-size:1.5rem;font-weight:700;margin-bottom:0;color:var(--smarterplan-primary)}.map-popup-address{align-self:flex-end;margin-bottom:10px}.map-popup-visit{color:var(--smarterplan-primary);font-size:1.15rem}.map-popup-visit:hover{color:var(--smarterplan-primary)}\n"] }]
136
- }], ctorParameters: function () { return [{ type: i1.Router }, { type: i0.NgZone }]; } });
137
-
138
- const iconRetinaUrl = "assets/marker-icon-2x.png";
139
- const iconUrl = "assets/marker-icon.png";
140
- const shadowUrl = "assets/marker-shadow.png";
141
- const iconDefault = icon({
142
- iconRetinaUrl,
143
- iconUrl,
144
- shadowUrl,
145
- iconSize: [25, 41],
146
- iconAnchor: [12, 41],
147
- popupAnchor: [1, -34],
148
- tooltipAnchor: [16, -28],
149
- shadowSize: [41, 41],
150
- });
151
- Marker.prototype.options.icon = iconDefault;
152
- class MapComponent {
153
- constructor(componentFactoryResolver, injector) {
154
- this.componentFactoryResolver = componentFactoryResolver;
155
- this.injector = injector;
156
- this.options = {
157
- layers: [
158
- tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
159
- maxZoom: 18,
160
- attribution: "...",
161
- }),
162
- ],
163
- zoom: 5.5,
164
- center: latLng(47.06394, 2.77736),
165
- };
166
- this.layers = [];
167
- }
168
- ngOnChanges(changes) {
169
- if (changes.spaces) {
170
- const nm = [];
171
- const bd = [];
172
- if (!changes.spaces.currentValue) {
173
- return;
174
- }
175
- // Filtering out spaces without lat/longitudes
176
- for (const s of changes.spaces.currentValue) {
177
- if (s.latitude === null || s.longitude === null) {
178
- console.log(`${s.name} has not coordinates for ${s.addresses}`);
179
- continue;
180
- }
181
- // We use the popup system from leaflet, as it packs a few improvements
182
- // on using bootstrap: autoclose other popups, closing option.
183
- const m = marker([s.latitude, s.longitude]);
184
- m.bindPopup(this.createPopupComponent(s, m));
185
- nm.push(m);
186
- bd.push(latLng(s.latitude, s.longitude));
187
- }
188
- // Note how we set the layers in one assignment, in order to have leaflet
189
- // detects the change correctly
190
- // We also set the bounds afterward, for the map to be properly zoomed and
191
- // centered
192
- this.layers = nm;
193
- if (this.map && bd.length > 0) {
194
- this.map.fitBounds(latLngBounds(bd), {
195
- padding: point(48, 48),
196
- maxZoom: 12,
197
- animate: true,
198
- });
199
- }
200
- }
201
- }
202
- onMapReady(map) {
203
- this.map = map;
204
- }
205
- createPopupComponent(space, marker) {
206
- const comp = this.componentFactoryResolver
207
- .resolveComponentFactory(MapPopupComponent)
208
- .create(this.injector);
209
- comp.instance.space = space;
210
- comp.instance.marker = marker;
211
- comp.changeDetectorRef.detectChanges();
212
- return comp.location.nativeElement;
213
- }
214
- }
215
- MapComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MapComponent, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
216
- MapComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: MapComponent, selector: "lib-map", inputs: { spaces: "spaces" }, usesOnChanges: true, ngImport: i0, template: "<div [leafletLayers]=\"layers\" [leafletOptions]=\"options\" (leafletMapReady)=\"onMapReady($any($event))\" id=\"map\" leaflet\r\n style=\"height: 500px; margin-top: 30px; z-index: 195\"></div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.LeafletDirective, selector: "[leaflet]", inputs: ["leafletFitBoundsOptions", "leafletPanOptions", "leafletZoomOptions", "leafletZoomPanOptions", "leafletOptions", "leafletZoom", "leafletCenter", "leafletFitBounds", "leafletMaxBounds", "leafletMinZoom", "leafletMaxZoom"], outputs: ["leafletMapReady", "leafletZoomChange", "leafletCenterChange", "leafletClick", "leafletDoubleClick", "leafletMouseDown", "leafletMouseUp", "leafletMouseMove", "leafletMouseOver", "leafletMouseOut", "leafletMapMove", "leafletMapMoveStart", "leafletMapMoveEnd", "leafletMapZoom", "leafletMapZoomStart", "leafletMapZoomEnd"] }, { kind: "directive", type: i1$1.LeafletLayersDirective, selector: "[leafletLayers]", inputs: ["leafletLayers"] }] });
217
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MapComponent, decorators: [{
218
- type: Component,
219
- args: [{ selector: 'lib-map', template: "<div [leafletLayers]=\"layers\" [leafletOptions]=\"options\" (leafletMapReady)=\"onMapReady($any($event))\" id=\"map\" leaflet\r\n style=\"height: 500px; margin-top: 30px; z-index: 195\"></div>" }]
220
- }], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.Injector }]; }, propDecorators: { spaces: [{
221
- type: Input
222
- }] } });
223
-
224
- class FormLocationComponent {
225
- constructor(spaceService, propertyService, userService, fb, missionService, layerService, validatorsService) {
226
- this.spaceService = spaceService;
227
- this.propertyService = propertyService;
228
- this.userService = userService;
229
- this.fb = fb;
230
- this.missionService = missionService;
231
- this.layerService = layerService;
232
- this.validatorsService = validatorsService;
233
- this.isSubmitted = false;
234
- this.addMissionForNewSpace = true;
235
- this.imageToBeDeleted = false;
236
- this.errorForm = false;
237
- this.onChange = new EventEmitter();
238
- this.levels = enumToArray(LevelStatus);
239
- }
240
- ngOnInit() {
241
- if (this.location) {
242
- this.initEditForm();
243
- }
244
- else {
245
- this.initForm();
246
- }
247
- this.handleInputImageText();
248
- }
249
- initForm() {
250
- this.form = this.fb.group({
251
- name: ["", [Validators.required, Validators.maxLength(255), textValidator(), noEmptyValidator()]],
252
- addresses: ["", [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
253
- latitude: [null, [Validators.maxLength(255), noEmptyValidator(), floatValidator()]],
254
- longitude: [null, [Validators.maxLength(255), noEmptyValidator(), floatValidator()]],
255
- level: LevelStatus.LOW,
256
- classGes: ["", [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
257
- classEnergyConsumption: ["", [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
258
- constructionYear: ["", [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
259
- });
260
- }
261
- initEditForm() {
262
- this.form = this.fb.group({
263
- id: this.location.id,
264
- name: [this.location.name, [Validators.required, Validators.maxLength(255), textValidator(), noEmptyValidator()]],
265
- addresses: [this.location.addresses, [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
266
- latitude: [this.location.latitude, [Validators.maxLength(255), floatValidator()]],
267
- longitude: [this.location.longitude, [Validators.maxLength(255), floatValidator()]],
268
- level: this.location.level,
269
- classGes: [this.location.classGes, [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
270
- classEnergyConsumption: [this.location.classEnergyConsumption, [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
271
- constructionYear: [this.location.constructionYear, [Validators.maxLength(255), textValidator(), noEmptyValidator()]],
272
- });
273
- }
274
- handleImageInput(target) {
275
- this.imageToUpload = target.files[0];
276
- if (this.imageToUpload) {
277
- this.imageInputContainer.nativeElement.style.display = "none";
278
- const reader = new FileReader();
279
- reader.addEventListener("load", () => {
280
- this.currentImage = reader.result;
281
- });
282
- reader.readAsDataURL(this.imageToUpload);
283
- }
284
- }
285
- uploadImage(spaceID) {
286
- return __awaiter(this, void 0, void 0, function* () {
287
- if (this.imageToUpload) {
288
- uploadFileToS3("locations/", this.imageToUpload, spaceID).then((url) => __awaiter(this, void 0, void 0, function* () {
289
- if (url) {
290
- yield this.spaceService.updateSpace({
291
- id: spaceID,
292
- annexes: url,
293
- });
294
- }
295
- }));
296
- }
297
- else if (this.imageToBeDeleted) {
298
- yield this.spaceService.updateSpace({
299
- id: spaceID,
300
- annexes: null,
301
- });
302
- yield deleteFromS3(this.location.annexes);
303
- }
304
- });
305
- }
306
- clearImageFile() {
307
- this.imageToUpload = null;
308
- this.currentImage = null;
309
- this.imageInputContainer.nativeElement.style.display = "flex";
310
- this.imageInput.nativeElement.value = "";
311
- this.imageInputText = "Add picture";
312
- }
313
- getLayerByName(name) {
314
- return __awaiter(this, void 0, void 0, function* () {
315
- const currentOrgId = this.userService.currentOrganisation().id;
316
- const layers = yield this.layerService.getLayerByNameForOrganisation(name, currentOrgId);
317
- if (layers) {
318
- return layers[0];
319
- }
320
- // create then
321
- return this.layerService.createLayerForOrganisation(name, currentOrgId);
322
- });
323
- }
324
- onSubmit() {
325
- return __awaiter(this, void 0, void 0, function* () {
326
- this.isSubmitted = true;
327
- if (!this.form.valid) {
328
- this.errorForm = true;
329
- return;
330
- }
331
- try {
332
- this.errorForm = false;
333
- let space;
334
- if (this.location) {
335
- this.changeCommaToDot();
336
- space = yield this.spaceService.updateSpace(this.form.value);
337
- if (space) {
338
- yield this.uploadImage(space.id);
339
- this.location = space;
340
- this.onChange.emit(space);
341
- }
342
- }
343
- else {
344
- this.changeCommaToDot();
345
- const spaceInput = this.form.value;
346
- const currentOrgID = this.userService.currentOrganisation().id;
347
- spaceInput.organisationID = currentOrgID;
348
- let layer = yield this.getLayerByName("BUILDING");
349
- if (!layer) {
350
- layer = yield this.layerService.createLayerForOrganisation("BUILDING", currentOrgID);
351
- }
352
- space = yield this.spaceService.createSpace(spaceInput, layer);
353
- const missions = this.userService.getManagerMissions();
354
- if (space && missions.length > 0) {
355
- const exampleMission = missions[0];
356
- yield this.uploadImage(space.id);
357
- try {
358
- yield this.propertyService.createProperty({
359
- type: PropertyType.PROPERTY,
360
- spaceID: space.id,
361
- organisationID: currentOrgID,
362
- });
363
- }
364
- catch (e) {
365
- console.log("API Service does not have Property requests");
366
- }
367
- // add directly a mission for this space
368
- if (this.addMissionForNewSpace) {
369
- yield this.missionService.create({
370
- spaceID: space.id,
371
- userID: exampleMission.userID,
372
- role: exampleMission.role,
373
- level: exampleMission.level,
374
- organisationID: exampleMission.organisationID,
375
- orderedOrganisationID: exampleMission.organisationID,
376
- });
377
- }
378
- this.onChange.emit(space);
379
- }
380
- else {
381
- this.onChange.emit(null);
382
- }
383
- }
384
- }
385
- catch (error) {
386
- console.error(error);
387
- this.onChange.emit(null);
388
- }
389
- });
390
- }
391
- onCancel() {
392
- this.form.reset();
393
- this.onChange.emit(null);
394
- }
395
- get name() {
396
- return this.form.get("name");
397
- }
398
- changeCommaToDot() {
399
- const updatedSpace = this.form.value;
400
- if (updatedSpace.latitude &&
401
- updatedSpace.latitude.toString().includes(",")) {
402
- updatedSpace.latitude = updatedSpace.latitude
403
- .toString()
404
- .replace(",", ".");
405
- Number.parseFloat(updatedSpace.latitude);
406
- }
407
- if (updatedSpace.longitude &&
408
- updatedSpace.longitude.toString().includes(",")) {
409
- updatedSpace.longitude = updatedSpace.longitude
410
- .toString()
411
- .replace(",", ".");
412
- Number.parseFloat(updatedSpace.longitude);
413
- }
414
- }
415
- handleInputImageText() {
416
- if (this.location && this.location.annexes) {
417
- this.imageInputText = "Change picture";
418
- getSignedImageUrlForSpace(this.location).then((url) => {
419
- if (url) {
420
- this.currentImage = url;
421
- }
422
- });
423
- }
424
- else {
425
- this.imageInputText = "Add picture";
426
- }
427
- }
428
- isFormError(control) {
429
- return control && control.invalid && this.errorForm;
430
- }
431
- onFormChange() {
432
- if (this.errorForm && this.form.valid) {
433
- this.errorForm = false;
434
- }
435
- }
436
- }
437
- FormLocationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FormLocationComponent, deps: [{ token: i2.SpaceService }, { token: i2.PropertyService }, { token: i2.BaseUserService }, { token: i1$2.UntypedFormBuilder }, { token: i2.MissionService }, { token: i2.LayerService }, { token: i2.ValidatorsService }], target: i0.ɵɵFactoryTarget.Component });
438
- FormLocationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: FormLocationComponent, selector: "lib-form-location", inputs: { location: "location" }, outputs: { onChange: "onChange" }, viewQueries: [{ propertyName: "imageInputContainer", first: true, predicate: ["imageInputContainer"], descendants: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true }, { propertyName: "imageBasePreview", first: true, predicate: ["imageBasePreview"], descendants: true }], ngImport: i0, template: "<div class=\"col-md-6 form-new-loc\" *ngIf=\"form\">\r\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" data-testid=\"new-location-name\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['name'])|| isFormError(form.controls['name'])}\"\r\n required formControlName=\"name\">\r\n\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" *ngIf=\"validatorsService.isControlError(form.controls['name']) \r\n || isFormError(form.controls['name'])\">\r\n {{validatorsService.getError(form.controls['name']) | translate}}\r\n </ngb-alert>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Address' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"addresses\" data-testid=\"new-location-address\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['addresses']) || isFormError(form.controls['addresses'])}\">\r\n <div class=\"invalid-feedback\">\r\n <span data-testid=\"\" [translate]=\"validatorsService.getError(form.controls['addresses'])\"\r\n *ngIf=\" validatorsService.isControlError(form.controls['addresses'])\"></span>\r\n\r\n <ngb-alert data-testid=\"new-location-address-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['addresses']) \">\r\n\r\n {{validatorsService.getError(form.controls['addresses']) | translate}}\r\n </ngb-alert>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Construction year' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"constructionYear\"\r\n data-testid=\"new-location-constructionYear\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['constructionYear']) || isFormError(form.controls['constructionYear'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-constructionYear-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['constructionYear']) || isFormError(form.controls['constructionYear'])\">\r\n {{validatorsService.getError(form.controls['constructionYear']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Latitude' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"latitude\" data-testid=\"new-location-latitude\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['latitude'])|| isFormError(form.controls['latitude'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-latitude-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['latitude']) || isFormError(form.controls['latitude'])\">\r\n {{validatorsService.getError(form.controls['latitude']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Longitude' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"longitude\" data-testid=\"new-location-longitude\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['longitude'])|| isFormError(form.controls['longitude'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-longitude-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['longitude']) || isFormError(form.controls['longitude'])\">\r\n {{validatorsService.getError(form.controls['longitude']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Access level' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <select class=\"d-inline-block custom-select rounded-pill\" formControlName=\"level\">\r\n <option *ngFor=\"let level of levels\" [value]=\"level\">{{level | translate}}</option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Energy Class' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"classEnergyConsumption\"\r\n data-testid=\"new-location-classEnergyConsumption\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['classEnergyConsumption']) || isFormError(form.controls['classEnergyConsumption'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-classEnergyConsumption-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['classEnergyConsumption']) || isFormError(form.controls['classEnergyConsumption'])\">\r\n {{validatorsService.getError(form.controls['classEnergyConsumption']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Greenhouse gas emission Class' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"classGes\" data-testid=\"new-location-classGes\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['classGes'])|| isFormError(form.controls['classGes'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-classGes-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['classGes']) || isFormError(form.controls['classGes'])\">\r\n {{validatorsService.getError(form.controls['classGes']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Cover picture' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <img #imageBasePreview *ngIf=\"currentImage\" class=\"image-preview\" [src]=\"currentImage\">\r\n <label #imageInputContainer for=\"image\"\r\n class=\"btn btn-label-file btn-outline-primary rounded-pill imageInputContainer\">\r\n <input #imageInput type=\"file\" id=\"image\" (change)=\"handleImageInput($event.target)\" />\r\n {{ imageInputText | translate}}</label>\r\n <button *ngIf=\"currentImage && !imageToUpload\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"imageToBeDeleted=true;clearImageFile()\">{{'Delete picture' | translate }}</button>\r\n <div class=\"image-name\" *ngIf=\"imageToUpload\">\r\n <p>{{ imageToUpload.name}}</p>\r\n <div (click)=\"clearImageFile()\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!location\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Create mission for this space' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input type=\"checkbox\" [(ngModel)]=\"addMissionForNewSpace\" [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <button data-testid=\"new-location-submit-btn\" [ngClass]=\"{'is-invalid' : errorForm }\" type=\"submit\"\r\n class=\"btn btn-outline-primary rounded-pill me-3\">{{'Save' | translate}}</button>\r\n\r\n <button data-testid=\"new-location-close-btn\" type=\"button\" (click)=\"onCancel()\"\r\n class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n\r\n </ngb-alert>\r\n </div>\r\n </form>\r\n</div>", styles: ["input[type=file]{display:none}.custom-select{border-color:var(--smarterplan-primary);width:auto}.form-new-loc{background-color:#d3d3d3;padding-top:10px;padding-bottom:10px;margin-bottom:15px}.btn-outline-primary{background-color:#fff}h4{color:var(--smarterplan-primary)}.image-preview{object-fit:cover;max-height:400px;max-width:400px;display:flex;margin-bottom:15px}.imageInputContainer{width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content}.image-name{display:flex}.col-form-label{margin-bottom:1rem;width:230px}.form-new-loc{background-color:#d3d3d3;margin-bottom:15px;padding:10px;width:80%;border-radius:10px}.col-sm-9 select{width:100%;height:31.25px;padding-left:10px}.btn-outline-primary{width:200px;margin-bottom:1rem;margin-right:1rem}.is-invalid,.btn-outline-primary.is-invalid{border-color:red!important}\n"], dependencies: [{ kind: "component", type: i4$1.NgbAlert, selector: "ngb-alert", inputs: ["animation", "dismissible", "type"], outputs: ["closed"], exportAs: ["ngbAlert"] }, { 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.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
439
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FormLocationComponent, decorators: [{
440
- type: Component,
441
- args: [{ selector: 'lib-form-location', template: "<div class=\"col-md-6 form-new-loc\" *ngIf=\"form\">\r\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" data-testid=\"new-location-name\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['name'])|| isFormError(form.controls['name'])}\"\r\n required formControlName=\"name\">\r\n\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" *ngIf=\"validatorsService.isControlError(form.controls['name']) \r\n || isFormError(form.controls['name'])\">\r\n {{validatorsService.getError(form.controls['name']) | translate}}\r\n </ngb-alert>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Address' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"addresses\" data-testid=\"new-location-address\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['addresses']) || isFormError(form.controls['addresses'])}\">\r\n <div class=\"invalid-feedback\">\r\n <span data-testid=\"\" [translate]=\"validatorsService.getError(form.controls['addresses'])\"\r\n *ngIf=\" validatorsService.isControlError(form.controls['addresses'])\"></span>\r\n\r\n <ngb-alert data-testid=\"new-location-address-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['addresses']) \">\r\n\r\n {{validatorsService.getError(form.controls['addresses']) | translate}}\r\n </ngb-alert>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Construction year' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"constructionYear\"\r\n data-testid=\"new-location-constructionYear\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['constructionYear']) || isFormError(form.controls['constructionYear'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-constructionYear-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['constructionYear']) || isFormError(form.controls['constructionYear'])\">\r\n {{validatorsService.getError(form.controls['constructionYear']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Latitude' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"latitude\" data-testid=\"new-location-latitude\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['latitude'])|| isFormError(form.controls['latitude'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-latitude-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['latitude']) || isFormError(form.controls['latitude'])\">\r\n {{validatorsService.getError(form.controls['latitude']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Longitude' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"longitude\" data-testid=\"new-location-longitude\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['longitude'])|| isFormError(form.controls['longitude'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-longitude-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['longitude']) || isFormError(form.controls['longitude'])\">\r\n {{validatorsService.getError(form.controls['longitude']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Access level' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <select class=\"d-inline-block custom-select rounded-pill\" formControlName=\"level\">\r\n <option *ngFor=\"let level of levels\" [value]=\"level\">{{level | translate}}</option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Energy Class' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"classEnergyConsumption\"\r\n data-testid=\"new-location-classEnergyConsumption\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['classEnergyConsumption']) || isFormError(form.controls['classEnergyConsumption'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-classEnergyConsumption-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['classEnergyConsumption']) || isFormError(form.controls['classEnergyConsumption'])\">\r\n {{validatorsService.getError(form.controls['classEnergyConsumption']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Greenhouse gas emission Class' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"classGes\" data-testid=\"new-location-classGes\" (ngModelChange)=\"onFormChange()\"\r\n [ngClass]=\"{'is-invalid' : validatorsService.isControlError(form.controls['classGes'])|| isFormError(form.controls['classGes'])}\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-classGes-invalid\" [dismissible]=\"false\" type=\"danger\"\r\n *ngIf=\"validatorsService.isControlError(form.controls['classGes']) || isFormError(form.controls['classGes'])\">\r\n {{validatorsService.getError(form.controls['classGes']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Cover picture' | translate}}</label>\r\n <div class=\"col-sm-9\">\r\n <img #imageBasePreview *ngIf=\"currentImage\" class=\"image-preview\" [src]=\"currentImage\">\r\n <label #imageInputContainer for=\"image\"\r\n class=\"btn btn-label-file btn-outline-primary rounded-pill imageInputContainer\">\r\n <input #imageInput type=\"file\" id=\"image\" (change)=\"handleImageInput($event.target)\" />\r\n {{ imageInputText | translate}}</label>\r\n <button *ngIf=\"currentImage && !imageToUpload\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"imageToBeDeleted=true;clearImageFile()\">{{'Delete picture' | translate }}</button>\r\n <div class=\"image-name\" *ngIf=\"imageToUpload\">\r\n <p>{{ imageToUpload.name}}</p>\r\n <div (click)=\"clearImageFile()\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!location\">\r\n <label class=\"col-sm-3 col-form-label\">{{'Create mission for this space' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input type=\"checkbox\" [(ngModel)]=\"addMissionForNewSpace\" [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <button data-testid=\"new-location-submit-btn\" [ngClass]=\"{'is-invalid' : errorForm }\" type=\"submit\"\r\n class=\"btn btn-outline-primary rounded-pill me-3\">{{'Save' | translate}}</button>\r\n\r\n <button data-testid=\"new-location-close-btn\" type=\"button\" (click)=\"onCancel()\"\r\n class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n\r\n </ngb-alert>\r\n </div>\r\n </form>\r\n</div>", styles: ["input[type=file]{display:none}.custom-select{border-color:var(--smarterplan-primary);width:auto}.form-new-loc{background-color:#d3d3d3;padding-top:10px;padding-bottom:10px;margin-bottom:15px}.btn-outline-primary{background-color:#fff}h4{color:var(--smarterplan-primary)}.image-preview{object-fit:cover;max-height:400px;max-width:400px;display:flex;margin-bottom:15px}.imageInputContainer{width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content}.image-name{display:flex}.col-form-label{margin-bottom:1rem;width:230px}.form-new-loc{background-color:#d3d3d3;margin-bottom:15px;padding:10px;width:80%;border-radius:10px}.col-sm-9 select{width:100%;height:31.25px;padding-left:10px}.btn-outline-primary{width:200px;margin-bottom:1rem;margin-right:1rem}.is-invalid,.btn-outline-primary.is-invalid{border-color:red!important}\n"] }]
442
- }], ctorParameters: function () { return [{ type: i2.SpaceService }, { type: i2.PropertyService }, { type: i2.BaseUserService }, { type: i1$2.UntypedFormBuilder }, { type: i2.MissionService }, { type: i2.LayerService }, { type: i2.ValidatorsService }]; }, propDecorators: { imageInputContainer: [{
443
- type: ViewChild,
444
- args: ["imageInputContainer"]
445
- }], imageInput: [{
446
- type: ViewChild,
447
- args: ["imageInput"]
448
- }], imageBasePreview: [{
449
- type: ViewChild,
450
- args: ["imageBasePreview"]
451
- }], location: [{
452
- type: Input
453
- }], onChange: [{
454
- type: Output
455
- }] } });
456
-
457
- class LocationsComponent {
458
- constructor(spaceService, router, userService, viewerService, navigationService, navigatorService) {
459
- this.spaceService = spaceService;
460
- this.router = router;
461
- this.userService = userService;
462
- this.viewerService = viewerService;
463
- this.navigationService = navigationService;
464
- this.navigatorService = navigatorService;
465
- this.isAdding = false;
466
- this.filteredLocations = [];
467
- this.isManager = false;
468
- this.isMuseumUser = true;
469
- this.locations = [];
470
- this.menuItems = [];
471
- /** Last filtered Locations, used when we go back on all locations from the search bar location */
472
- this.lastFiltredLocations = [];
473
- this.levels = enumToArray(LevelStatus);
474
- this.userSubcription = this.userService.isChanged.subscribe((isConnected) => {
475
- if (isConnected) {
476
- this.refresh();
477
- }
478
- });
479
- this.locationIDSubscription =
480
- this.navigatorService.locationIDChange.subscribe((id) => {
481
- this.changeSelectedLocation(id);
482
- this.setupMenuItems();
483
- });
484
- }
485
- ngOnInit() {
486
- return __awaiter(this, void 0, void 0, function* () {
487
- if (this.userService.cu) {
488
- this.resetList();
489
- this.updateUserRights();
490
- }
491
- this.setupMenuItems();
492
- });
493
- }
494
- findSpaceById(id) {
495
- return this.locations.find((loc) => loc.id === id);
496
- }
497
- /**
498
- * Update when we change the selected location in filter (search bar)
499
- * @param id for a location, if null display all last filtred location
500
- */
501
- changeSelectedLocation(id) {
502
- const space = id ? this.findSpaceById(id) : null;
503
- this.filteredLocations = space ? [space] : this.lastFiltredLocations; // New selected space or last filtered location
504
- }
505
- refresh() {
506
- this.updateUserRights();
507
- this.resetList();
508
- }
509
- ngOnDestroy() {
510
- this.userSubcription.unsubscribe();
511
- this.locationIDSubscription.unsubscribe();
512
- }
513
- setupMenuItems() {
514
- this.menuItems = [{ label: "All Locations", url: "/localisation" }];
515
- if (this.isAdding) {
516
- this.menuItems.push({ label: "New" });
517
- }
518
- if (this.filteredLocations.length === 1) {
519
- const selectedLoc = this.filteredLocations[0];
520
- this.menuItems.push({ label: selectedLoc.name });
521
- }
522
- }
523
- updateUserRights() {
524
- this.isManager = this.userService.hasManagerRoleInAnyMission();
525
- this.isMuseumUser = this.userService.hasOnlyMuseumRole();
526
- }
527
- isManagerForSpace(spaceID) {
528
- return (this.userService.isManager(spaceID) ||
529
- this.userService.isGuide(spaceID));
530
- }
531
- resetList() {
532
- return __awaiter(this, void 0, void 0, function* () {
533
- this.locations = yield this.spaceService.getLocationsForCurrentUser();
534
- this.filteredLocations = this.locations;
535
- this.lastFiltredLocations = this.locations;
536
- this.isAdding = false;
537
- this.changeSelectedLocation(this.navigatorService.currentNavBarLocationID); // Set for the current selected location
538
- this.setupMenuItems();
539
- });
540
- }
541
- onAddLocation() {
542
- this.isAdding = true;
543
- this.setupMenuItems();
544
- }
545
- handleImageInput(files) {
546
- this.imageToUpload = files.item(0);
547
- }
548
- onFormChange(event) {
549
- this.navigatorService.locationIDChange.next(null); /** Remove selected location */
550
- this.isAdding = false;
551
- if (event) {
552
- this.resetList();
553
- }
554
- this.setupMenuItems();
555
- }
556
- onVisitClick(loc, visit) {
557
- return __awaiter(this, void 0, void 0, function* () {
558
- if (!this.userService.userHasAccessToAllZonesInSpace(loc.id)) {
559
- // get allowed sweep for the user
560
- const allowedSweeps = yield this.navigationService.getAllowedSweepsIDsForUserInSpace(loc.id);
561
- const firstSweep = allowedSweeps[0];
562
- this.viewerService.setSweepToMove(firstSweep);
563
- }
564
- if (this.userService.isGuide(loc.id)) {
565
- this.router.navigate(["museum", loc.id]);
566
- }
567
- else {
568
- this.router.navigate(["visit", loc.id], {
569
- queryParams: { model3D: visit.model3d },
570
- });
571
- }
572
- });
573
- }
574
- applyResultsSearchBar(results) {
575
- this.filteredLocations = results || this.locations;
576
- this.lastFiltredLocations = this.filteredLocations;
577
- this.navigatorService.locationIDChange.next(null); // When we search with keyword, we would like to search on all locations
578
- }
579
- getSearchType() {
580
- return SearchObjectType.LOCATION;
581
- }
582
- getStringNoSpace(data) {
583
- return data.replace(/\s/g, '');
584
- }
585
- onDetailViewClick(spaceID) {
586
- this.navigatorService.locationIDChange.next(spaceID); // Send update for the location filter bar
587
- this.router.navigate(["dashboard/localisation", spaceID]);
588
- }
589
- }
590
- LocationsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocationsComponent, deps: [{ token: i2.SpaceService }, { token: i1.Router }, { token: i2.BaseUserService }, { token: i2.ViewerService }, { token: i2.NavigationService }, { token: i2.NavigatorService }], target: i0.ɵɵFactoryTarget.Component });
591
- LocationsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: LocationsComponent, selector: "lib-locations", ngImport: i0, template: "<div class=\"dashboard-tab\">\r\n <div class=\"header-dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation (onGoBack)=\"onFormChange(null)\" [menuItems]='menuItems'></lib-tab-navigation>\r\n <span class=\"ml-3 refreshIcon\" (click)=\"refresh()\" *ngIf=\"!(isAdding)\" ngbTooltip=\"Refresh list\">\r\n <span class=\"iconify refreshIcon\" data-icon=\"ion:refresh-circle\" data-width=\"35\" data-rotate=\"90deg\"></span>\r\n </span>\r\n </div> \r\n <lib-search-bar *ngIf=\"!isAdding && !isMuseumUser\" [searchable]=\"locations\" [objectType]=\"getSearchType()\"\r\n (searchEvent)=\"applyResultsSearchBar($event)\"></lib-search-bar>\r\n \r\n <div class=\"col-md-8\">\r\n <div class=\"sp-row\" *ngIf=\"!isAdding && isManager\">\r\n <button data-testid=\"new-location-btn\" class=\"btn btn-outline-primary rounded-pill add-location\" (click)=\"onAddLocation()\">\r\n {{'Add location' | translate}}</button>\r\n <!-- <div class=\"outer_circle\">\r\n <button id='btn-icon' (click)=\"onAddLocation()\"></button>\r\n </div> -->\r\n </div>\r\n </div>\r\n </div>\r\n <hr>\r\n <div class=\"row\" *ngIf=\"isAdding\">\r\n <div class=\"col-md-6\">\r\n <h4>{{'New location' | translate}}</h4>\r\n </div>\r\n </div>\r\n <section *ngIf=\"!isAdding\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-12 col-md-12 col-lg-6\" *ngIf=\"filteredLocations\">\r\n <ul data-testid=\"location-list-container\" class=\"list-group list-group-flush\">\r\n <li class=\"d-flex justify-content-between list-group-item\"\r\n *ngFor=\"let loc of filteredLocations; index as index\">\r\n <div class=\"d-flex\">\r\n <div class=\"col-md-5 img-main-container\">\r\n <div id=\"img_container\">\r\n <img class=\"location-img\" *ngIf=\"loc.annexes; else elseBlock\" [src]=\"loc.annexes\">\r\n <ng-template #elseBlock><img class=\"location-img\"\r\n src=\"./../../../../assets/images/visuel-off-big.jpg\" />\r\n </ng-template>\r\n <button [ngClass]=\"['open-btn-'+getStringNoSpace(loc.name)]\" *ngIf=\"isManagerForSpace(loc.id)\" class=\"btn-details\" (click)=\"onDetailViewClick(loc.id)\">\r\n {{'View details' | translate}}</button>\r\n </div>\r\n \r\n </div>\r\n <div class=\"col-md-7 location-info\">\r\n <p>{{loc.name}}</p>\r\n <p>{{loc.addresses}}</p>\r\n <p [ngClass]=\"['view-btn-'+getStringNoSpace(loc.name)]\" *ngFor=\"let visit of loc.visits\" (click)=\"onVisitClick(loc, visit)\" class=\"visit-name\"\r\n [style.cursor]=\"'pointer'\" ngbTooltip=\"Visit\">{{ visit.name ? visit.name : loc.name}}</p>\r\n </div>\r\n </div>\r\n </li>\r\n \r\n </ul>\r\n </div>\r\n <div class=\"col-sm-12 col-md-12 col-lg-6\">\r\n <lib-map [spaces]=\"filteredLocations\"></lib-map>\r\n </div>\r\n </div>\r\n </section>\r\n <lib-form-location *ngIf=\"isAdding\" (onChange)=\"onFormChange($event)\"></lib-form-location>\r\n</div>\r\n", styles: [".searchbar{margin-bottom:10px}input[type=file]{display:none}.form-control{border-radius:var(--form-control-border-radius)}.custom-select{border-color:var(--smarterplan-primary);width:auto}.form-new-loc{background-color:#d3d3d3;padding-top:10px;padding-bottom:10px;margin-bottom:15px}.btn-outline-primary{background-color:#fff}h4{color:var(--smarterplan-primary)}section .list-group{margin-top:15px}section .list-group-item{padding:5px 0}section .location-info{font-size:1.1em}section .location-img{width:100%;object-fit:cover;object-position:center bottom;height:165px}#img_container{position:relative;display:inline-block;text-align:center;width:250px}.img-main-container{max-width:250px;width:250px!important;margin-right:10px}.visit-name{color:var(--smarterplan-primary);font-weight:600}.btn-details{background-color:var(--smarterplan-primary-transparent);position:absolute;color:#fff;bottom:0;right:0;width:100%;height:30%;border:none;font-size:1em;text-transform:lowercase}#btn-icon{width:30px;height:30px;background:url(../../../../assets/icons/plus.svg);border:none;vertical-align:middle}#btn-icon:hover{background:url(../../../../assets/icons/plus-over.svg)}#btn-icon[disabled]:hover{background:url(../../../../assets/icons/plus.svg)}.outer_circle{background-color:#ebebeb;border-radius:50%;width:32px;height:32px;padding:1px;margin-left:5px}.refreshIcon{color:var(--smarterplan-primary);cursor:pointer}.refreshIcon svg{vertical-align:middle!important}.add-location{width:-moz-fit-content;width:fit-content}.sp-row{display:flex;flex-direction:row}\n"], dependencies: [{ kind: "directive", type: i4$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { 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: i2.SearchBarComponent, selector: "lib-search-bar", inputs: ["searchable", "objectType"], outputs: ["searchEvent"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: MapComponent, selector: "lib-map", inputs: ["spaces"] }, { kind: "component", type: FormLocationComponent, selector: "lib-form-location", inputs: ["location"], outputs: ["onChange"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocationsComponent, decorators: [{
593
- type: Component,
594
- args: [{ selector: 'lib-locations', template: "<div class=\"dashboard-tab\">\r\n <div class=\"header-dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation (onGoBack)=\"onFormChange(null)\" [menuItems]='menuItems'></lib-tab-navigation>\r\n <span class=\"ml-3 refreshIcon\" (click)=\"refresh()\" *ngIf=\"!(isAdding)\" ngbTooltip=\"Refresh list\">\r\n <span class=\"iconify refreshIcon\" data-icon=\"ion:refresh-circle\" data-width=\"35\" data-rotate=\"90deg\"></span>\r\n </span>\r\n </div> \r\n <lib-search-bar *ngIf=\"!isAdding && !isMuseumUser\" [searchable]=\"locations\" [objectType]=\"getSearchType()\"\r\n (searchEvent)=\"applyResultsSearchBar($event)\"></lib-search-bar>\r\n \r\n <div class=\"col-md-8\">\r\n <div class=\"sp-row\" *ngIf=\"!isAdding && isManager\">\r\n <button data-testid=\"new-location-btn\" class=\"btn btn-outline-primary rounded-pill add-location\" (click)=\"onAddLocation()\">\r\n {{'Add location' | translate}}</button>\r\n <!-- <div class=\"outer_circle\">\r\n <button id='btn-icon' (click)=\"onAddLocation()\"></button>\r\n </div> -->\r\n </div>\r\n </div>\r\n </div>\r\n <hr>\r\n <div class=\"row\" *ngIf=\"isAdding\">\r\n <div class=\"col-md-6\">\r\n <h4>{{'New location' | translate}}</h4>\r\n </div>\r\n </div>\r\n <section *ngIf=\"!isAdding\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-12 col-md-12 col-lg-6\" *ngIf=\"filteredLocations\">\r\n <ul data-testid=\"location-list-container\" class=\"list-group list-group-flush\">\r\n <li class=\"d-flex justify-content-between list-group-item\"\r\n *ngFor=\"let loc of filteredLocations; index as index\">\r\n <div class=\"d-flex\">\r\n <div class=\"col-md-5 img-main-container\">\r\n <div id=\"img_container\">\r\n <img class=\"location-img\" *ngIf=\"loc.annexes; else elseBlock\" [src]=\"loc.annexes\">\r\n <ng-template #elseBlock><img class=\"location-img\"\r\n src=\"./../../../../assets/images/visuel-off-big.jpg\" />\r\n </ng-template>\r\n <button [ngClass]=\"['open-btn-'+getStringNoSpace(loc.name)]\" *ngIf=\"isManagerForSpace(loc.id)\" class=\"btn-details\" (click)=\"onDetailViewClick(loc.id)\">\r\n {{'View details' | translate}}</button>\r\n </div>\r\n \r\n </div>\r\n <div class=\"col-md-7 location-info\">\r\n <p>{{loc.name}}</p>\r\n <p>{{loc.addresses}}</p>\r\n <p [ngClass]=\"['view-btn-'+getStringNoSpace(loc.name)]\" *ngFor=\"let visit of loc.visits\" (click)=\"onVisitClick(loc, visit)\" class=\"visit-name\"\r\n [style.cursor]=\"'pointer'\" ngbTooltip=\"Visit\">{{ visit.name ? visit.name : loc.name}}</p>\r\n </div>\r\n </div>\r\n </li>\r\n \r\n </ul>\r\n </div>\r\n <div class=\"col-sm-12 col-md-12 col-lg-6\">\r\n <lib-map [spaces]=\"filteredLocations\"></lib-map>\r\n </div>\r\n </div>\r\n </section>\r\n <lib-form-location *ngIf=\"isAdding\" (onChange)=\"onFormChange($event)\"></lib-form-location>\r\n</div>\r\n", styles: [".searchbar{margin-bottom:10px}input[type=file]{display:none}.form-control{border-radius:var(--form-control-border-radius)}.custom-select{border-color:var(--smarterplan-primary);width:auto}.form-new-loc{background-color:#d3d3d3;padding-top:10px;padding-bottom:10px;margin-bottom:15px}.btn-outline-primary{background-color:#fff}h4{color:var(--smarterplan-primary)}section .list-group{margin-top:15px}section .list-group-item{padding:5px 0}section .location-info{font-size:1.1em}section .location-img{width:100%;object-fit:cover;object-position:center bottom;height:165px}#img_container{position:relative;display:inline-block;text-align:center;width:250px}.img-main-container{max-width:250px;width:250px!important;margin-right:10px}.visit-name{color:var(--smarterplan-primary);font-weight:600}.btn-details{background-color:var(--smarterplan-primary-transparent);position:absolute;color:#fff;bottom:0;right:0;width:100%;height:30%;border:none;font-size:1em;text-transform:lowercase}#btn-icon{width:30px;height:30px;background:url(../../../../assets/icons/plus.svg);border:none;vertical-align:middle}#btn-icon:hover{background:url(../../../../assets/icons/plus-over.svg)}#btn-icon[disabled]:hover{background:url(../../../../assets/icons/plus.svg)}.outer_circle{background-color:#ebebeb;border-radius:50%;width:32px;height:32px;padding:1px;margin-left:5px}.refreshIcon{color:var(--smarterplan-primary);cursor:pointer}.refreshIcon svg{vertical-align:middle!important}.add-location{width:-moz-fit-content;width:fit-content}.sp-row{display:flex;flex-direction:row}\n"] }]
595
- }], ctorParameters: function () { return [{ type: i2.SpaceService }, { type: i1.Router }, { type: i2.BaseUserService }, { type: i2.ViewerService }, { type: i2.NavigationService }, { type: i2.NavigatorService }]; } });
596
-
597
- class DetailLocationComponent {
598
- constructor(route, spaceService, router, userService, translate, navigatorService) {
599
- this.route = route;
600
- this.spaceService = spaceService;
601
- this.router = router;
602
- this.userService = userService;
603
- this.translate = translate;
604
- this.navigatorService = navigatorService;
605
- this.isEditing = false;
606
- this.menuItems = [];
607
- this.isValidatingDpe = false;
608
- this.gettingData = false;
609
- this.destroy$ = new Subject();
610
- this.navigatorService.locationIDChange
611
- .pipe(takeUntil(this.destroy$))
612
- .subscribe((spaceID) => {
613
- this.router.navigate(["dashboard/localisation", spaceID]);
614
- });
615
- this.route.params.subscribe((params) => {
616
- this.id = params.id;
617
- this.setup();
618
- });
619
- }
620
- ngOnInit() { }
621
- setup() {
622
- return __awaiter(this, void 0, void 0, function* () {
623
- this.space = yield this.spaceService.getSpace(this.id);
624
- this.setupMenuItems();
625
- this.setGuestLink();
626
- this.setCanArchive();
627
- });
628
- }
629
- ngOnDestroy() {
630
- this.destroy$.next(true);
631
- this.destroy$.complete();
632
- }
633
- setupMenuItems() {
634
- this.menuItems = [
635
- { label: "Locations", url: "/localisation" },
636
- {
637
- label: this.space.name,
638
- url: `/localisation/${this.space.id}`,
639
- },
640
- ];
641
- if (this.isEditing) {
642
- this.menuItems.push({ label: "Edit" });
643
- }
644
- else {
645
- this.menuItems.push({ label: "Information" });
646
- }
647
- }
648
- onEdit() {
649
- this.isEditing = true;
650
- this.setupMenuItems();
651
- }
652
- onReturn() {
653
- // this.locationService.back()
654
- this.router.navigate(["dashboard/localisation"]);
655
- }
656
- reset() {
657
- this.isEditing = false;
658
- this.setupMenuItems();
659
- }
660
- onArchive() {
661
- return __awaiter(this, void 0, void 0, function* () {
662
- const message = this.translate.instant("confirm.archiveSpace");
663
- if (window.confirm(message)) {
664
- yield this.spaceService.softDeleteSpace(this.id);
665
- this.onReturn();
666
- }
667
- });
668
- }
669
- onFormChange(event) {
670
- this.isEditing = false;
671
- if (event) {
672
- this.space = event;
673
- }
674
- this.setupMenuItems();
675
- }
676
- onDpeValidate() {
677
- this.isValidatingDpe = true;
678
- this.parsedMetadata = JSON.parse(this.space.metadata);
679
- this.parsedMetadata = this.parsedMetadata.filter((result) => result.geo_adresse);
680
- }
681
- onSelectChange(selectedResult) {
682
- for (const result of this.parsedMetadata) {
683
- if (result !== selectedResult && result.selected) {
684
- result.selected = false;
685
- }
686
- }
687
- this.selectedDpeResult = selectedResult;
688
- }
689
- onSaveResult() {
690
- return __awaiter(this, void 0, void 0, function* () {
691
- if (this.selectedDpeResult) {
692
- const input = {
693
- id: this.space.id,
694
- constructionYear: this.selectedDpeResult.annee_construction,
695
- classEnergyConsumption: this.selectedDpeResult.classe_consommation_energie,
696
- classGes: this.selectedDpeResult.classe_estimation_ges,
697
- status: SpaceStatus.DPE_VALIDATED,
698
- };
699
- const updatedLoc = yield this.spaceService.updateSpace(input);
700
- this.space = updatedLoc;
701
- this.isValidatingDpe = false;
702
- }
703
- });
704
- }
705
- onCancel() {
706
- this.isValidatingDpe = false;
707
- }
708
- onErase() {
709
- return __awaiter(this, void 0, void 0, function* () {
710
- yield this.spaceService.updateSpace({
711
- id: this.space.id,
712
- status: SpaceStatus.DPE_VALIDATED,
713
- });
714
- this.space.status = SpaceStatus.DPE_VALIDATED;
715
- this.isValidatingDpe = false;
716
- });
717
- }
718
- onGetDpeData() {
719
- return __awaiter(this, void 0, void 0, function* () {
720
- this.gettingData = true;
721
- yield this.spaceService.updateSpace({
722
- id: this.space.id,
723
- status: SpaceStatus.DPE_FETCH,
724
- });
725
- // force update of location
726
- setTimeout(() => __awaiter(this, void 0, void 0, function* () {
727
- this.space = yield this.spaceService.getSpace(this.space.id);
728
- this.gettingData = false;
729
- }), 1500);
730
- });
731
- }
732
- setGuestLink() {
733
- if (this.space.guestLink) {
734
- const { origin } = document.location;
735
- this.guestLink = `${origin}/${this.space.guestLink}`;
736
- setTimeout(() => {
737
- const hyperlink = document.querySelector("#linkHref");
738
- const message = this.translate.instant("confirm.followLink");
739
- hyperlink.addEventListener("click", () => __awaiter(this, void 0, void 0, function* () {
740
- if (window.confirm(message)) {
741
- window.location.href = this.guestLink;
742
- yield this.userService.logoutCurrentAndSignOutAuth();
743
- this.router.navigate(["auth"]);
744
- }
745
- }));
746
- }, 0);
747
- }
748
- }
749
- setCanArchive() {
750
- return __awaiter(this, void 0, void 0, function* () {
751
- this.canArchive = this.userService.isSPAdmin()
752
- ? true
753
- : yield this.spaceService.canArchiveSpace(this.id);
754
- });
755
- }
756
- }
757
- DetailLocationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DetailLocationComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.SpaceService }, { token: i1.Router }, { token: i2.BaseUserService }, { token: i3.TranslateService }, { token: i2.NavigatorService }], target: i0.ɵɵFactoryTarget.Component });
758
- DetailLocationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DetailLocationComponent, selector: "lib-detail-location", ngImport: i0, template: "<div class=\"container-fluid\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"reset()\"></lib-tab-navigation>\r\n </div>\r\n <button class=\"btn btn-outline-primary rounded-pill me-3\" (click)=\"onReturn()\">{{'Back to locations' |\r\n translate}}</button>\r\n <div class=\"row\" *ngIf=\"!isEditing && space\">\r\n <div class=\"col-md-5\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}}: {{space.name}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Address' | translate}}: {{space.addresses}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Construction year' | translate}}:\r\n {{space.constructionYear ?\r\n space.constructionYear : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Latitude' | translate}}:\r\n {{space.latitude ?\r\n space.latitude : \"No data\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Longitude' | translate}}: {{space.longitude ?\r\n space.longitude : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Access level' | translate}}: {{space.level | translate\r\n }} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Energy Class' | translate}}:\r\n {{space.classEnergyConsumption ?\r\n space.classEnergyConsumption : \"No data\" | translate}}\r\n <button *ngIf=\"space.status !== 'DPE_TO_VALIDATE'\"\r\n class=\"btn btn-outline-primary rounded-pill no-lowercase ms-5\" (click)=\"onGetDpeData()\">\r\n {{'Get data from API DPE' | translate}}</button>\r\n <a class=\"bg-transparent ms-5\" *ngIf=\"space.status === 'DPE_TO_VALIDATE'\" (click)=\"onDpeValidate()\"\r\n style=\"cursor: pointer;\">\r\n <span class=\"iconify\" data-icon=\"mdi:alert-circle-check\" style=\"color: #f19c80;\" data-width=\"25\"\r\n data-height=\"25\"></span>\r\n {{'DPE data found. Click to validate' | translate}}\r\n </a>\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Greenhouse gas emission Class' | translate}}:\r\n {{space.classGes ? space.classGes : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Shareable Guest Link' | translate}}:\r\n <div style=\"display: inline;\" *ngIf=\"guestLink\">\r\n <a id=\"linkHref\" target=\"_blank\">{{'Try the link' | translate }}</a>\r\n <div [cdkCopyToClipboard]=\"guestLink\" [style.cursor]=\"'pointer'\"\r\n style=\"margin-left: 5px; max-width: 20px; display: inline;\" ngbTooltip=\"Copied!\"\r\n triggers=\"click:blur\">\r\n <span class=\"iconify\" data-icon=\"mdi:content-copy\" data-inline=\"false\" data-width=\"20\"\r\n data-height=\"20\"></span>\r\n </div>\r\n </div>\r\n <p *ngIf=\"!guestLink\" style=\"display: inline;\">{{'No link' | translate }}</p>\r\n <p *ngIf=\"!guestLink\"><small>({{'Generate link from a VISITOR mission'|translate}})</small>\r\n </p>\r\n </li>\r\n\r\n </ul>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"gettingData\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <hr>\r\n <div class=\"d-flex\">\r\n <button class=\"btn btn-outline-primary rounded-pill me-3\" (click)=\"onEdit()\"\r\n data-testid=\"location-edit-btn\">{{'Edit' |\r\n translate}}</button>\r\n <div class=\"tooltip-wrapper\"\r\n ngbTooltip=\"{{!canArchive ? ('Contact SmarterPlan' | translate) : ('Archive location and related data' | translate)}}\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onArchive()\" [disabled]=\"!canArchive\">\r\n {{'Archive' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n\r\n </div>\r\n <div class=\"col-md-7\" *ngIf=\"isValidatingDpe\">\r\n <h6>{{'Most relevant results for' | translate}} :\r\n <b>diagnostics de performance \u00E9nerg\u00E9tique (DPE) des b\u00E2timents tertiaires</b>\r\n </h6>\r\n <table class=\"table table-striped\">\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">#</th>\r\n <th scope=\"col\">{{'Apply to location' | translate}}</th>\r\n <th scope=\"col\">{{'Address' | translate}}</th>\r\n <th scope=\"col\">{{'Activity sector' | translate}}</th>\r\n <th scope=\"col\">{{'Construction year' | translate}}</th>\r\n <th scope=\"col\">{{'Energy Class' | translate}}</th>\r\n <th scope=\"col\">{{'Greenhouse gas emission Class' | translate}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let result of parsedMetadata; index as i\">\r\n <th scope=\"row\">{{ i + 1 }}</th>\r\n <td><input class=\"checkbox-apply\" type=\"checkbox\" [(ngModel)]=\"result.selected\"\r\n (change)=\"onSelectChange(result)\"></td>\r\n <td>{{result.geo_adresse}}</td>\r\n <td>{{result.secteur_activite}}</td>\r\n <td>{{ result.annee_construction }}</td>\r\n <td>{{ result.classe_consommation_energie }}</td>\r\n <td>{{ result.classe_estimation_ges }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onSaveResult()\"\r\n [disabled]=\"!selectedDpeResult\">{{'Save selected' |\r\n translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onErase()\">\r\n {{'No match (erase data)' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onCancel()\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </div>\r\n <lib-form-location *ngIf=\"isEditing\" [location]=\"space\" (onChange)=\"onFormChange($event)\"></lib-form-location>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i4$2.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "directive", type: i4$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { 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: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: FormLocationComponent, selector: "lib-form-location", inputs: ["location"], outputs: ["onChange"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
759
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DetailLocationComponent, decorators: [{
760
- type: Component,
761
- args: [{ selector: 'lib-detail-location', template: "<div class=\"container-fluid\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"reset()\"></lib-tab-navigation>\r\n </div>\r\n <button class=\"btn btn-outline-primary rounded-pill me-3\" (click)=\"onReturn()\">{{'Back to locations' |\r\n translate}}</button>\r\n <div class=\"row\" *ngIf=\"!isEditing && space\">\r\n <div class=\"col-md-5\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}}: {{space.name}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Address' | translate}}: {{space.addresses}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Construction year' | translate}}:\r\n {{space.constructionYear ?\r\n space.constructionYear : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Latitude' | translate}}:\r\n {{space.latitude ?\r\n space.latitude : \"No data\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Longitude' | translate}}: {{space.longitude ?\r\n space.longitude : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Access level' | translate}}: {{space.level | translate\r\n }} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Energy Class' | translate}}:\r\n {{space.classEnergyConsumption ?\r\n space.classEnergyConsumption : \"No data\" | translate}}\r\n <button *ngIf=\"space.status !== 'DPE_TO_VALIDATE'\"\r\n class=\"btn btn-outline-primary rounded-pill no-lowercase ms-5\" (click)=\"onGetDpeData()\">\r\n {{'Get data from API DPE' | translate}}</button>\r\n <a class=\"bg-transparent ms-5\" *ngIf=\"space.status === 'DPE_TO_VALIDATE'\" (click)=\"onDpeValidate()\"\r\n style=\"cursor: pointer;\">\r\n <span class=\"iconify\" data-icon=\"mdi:alert-circle-check\" style=\"color: #f19c80;\" data-width=\"25\"\r\n data-height=\"25\"></span>\r\n {{'DPE data found. Click to validate' | translate}}\r\n </a>\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Greenhouse gas emission Class' | translate}}:\r\n {{space.classGes ? space.classGes : \"No data\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Shareable Guest Link' | translate}}:\r\n <div style=\"display: inline;\" *ngIf=\"guestLink\">\r\n <a id=\"linkHref\" target=\"_blank\">{{'Try the link' | translate }}</a>\r\n <div [cdkCopyToClipboard]=\"guestLink\" [style.cursor]=\"'pointer'\"\r\n style=\"margin-left: 5px; max-width: 20px; display: inline;\" ngbTooltip=\"Copied!\"\r\n triggers=\"click:blur\">\r\n <span class=\"iconify\" data-icon=\"mdi:content-copy\" data-inline=\"false\" data-width=\"20\"\r\n data-height=\"20\"></span>\r\n </div>\r\n </div>\r\n <p *ngIf=\"!guestLink\" style=\"display: inline;\">{{'No link' | translate }}</p>\r\n <p *ngIf=\"!guestLink\"><small>({{'Generate link from a VISITOR mission'|translate}})</small>\r\n </p>\r\n </li>\r\n\r\n </ul>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"gettingData\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <hr>\r\n <div class=\"d-flex\">\r\n <button class=\"btn btn-outline-primary rounded-pill me-3\" (click)=\"onEdit()\"\r\n data-testid=\"location-edit-btn\">{{'Edit' |\r\n translate}}</button>\r\n <div class=\"tooltip-wrapper\"\r\n ngbTooltip=\"{{!canArchive ? ('Contact SmarterPlan' | translate) : ('Archive location and related data' | translate)}}\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onArchive()\" [disabled]=\"!canArchive\">\r\n {{'Archive' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n\r\n </div>\r\n <div class=\"col-md-7\" *ngIf=\"isValidatingDpe\">\r\n <h6>{{'Most relevant results for' | translate}} :\r\n <b>diagnostics de performance \u00E9nerg\u00E9tique (DPE) des b\u00E2timents tertiaires</b>\r\n </h6>\r\n <table class=\"table table-striped\">\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">#</th>\r\n <th scope=\"col\">{{'Apply to location' | translate}}</th>\r\n <th scope=\"col\">{{'Address' | translate}}</th>\r\n <th scope=\"col\">{{'Activity sector' | translate}}</th>\r\n <th scope=\"col\">{{'Construction year' | translate}}</th>\r\n <th scope=\"col\">{{'Energy Class' | translate}}</th>\r\n <th scope=\"col\">{{'Greenhouse gas emission Class' | translate}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let result of parsedMetadata; index as i\">\r\n <th scope=\"row\">{{ i + 1 }}</th>\r\n <td><input class=\"checkbox-apply\" type=\"checkbox\" [(ngModel)]=\"result.selected\"\r\n (change)=\"onSelectChange(result)\"></td>\r\n <td>{{result.geo_adresse}}</td>\r\n <td>{{result.secteur_activite}}</td>\r\n <td>{{ result.annee_construction }}</td>\r\n <td>{{ result.classe_consommation_energie }}</td>\r\n <td>{{ result.classe_estimation_ges }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onSaveResult()\"\r\n [disabled]=\"!selectedDpeResult\">{{'Save selected' |\r\n translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onErase()\">\r\n {{'No match (erase data)' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onCancel()\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </div>\r\n <lib-form-location *ngIf=\"isEditing\" [location]=\"space\" (onChange)=\"onFormChange($event)\"></lib-form-location>\r\n</div>" }]
762
- }], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i2.SpaceService }, { type: i1.Router }, { type: i2.BaseUserService }, { type: i3.TranslateService }, { type: i2.NavigatorService }]; } });
763
-
764
- class CalibrationComponent {
765
- constructor(matterportImportService, planService, route, router, zoneService, spaceService, navigationService, translate) {
766
- this.matterportImportService = matterportImportService;
767
- this.planService = planService;
768
- this.route = route;
769
- this.router = router;
770
- this.zoneService = zoneService;
771
- this.spaceService = spaceService;
772
- this.navigationService = navigationService;
773
- this.translate = translate;
774
- /** Item to display for the navbar */
775
- this.menuItems = [];
776
- /** Zoom ratio of the canvas/plan */
777
- this.canvasZoom = 0;
778
- /** Opacity for matterport iframe */
779
- this.opacity = 50;
780
- /** Current rotation for matterport, [0-360], matterport rotation is bind to input range */
781
- this.rotation = 180;
782
- /** Previous rotation, use to calculate the deltaRotation to rotate, when user change rotation value using range input */
783
- this.prevRotation = 180;
784
- /** True when the user is currently rotating with the input range, the matterport rotation events will be ignored */
785
- this.isRotatingRange = false;
786
- /** Rotating queue event to send to matterport */
787
- this.rotatingQueueEvent = [];
788
- /** True when Vertical symmetry is enabled */
789
- this.reflectV = false;
790
- /** True when Horizontal symmetry is enabled */
791
- this.reflectH = false;
792
- this.chosenPlanIsPdf = false;
793
- /** First Point in visit, used to determine the calibration */
794
- this.firstMarkVisit = { x: 0, y: 0 };
795
- /** Second Point in visit, used to determine the calibration */
796
- this.secondMarkVisit = { x: 0.5, y: 0.5 };
797
- /** Equivalent of 'firstMarkVisit' in canvas */
798
- this.firstMarkPlan = { x: 0, y: 0 };
799
- /** Equivalent of 'secondMarkVisit' in canvas */
800
- this.secondMarkPlan = { x: 0, y: 0 };
801
- /** Calibration result, (offsetX, offsetY, x, y) */
802
- this.calibrage = {};
803
- /** Is in preview mode (see scan result) */
804
- this.preview = false;
805
- /** Matterport is loading */
806
- this.loading = true;
807
- this.positions = [];
808
- this.floors = [];
809
- this.zoomCanBeChanged = false;
810
- }
811
- ngOnDestroy() {
812
- if (!this.loading) {
813
- this.matterportImportService.removeFrame();
814
- }
815
- }
816
- ngOnInit() {
817
- return __awaiter(this, void 0, void 0, function* () {
818
- this.spaceID = this.route.snapshot.queryParams.spaceID;
819
- this.currentSpace = yield this.spaceService.getSpace(this.spaceID);
820
- /** Menu nav bar */
821
- this.setupMenuItems();
822
- this.chosenPlan = this.planService.getChosenPlan();
823
- if (this.chosenPlan) {
824
- this.chosenPlanIsPdf = this.chosenPlan.annexe.includes('pdf');
825
- this.launchViewer();
826
- setTimeout(() => {
827
- this.configureCanvas().then(() => {
828
- this.panzoom = panzoom(this.canvas, {
829
- bounds: true,
830
- boundsPadding: 0,
831
- maxZoom: 2.5,
832
- minZoom: 0.1,
833
- initialZoom: 1,
834
- zoomSpeed: 0.02,
835
- });
836
- });
837
- }, 500);
838
- }
839
- else {
840
- this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
841
- }
842
- });
843
- }
844
- /** **********************************************************************************************
845
- * MENU NAV BAR
846
- *********************************************************************************************** */
847
- setupMenuItems() {
848
- this.menuItems = [
849
- { label: 'Locations', url: '/localisation' },
850
- {
851
- label: this.currentSpace.name,
852
- url: `/localisation/${this.spaceID}`,
853
- },
854
- {
855
- label: 'Plans',
856
- url: `/localisation/${this.currentSpace.id}/plans`,
857
- },
858
- {
859
- label: 'Calibration',
860
- url: `/localisation/${this.currentSpace.id}/plan-calibration?spaceID=${this.currentSpace.id}`,
861
- },
862
- ];
863
- }
864
- /** **********************************************************************************************
865
- * CANVAS
866
- *********************************************************************************************** */
867
- /** Display the plan */
868
- configureCanvas() {
869
- return __awaiter(this, void 0, void 0, function* () {
870
- /** Get canvas */
871
- if (!this.canvas) {
872
- const canvas = document.querySelector('#canvas');
873
- this.canvas = canvas;
874
- }
875
- if (!this.chosenPlanIsPdf) {
876
- const image = yield getMetaForImage(this.chosenPlan.filepath);
877
- /** Compute the new size for the canvas/matterport, base on the dimension of the plan, keeping the ratio */
878
- const size = this.getSizeForCanvas(image.width, image.height);
879
- /** Compute the plan zoom ratio (use for the calibration later) */
880
- this.canvasZoom = size.w / image.width;
881
- this.resizeView(size);
882
- /** Draw Plan on the canvas */
883
- this.drawImage(this.chosenPlan.filepath);
884
- }
885
- else {
886
- // TODO
887
- this.pdfToCanvas();
888
- }
889
- });
890
- }
891
- /** Update size of the canvas/matterport */
892
- resizeView(size) {
893
- this.canvasDiv.nativeElement.style.width = `${size.w}px`;
894
- this.canvasDiv.nativeElement.style.height = `${size.h}px`;
895
- this.canvas.style.width = `${size.w}px`;
896
- this.canvas.style.height = `${size.h}px`;
897
- this.canvas.width = size.w;
898
- this.canvas.height = size.h;
899
- this.canvasSize = size;
900
- }
901
- /** Draw something on the canvas */
902
- drawImage(url, x = 0, y = 0, icone = false) {
903
- const image = new Image();
904
- const size = this.canvasSize;
905
- const context = this.canvas.getContext('2d');
906
- /** Flip the context, for symmetry */
907
- // if (this.reflectV) {
908
- // context.translate(size.w, 0);
909
- // context.scale(-1, 1);
910
- // }
911
- // if (this.reflectH) {
912
- // context.translate(0, size.h);
913
- // context.scale(1, -1);
914
- // }
915
- let imageWidth = size.w;
916
- let imageHeight = size.h;
917
- image.addEventListener('load', () => {
918
- if (icone) {
919
- imageWidth = image.width;
920
- imageHeight = image.height;
921
- }
922
- context.drawImage(image, 0, 0, image.width, image.height, x, y, imageWidth, imageHeight);
923
- });
924
- image.src = url;
925
- }
926
- /** Get the size for the canvas, based on the plan size, keeping the ratio */
927
- getSizeForCanvas(w, h) {
928
- let canvasW = this.canvasDiv.nativeElement.offsetWidth;
929
- let canvasH = this.canvasDiv.nativeElement.offsetHeight;
930
- const imageRatio = w / h;
931
- const canvasRatio = canvasW / canvasH;
932
- if (imageRatio > canvasRatio) {
933
- canvasH = canvasW / imageRatio;
934
- }
935
- else {
936
- canvasW = canvasH * imageRatio;
937
- }
938
- return { w: canvasW, h: canvasH };
939
- }
940
- /** [TODO] Convert a PDF to a Canvas */
941
- pdfToCanvas() {
942
- return __awaiter(this, void 0, void 0, function* () {
943
- const pdfjs = yield import('pdfjs-dist/build/pdf');
944
- const pdfjsWorker = yield import('pdfjs-dist/build/pdf.worker.entry');
945
- pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
946
- const pdf = yield getDocument(this.chosenPlan.filepath)
947
- .promise;
948
- const page = yield pdf.getPage(1);
949
- const viewPortParameters = { scale: 1 };
950
- const viewport = page.getViewport(viewPortParameters);
951
- this.canvas.height = viewport.height;
952
- this.canvas.width = viewport.width;
953
- const size = this.getSizeForCanvas(viewport.width, viewport.height);
954
- console.log(size);
955
- this.canvasSize = size;
956
- this.canvasZoom = size.w / viewport.width;
957
- const context = this.canvas.getContext('2d');
958
- const renderContext = {
959
- canvasContext: context,
960
- viewport,
961
- };
962
- const renderTask = page.render(renderContext).promise;
963
- renderTask.then(() => console.log('Page rendered'));
964
- // const res = canvas.toDataURL();
965
- // if (pdf != null) pdf.destroy();
966
- // return res;
967
- });
968
- }
969
- /** User click to user Symmetry Vertical */
970
- onReflectV() {
971
- this.reflectV = !this.reflectV;
972
- this.configureCanvas();
973
- }
974
- /** User click to user Symmetry Horizontal */
975
- onReflectH() {
976
- this.reflectH = !this.reflectH;
977
- this.configureCanvas();
978
- }
979
- /** **********************************************************************************************
980
- * MATTERPORT
981
- *********************************************************************************************** */
982
- /** Launch matterport */
983
- launchViewer() {
984
- return __awaiter(this, void 0, void 0, function* () {
985
- yield this.matterportImportService.initSdkForModel(this.chosenPlan.model3d);
986
- const { sdk } = this.matterportImportService;
987
- this.floors = Object.values(this.matterportImportService.floors);
988
- // console.log(this.floors);
989
- setTimeout(() => __awaiter(this, void 0, void 0, function* () {
990
- /** Move Floor mode */
991
- sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN).then((nextMode) => __awaiter(this, void 0, void 0, function* () {
992
- /** Display the correct floor for the plan */
993
- try {
994
- const matterportFloor = this.chosenPlan.zone.metadata ?
995
- JSON.parse(this.chosenPlan.zone.metadata).matterportFloorSequence : null;
996
- yield this.matterportImportService.moveToFloor(this.chosenPlan.zone.name, matterportFloor);
997
- /** When the user try to change the view mode we set it back to floorpan */
998
- sdk.on(sdk.Mode.Event.CHANGE_END, (oldMode, newMode) => {
999
- if (newMode !== sdk.Mode.Mode.FLOORPLAN) {
1000
- sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN, {
1001
- transition: 'transition.instant',
1002
- });
1003
- }
1004
- });
1005
- }
1006
- catch (_a) {
1007
- console.log('couldnot move to floor');
1008
- }
1009
- }));
1010
- /** We can display the matterport view now */
1011
- this.loading = false;
1012
- }), 1000);
1013
- /** Update current camera pose and rotation */
1014
- sdk.Camera.pose.subscribe((event) => {
1015
- /** We update only if the user is not changing the rotation with the <input> range, to not override the <input> value */
1016
- if (!this.isRotatingRange) {
1017
- this.rotation = event.rotation.y + 180;
1018
- this.prevRotation = this.rotation;
1019
- this.cameraPose = event;
1020
- }
1021
- });
1022
- });
1023
- }
1024
- /** When the <input> range, for rotation, change */
1025
- onRotationChange() {
1026
- return __awaiter(this, void 0, void 0, function* () {
1027
- const rotationDelta = this.rotation - this.prevRotation;
1028
- this.prevRotation = this.rotation;
1029
- /** Send the rotationDelta to th queue event in order to be send to matterport */
1030
- this.rotatingQueueEvent.push(rotationDelta);
1031
- /** Start to process the queue, if it's the first event */
1032
- if (!this.isRotatingRange) {
1033
- this.isRotatingRange = true;
1034
- this.processRotatingQueueEvent();
1035
- }
1036
- });
1037
- }
1038
- /** Process the rotating event queue, send event one by one to matterport */
1039
- processRotatingQueueEvent() {
1040
- return __awaiter(this, void 0, void 0, function* () {
1041
- const { sdk } = this.matterportImportService;
1042
- /** While the queue is not empty */
1043
- while (this.rotatingQueueEvent.length > 0) {
1044
- /** Rotate matterport by deltaRotation and remove event from queue */
1045
- yield sdk.Camera.rotate(this.rotatingQueueEvent.shift(), 0, {
1046
- speed: 360,
1047
- });
1048
- }
1049
- /** When the queue is empty, then the user is not rotating with the <input> range anymore */
1050
- this.isRotatingRange = false;
1051
- });
1052
- }
1053
- /** **********************************************************************************************
1054
- * USER ACTIONS
1055
- *********************************************************************************************** */
1056
- /** Preview calibration */
1057
- onPreview() {
1058
- return __awaiter(this, void 0, void 0, function* () {
1059
- this.preview = true;
1060
- /** Place sweeps */
1061
- this.onPlaceSweeps();
1062
- });
1063
- }
1064
- calibrate() {
1065
- return __awaiter(this, void 0, void 0, function* () {
1066
- const [navigation] = this.currentNavigations;
1067
- const position = JSON.parse(navigation.position);
1068
- this.firstMarkPlan =
1069
- yield this.matterportImportService.sdk.Renderer.getScreenPosition({
1070
- x: position.x,
1071
- y: position.y,
1072
- z: position.z,
1073
- });
1074
- this.secondMarkPlan =
1075
- yield this.matterportImportService.sdk.Renderer.getScreenPosition({
1076
- x: position.x,
1077
- y: 0,
1078
- z: 0,
1079
- });
1080
- const deltaZVisit = 0 - position.z;
1081
- let deltaXPlan = this.secondMarkPlan.x - this.firstMarkPlan.x;
1082
- if (deltaXPlan === 0) {
1083
- // console.log("we moved along Y axis on Plan");
1084
- const deltaYPlan = this.secondMarkPlan.y - this.firstMarkPlan.y;
1085
- this.calibrage.nameYAxis = 'z';
1086
- this.calibrage.nameXAxis = 'x';
1087
- this.calibrage.offsetY = this.secondMarkPlan.y;
1088
- this.calibrage.scaleY = deltaYPlan / deltaZVisit;
1089
- }
1090
- else {
1091
- // console.log(" we moved along X axis on Plan");
1092
- this.calibrage.nameYAxis = 'x';
1093
- this.calibrage.nameXAxis = 'z';
1094
- this.calibrage.offsetX = this.secondMarkPlan.x;
1095
- this.calibrage.scaleX = deltaXPlan / deltaZVisit;
1096
- }
1097
- const thirdMarkPlan = yield this.matterportImportService.sdk.Renderer.getScreenPosition({
1098
- x: 0,
1099
- y: 0,
1100
- z: position.z,
1101
- });
1102
- const deltaXVisit = 0 - position.x;
1103
- if (deltaXPlan === 0) {
1104
- // console.log(" we moved along X axis on Plan");
1105
- deltaXPlan = thirdMarkPlan.x - this.firstMarkPlan.x;
1106
- this.calibrage.offsetX = thirdMarkPlan.x;
1107
- this.calibrage.scaleX = deltaXPlan / deltaXVisit;
1108
- }
1109
- else {
1110
- const deltaYPlan = thirdMarkPlan.y - this.firstMarkPlan.y;
1111
- this.calibrage.offsetY = thirdMarkPlan.y;
1112
- this.calibrage.scaleY = deltaYPlan / deltaXVisit;
1113
- }
1114
- /** Take considiration of pan and zoom of plan on canvas */
1115
- const transformInfo = this.panzoom.getTransform();
1116
- const { scale, x, y } = transformInfo;
1117
- // console.log(transformInfo);
1118
- this.calibrage.offsetXPlan = x;
1119
- this.calibrage.offsetYPlan = y;
1120
- this.calibrage.scalePlan = scale;
1121
- console.log(this.calibrage);
1122
- });
1123
- }
1124
- /** Place sweeps */
1125
- onPlaceSweeps() {
1126
- return __awaiter(this, void 0, void 0, function* () {
1127
- /** Display all scan */
1128
- const zone = yield this.zoneService.getZone(this.chosenPlan.zoneID);
1129
- if (zone) {
1130
- this.currentZone = zone;
1131
- const navigations = yield this.navigationService.getNavigationsForZone(this.currentZone);
1132
- this.currentNavigations = navigations;
1133
- yield this.calibrate();
1134
- if (navigations.length > 0) {
1135
- for (const navigation of navigations) {
1136
- const testPosition = JSON.parse(navigation.position);
1137
- const positionX = this.calibrage.nameXAxis === 'x' ? testPosition.x : testPosition.z;
1138
- const positionY = this.calibrage.nameYAxis === 'x' ? testPosition.x : testPosition.z;
1139
- const testX = positionX * this.calibrage.scaleX + this.calibrage.offsetX;
1140
- const testY = positionY * this.calibrage.scaleY + this.calibrage.offsetY;
1141
- // console.log("test position GREEN", testX, testY);
1142
- const transformedX = (testX - this.calibrage.offsetXPlan) / this.calibrage.scalePlan; // we are undoing the pan and zoom
1143
- const transformedY = (testY - this.calibrage.offsetYPlan) / this.calibrage.scalePlan;
1144
- this.positions.push({
1145
- navID: navigation.id,
1146
- planID: this.chosenPlan.id,
1147
- x: transformedX,
1148
- y: transformedY,
1149
- });
1150
- const iconSize = 30 * this.calibrage.scalePlan;
1151
- const shift = iconSize / 2;
1152
- this.drawImage('https://api.iconify.design/mdi:adjust.svg?color=green&height=30&width=30', transformedX - shift, transformedY - shift, true);
1153
- }
1154
- }
1155
- }
1156
- });
1157
- }
1158
- /** Save calibration */
1159
- onSave() {
1160
- return __awaiter(this, void 0, void 0, function* () {
1161
- if (this.currentZone) {
1162
- /** Normalize with the zoom */
1163
- // this.calibrage.offsetX /= this.canvasZoom;
1164
- // this.calibrage.offsetY /= this.canvasZoom;
1165
- // this.calibrage.x /= this.canvasZoom;
1166
- // this.calibrage.y /= this.canvasZoom;
1167
- this.calibrage.new = true;
1168
- this.calibrage.imgWidth = this.canvasSize.w;
1169
- this.calibrage.imgHeight = this.canvasSize.h;
1170
- yield this.planService.updatePlan({
1171
- id: this.chosenPlan.id,
1172
- calibration: JSON.stringify(this.calibrage),
1173
- });
1174
- yield Promise.all(this.positions.map((position) => __awaiter(this, void 0, void 0, function* () {
1175
- const { navID } = position;
1176
- delete position.navID;
1177
- const nav = this.currentNavigations.find((_nav) => _nav.id === navID);
1178
- let positionsDataToUpdate;
1179
- if (nav.positionOnPlan) {
1180
- const positionOnPlan = nav.positionOnPlan.map((entry) => JSON.parse(entry));
1181
- const positionForCurrentPlan = positionOnPlan.find((entry) => entry.planID === this.chosenPlan.id);
1182
- if (positionForCurrentPlan) {
1183
- positionOnPlan.splice(positionOnPlan.indexOf(positionForCurrentPlan), 1, position);
1184
- }
1185
- else {
1186
- positionOnPlan.push(position);
1187
- }
1188
- positionsDataToUpdate = [...positionOnPlan];
1189
- }
1190
- else {
1191
- positionsDataToUpdate = [position];
1192
- }
1193
- // console.log(positionsDataToUpdate);
1194
- yield this.navigationService.updateNavigation({
1195
- id: navID,
1196
- positionOnPlan: positionsDataToUpdate.map((entry) => JSON.stringify(entry)),
1197
- });
1198
- })));
1199
- }
1200
- this.matterportImportService.removeFrame();
1201
- this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
1202
- alert(this.translate.instant('calibration.success'));
1203
- });
1204
- }
1205
- /** Reset the canvas */
1206
- onReset() {
1207
- this.reflectH = false;
1208
- this.reflectV = false;
1209
- this.preview = false;
1210
- this.configureCanvas();
1211
- }
1212
- /** Cancel, leave */
1213
- onCancel() {
1214
- this.matterportImportService.removeFrame();
1215
- this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
1216
- alert(this.translate.instant('calibration.canceled'));
1217
- }
1218
- onFloorClick(floor) {
1219
- return __awaiter(this, void 0, void 0, function* () {
1220
- this.currentFloor = floor;
1221
- yield this.matterportImportService.moveToFloor(floor.id);
1222
- });
1223
- }
1224
- onActivateZoomChange() {
1225
- this.zoomCanBeChanged = !this.zoomCanBeChanged;
1226
- const iframe = document.querySelector('#viewer-frame');
1227
- if (iframe) {
1228
- iframe.style.zIndex = this.zoomCanBeChanged ? '1' : '0';
1229
- }
1230
- }
1231
- }
1232
- CalibrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CalibrationComponent, deps: [{ token: i2.MatterportImportService }, { token: i2.PlanService }, { token: i1.ActivatedRoute }, { token: i1.Router }, { token: i2.ZoneService }, { token: i2.SpaceService }, { token: i2.NavigationService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
1233
- CalibrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CalibrationComponent, selector: "lib-calibration", viewQueries: [{ propertyName: "canvasDiv", first: true, predicate: ["canvasDiv"], descendants: true }], ngImport: i0, template: "<div class=\"row mt-3\">\r\n <div class=\"col\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div id=\"rowCanvas\">\r\n <div #canvasDiv id=\"canvasDiv\">\r\n\r\n <div id=\"viewer-frame\" [style.pointer-events]=\"zoomCanBeChanged?'auto':'none'\">\r\n <!-- <div class=\"blur\"></div> -->\r\n </div>\r\n <canvas id=\"canvas\" [ngStyle]=\"{'opacity': (preview||loading) ? '1' : 'calc(' + opacity + '/ 100)'}\"></canvas>\r\n </div>\r\n\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"!(preview || loading)\">\r\n <h1>{{'Calibration tool' | translate}}</h1>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 legend\">\r\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">\r\n {{'Less' | translate}}</div>\r\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\r\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' |\r\n translate}}</div>\r\n </div>\r\n <div class=\"row ms-0 me-0 \">\r\n <input [disabled]=\"false\" [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"opacity\" type=\"range\"\r\n class=\"form-range\" min=\"0\" max=\"100\" value=\"50\" id=\"opacity\">\r\n </div>\r\n </div>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 \">\r\n <div class=\"label-legend\">{{'Change Visit Floor' | translate}}</div>\r\n <div ngbDropdown class=\"d-inline-block ms-3\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>\r\n {{currentFloor ? currentFloor.id : ('Floor' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let floor of floors\" (click)=\"onFloorClick(floor)\">\r\n {{ floor.name.length > 0 ? floor.name : ('Floor ' + floor.id) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 \">\r\n <div class=\"tool-checkbox-container\">\r\n <div class=\"tool-checkbox-subcontainer\">\r\n <div class=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" :\r\n \"OFF\"}}\r\n </div>\r\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\r\n </div>\r\n <div class=\"card border-warning mb-3 mt-3\" *ngIf=\"zoomCanBeChanged\">\r\n <div class=\"card-body text-warning\">\r\n <h5 class=\"card-title\">{{\"calibration.wait-message\" | translate}}</h5>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"action\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onPreview()\"\r\n [disabled]=\"zoomCanBeChanged\">{{'Preview' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n </div>\r\n\r\n </div>\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"preview\">\r\n <h1>{{'Validation' | translate}}</h1>\r\n <div class=\"action\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onSave()\">{{'Validate' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onReset()\">{{'Reset' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n </div>\r\n </div>\r\n\r\n\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"loading\">\r\n <h3>{{\"Waiting for Matterport\" | translate}}...</h3>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}#rowCanvas{display:flex}#canvasDiv{height:100%;width:100%;position:relative}#canvas{width:100%;height:100%;opacity:.5}#viewer-frame{top:0;position:absolute;width:100%;height:100%}.calibration-tools{margin-left:20px;width:400px;background-color:#fff;z-index:11;border:1px solid var(--smarterplan-primary);padding:7px}.form-range{width:100%}.tool{margin-top:20px}.tool .legend{justify-content:space-between;position:relative;margin-bottom:5px}.tool .legend-title{font-size:1.2rem;color:var(--smarterplan-primary);margin:auto;width:100%;font-weight:700;display:flex;justify-content:center}.tool .legend-bar-indicator{width:15%!important}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem;max-width:55%}.tool .tool-checkbox-container{display:flex;flex-direction:column}.tool .tool-checkbox-container .tool-checkbox-subcontainer{display:flex}.blur{width:150px;height:52px;position:absolute;background-color:#1e2023;bottom:0}.symmetry{padding:5px;border:solid 2px;border-radius:10px;color:var(--smarterplan-primary);margin:25px 10px;cursor:pointer}.symmetry:hover{color:var(--smarterplan-primary)}.symmetry-row{justify-content:center}.action{margin-top:30px;display:flex;justify-content:space-evenly}h1{color:var(--smarterplan-primary);text-align:center;margin-bottom:20px}h3{color:var(--smarterplan-primary);text-align:center;margin-bottom:10px}.btn-outline-primary.disabled{background-color:var(--smarterplan-orange)!important}\n"], dependencies: [{ kind: "directive", type: i4$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i4$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i4$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i4$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { 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: "directive", type: i1$2.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: i1$2.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
1234
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CalibrationComponent, decorators: [{
1235
- type: Component,
1236
- args: [{ selector: 'lib-calibration', template: "<div class=\"row mt-3\">\r\n <div class=\"col\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div id=\"rowCanvas\">\r\n <div #canvasDiv id=\"canvasDiv\">\r\n\r\n <div id=\"viewer-frame\" [style.pointer-events]=\"zoomCanBeChanged?'auto':'none'\">\r\n <!-- <div class=\"blur\"></div> -->\r\n </div>\r\n <canvas id=\"canvas\" [ngStyle]=\"{'opacity': (preview||loading) ? '1' : 'calc(' + opacity + '/ 100)'}\"></canvas>\r\n </div>\r\n\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"!(preview || loading)\">\r\n <h1>{{'Calibration tool' | translate}}</h1>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 legend\">\r\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">\r\n {{'Less' | translate}}</div>\r\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\r\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' |\r\n translate}}</div>\r\n </div>\r\n <div class=\"row ms-0 me-0 \">\r\n <input [disabled]=\"false\" [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"opacity\" type=\"range\"\r\n class=\"form-range\" min=\"0\" max=\"100\" value=\"50\" id=\"opacity\">\r\n </div>\r\n </div>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 \">\r\n <div class=\"label-legend\">{{'Change Visit Floor' | translate}}</div>\r\n <div ngbDropdown class=\"d-inline-block ms-3\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>\r\n {{currentFloor ? currentFloor.id : ('Floor' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let floor of floors\" (click)=\"onFloorClick(floor)\">\r\n {{ floor.name.length > 0 ? floor.name : ('Floor ' + floor.id) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"tool\">\r\n <div class=\"row ms-0 me-0 \">\r\n <div class=\"tool-checkbox-container\">\r\n <div class=\"tool-checkbox-subcontainer\">\r\n <div class=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" :\r\n \"OFF\"}}\r\n </div>\r\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\r\n </div>\r\n <div class=\"card border-warning mb-3 mt-3\" *ngIf=\"zoomCanBeChanged\">\r\n <div class=\"card-body text-warning\">\r\n <h5 class=\"card-title\">{{\"calibration.wait-message\" | translate}}</h5>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"action\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onPreview()\"\r\n [disabled]=\"zoomCanBeChanged\">{{'Preview' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n </div>\r\n\r\n </div>\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"preview\">\r\n <h1>{{'Validation' | translate}}</h1>\r\n <div class=\"action\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onSave()\">{{'Validate' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onReset()\">{{'Reset' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\r\n translate}}</button>\r\n\r\n </div>\r\n </div>\r\n\r\n\r\n <div class=\"calibration-tools container-fluid\" *ngIf=\"loading\">\r\n <h3>{{\"Waiting for Matterport\" | translate}}...</h3>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}#rowCanvas{display:flex}#canvasDiv{height:100%;width:100%;position:relative}#canvas{width:100%;height:100%;opacity:.5}#viewer-frame{top:0;position:absolute;width:100%;height:100%}.calibration-tools{margin-left:20px;width:400px;background-color:#fff;z-index:11;border:1px solid var(--smarterplan-primary);padding:7px}.form-range{width:100%}.tool{margin-top:20px}.tool .legend{justify-content:space-between;position:relative;margin-bottom:5px}.tool .legend-title{font-size:1.2rem;color:var(--smarterplan-primary);margin:auto;width:100%;font-weight:700;display:flex;justify-content:center}.tool .legend-bar-indicator{width:15%!important}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem;max-width:55%}.tool .tool-checkbox-container{display:flex;flex-direction:column}.tool .tool-checkbox-container .tool-checkbox-subcontainer{display:flex}.blur{width:150px;height:52px;position:absolute;background-color:#1e2023;bottom:0}.symmetry{padding:5px;border:solid 2px;border-radius:10px;color:var(--smarterplan-primary);margin:25px 10px;cursor:pointer}.symmetry:hover{color:var(--smarterplan-primary)}.symmetry-row{justify-content:center}.action{margin-top:30px;display:flex;justify-content:space-evenly}h1{color:var(--smarterplan-primary);text-align:center;margin-bottom:20px}h3{color:var(--smarterplan-primary);text-align:center;margin-bottom:10px}.btn-outline-primary.disabled{background-color:var(--smarterplan-orange)!important}\n"] }]
1237
- }], ctorParameters: function () { return [{ type: i2.MatterportImportService }, { type: i2.PlanService }, { type: i1.ActivatedRoute }, { type: i1.Router }, { type: i2.ZoneService }, { type: i2.SpaceService }, { type: i2.NavigationService }, { type: i3.TranslateService }]; }, propDecorators: { canvasDiv: [{
1238
- type: ViewChild,
1239
- args: ['canvasDiv']
1240
- }] } });
1241
-
1242
- class PlansComponent {
1243
- constructor(route, router, spaceService, planService, fb, translate, navigatorService) {
1244
- this.route = route;
1245
- this.router = router;
1246
- this.spaceService = spaceService;
1247
- this.planService = planService;
1248
- this.fb = fb;
1249
- this.translate = translate;
1250
- this.navigatorService = navigatorService;
1251
- // chosenPlan: Plan;
1252
- this.indexDetails = -1;
1253
- this.loading = false;
1254
- this.uploadingPlan = false;
1255
- this.isCurrentPlanForZone = false;
1256
- this.chosenPlanIsPdf = false;
1257
- this.menuItems = [];
1258
- this.destroy$ = new Subject();
1259
- this.navigatorService.locationIDChange
1260
- .pipe(takeUntil(this.destroy$))
1261
- .subscribe((spaceID) => {
1262
- this.router.navigate(["dashboard/localisation", spaceID, "plans"]);
1263
- });
1264
- this.route.params.subscribe((params) => {
1265
- this.spaceID = params.id;
1266
- this.getPlans();
1267
- });
1268
- }
1269
- ngOnInit() {
1270
- if (this.planService.getPlanFileCache() &&
1271
- this.planService.getChosenPlan()) {
1272
- this.addPlanFromCache(this.planService.getPlanFileCache(), this.planService.getChosenPlan());
1273
- this.planService.setPlanFileCache(null);
1274
- }
1275
- this.planService.setChosenPlan(null);
1276
- }
1277
- ngOnDestroy() {
1278
- this.destroy$.next(true);
1279
- this.destroy$.complete();
1280
- }
1281
- setupMenuItems() {
1282
- this.menuItems = [
1283
- { label: "Locations", url: "/localisation" },
1284
- {
1285
- label: this.currentSpace.name,
1286
- url: `/localisation/${this.currentSpace.id}`,
1287
- },
1288
- {
1289
- label: "Plans",
1290
- url: `/localisation/${this.currentSpace.id}/plans`,
1291
- },
1292
- ];
1293
- }
1294
- onGoBack() { }
1295
- onPlanClick(plan) {
1296
- return __awaiter(this, void 0, void 0, function* () {
1297
- if (plan)
1298
- this.planService.setChosenPlan(plan);
1299
- this.chosenPlanIsPdf = plan.annexe.includes("pdf");
1300
- if (!this.chosenPlanIsPdf) {
1301
- setTimeout(() => {
1302
- this.configureCanvas().then(() => {
1303
- this.panzoom = panzoom(this.canvas, {
1304
- bounds: true,
1305
- boundsPadding: 0,
1306
- maxZoom: 3.5,
1307
- minZoom: 0.1,
1308
- initialZoom: 0.5,
1309
- });
1310
- });
1311
- }, 500);
1312
- }
1313
- });
1314
- }
1315
- configureCanvas() {
1316
- return __awaiter(this, void 0, void 0, function* () {
1317
- this.uploadingPlan = true;
1318
- const canvas = document.querySelector("#canvas");
1319
- const image = yield getMetaForImage(this.getChoosenPlan().filepath);
1320
- canvas.width = image.width;
1321
- canvas.height = image.height;
1322
- this.canvas = canvas;
1323
- this.drawImage(this.getChoosenPlan().filepath);
1324
- this.uploadingPlan = false;
1325
- });
1326
- }
1327
- drawImage(url, x = 0, y = 0) {
1328
- const image = new Image();
1329
- const context = this.canvas.getContext("2d");
1330
- const imageWidth = this.canvas.width;
1331
- const imageHeight = this.canvas.height;
1332
- image.addEventListener("load", () => {
1333
- context.drawImage(image, 0, 0, image.width, image.height, x, y, imageWidth, imageHeight);
1334
- });
1335
- image.src = url;
1336
- // image.crossOrigin = "*"; //need to download as png,
1337
- // BUT: https://stackoverflow.com/questions/49503171/the-image-tag-with-crossorigin-anonymous-cant-load-success-from-s3
1338
- }
1339
- getPlans() {
1340
- return __awaiter(this, void 0, void 0, function* () {
1341
- this.loading = true;
1342
- this.currentSpace = yield this.spaceService.getSpace(this.spaceID);
1343
- this.setupMenuItems();
1344
- this.zones = this.currentSpace.zones.items;
1345
- this.plans = yield this.planService.getSingedPlansForSpace(this.spaceID);
1346
- this.loading = false;
1347
- if (this.plans.length === 1) {
1348
- this.onPlanClick(this.plans[0]);
1349
- }
1350
- });
1351
- }
1352
- getChoosenPlan() {
1353
- return this.planService.getChosenPlan();
1354
- }
1355
- removeImage() {
1356
- const context = this.canvas.getContext("2d");
1357
- context.clearRect(0, 0, 4096, 4096);
1358
- }
1359
- /**
1360
- *
1361
- */
1362
- onCalibrateClick() {
1363
- if (this.getChoosenPlan()) {
1364
- this.router.navigate(["/dashboard/localisation", this.spaceID, "plan-calibration"], { queryParams: { spaceID: this.spaceID } });
1365
- }
1366
- }
1367
- /**
1368
- *
1369
- */
1370
- onEditClick() {
1371
- if (this.getChoosenPlan()) {
1372
- this.router.navigate(["/dashboard/localisation", this.spaceID, "plan-edit"], { queryParams: { spaceID: this.spaceID } });
1373
- }
1374
- }
1375
- onUploadClick() {
1376
- const inputFile = document.querySelector("#upload-file");
1377
- inputFile.click();
1378
- }
1379
- addPlan(target) {
1380
- this.fileToUpload = target.files[0];
1381
- this.planForm = this.fb.group({
1382
- name: [this.fileToUpload.name, [Validators.required]],
1383
- zoneID: [null, [Validators.required]],
1384
- spaceID: this.spaceID,
1385
- isModified: false,
1386
- calibration: "",
1387
- });
1388
- }
1389
- addPlanFromCache(file, plan) {
1390
- this.fileToUpload = file;
1391
- this.planForm = this.fb.group({
1392
- name: [this.fileToUpload.name, [Validators.required]],
1393
- zoneID: [plan ? plan.zoneID : null, [Validators.required]],
1394
- spaceID: this.spaceID,
1395
- isModified: !!plan,
1396
- calibration: plan && plan.isModified && plan.calibration
1397
- ? plan.calibration
1398
- : "",
1399
- });
1400
- }
1401
- onSavePlan() {
1402
- return __awaiter(this, void 0, void 0, function* () {
1403
- const formValue = this.planForm.value;
1404
- formValue.isCurrentForZone = this.isCurrentPlanForZone;
1405
- const createdPlan = yield this.planService.createPlanWithAnnexe(formValue, this.fileToUpload);
1406
- const filepath = yield getSignedFile(createdPlan.annexe);
1407
- if (filepath) {
1408
- createdPlan.filepath = filepath;
1409
- }
1410
- if (formValue.isCurrentForZone) {
1411
- // set all other plans to not current
1412
- this.planService.setAllPlansForZoneNotCurrent(createdPlan.zoneID, createdPlan.id);
1413
- }
1414
- this.plans.push(createdPlan);
1415
- this.planForm = null;
1416
- this.fileToUpload = null;
1417
- });
1418
- }
1419
- onCancelUpload() {
1420
- this.fileToUpload = null;
1421
- this.planForm = null;
1422
- }
1423
- onCurrentPlanClick() {
1424
- return __awaiter(this, void 0, void 0, function* () {
1425
- yield this.planService.updatePlan({
1426
- id: this.getChoosenPlan().id,
1427
- isCurrentForZone: this.getChoosenPlan().isCurrentForZone,
1428
- });
1429
- if (this.getChoosenPlan().isCurrentForZone) {
1430
- this.planService.setAllPlansForZoneNotCurrent(this.getChoosenPlan().zoneID, this.getChoosenPlan().id);
1431
- }
1432
- });
1433
- }
1434
- onDownloadClick() {
1435
- return __awaiter(this, void 0, void 0, function* () {
1436
- const signedFile = yield downloadFileAsObject(this.getChoosenPlan().annexe);
1437
- if (signedFile) {
1438
- // @ts-ignore
1439
- downloadBlob(signedFile.Body, this.getChoosenPlan().name);
1440
- }
1441
- });
1442
- }
1443
- onDownloadAsPng() {
1444
- return __awaiter(this, void 0, void 0, function* () {
1445
- const canvas = document.querySelector("#canvas");
1446
- canvas.toBlob(function (blob) {
1447
- downloadBlob(blob, "plan-as-png.png");
1448
- });
1449
- });
1450
- }
1451
- onRemoveClick() {
1452
- return __awaiter(this, void 0, void 0, function* () {
1453
- const message = this.translate.instant("confirm.deletePlan");
1454
- if (window.confirm(message)) {
1455
- yield this.planService.deletePlan(this.getChoosenPlan());
1456
- this.removeImage();
1457
- this.planService.setChosenPlan(null);
1458
- this.getPlans();
1459
- }
1460
- });
1461
- }
1462
- }
1463
- PlansComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PlansComponent, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: i2.SpaceService }, { token: i2.PlanService }, { token: i1$2.UntypedFormBuilder }, { token: i3.TranslateService }, { token: i2.NavigatorService }], target: i0.ɵɵFactoryTarget.Component });
1464
- PlansComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PlansComponent, selector: "lib-plans", ngImport: i0, template: "<div class=\"container-fluid\" *ngIf=\"currentSpace\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <div class=\"mt-3\" *ngIf=\"!plans && !loading\">\r\n <h4 style=\"font-weight: bold;\">{{'No imported plans' | translate }}</h4>\r\n <p>{{'For import from 3D visit: go Virtual Visits => Import Images' | translate}}</p>\r\n </div>\r\n <div class=\"row ms-1\">\r\n <div ngbDropdown class=\"d-inline-block me-3\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>{{getChoosenPlan() ?\r\n getChoosenPlan().name: ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\">{{plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"d-inline-block\" ngbDropdown #myDrop=\"ngbDropdown\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownManual\" ngbDropdownToggle>{{'Choose action' |\r\n translate}}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownManual\">\r\n <button (click)=\"onCalibrateClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Calibrate' |\r\n translate}}</button>\r\n <button (click)=\"onEditClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Edit plan' |\r\n translate}}\r\n </button>\r\n <button (click)=\"onUploadClick()\" ngbDropdownItem>{{'Upload new plan' | translate}}</button>\r\n <button (click)=\"onDownloadClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Download plan' |\r\n translate}}</button>\r\n <button (click)=\"onRemoveClick()\" ngbDropdownItem\r\n [disabled]=\"!getChoosenPlan() || getChoosenPlan().isImportedMatterport\">{{'Delete plan' |\r\n translate}}</button>\r\n <!-- <button (click)=\"onDownloadAsPng()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">\r\n {{'Download plan as PNG' | translate}}</button> -->\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3 ms-0\">\r\n <h4 *ngIf=\"fileToUpload\">{{'New plan' | translate }}</h4>\r\n <input class=\"hidden\" type=\"file\" id=\"upload-file\" name=\"upload-file\" accept=\"image/png, image/jpeg, .pdf, .svg\"\r\n ngf-max-size=\"6MB\" (change)=\"addPlan($event.target)\">\r\n </div>\r\n <div class=\"col-md-6 mt-3\" *ngIf=\"planForm\">\r\n <form (ngSubmit)=\"onSavePlan()\" [formGroup]=\"planForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Name' | translate}} </label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Zone' | translate}} </label>\r\n <div class=\"col-sm-9\">\r\n <select class=\"form-control\" formControlName=\"zoneID\">\r\n <option *ngFor=\"let zone of zones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Set as current plan for zone' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input type=\"checkbox\" [(ngModel)]=\"isCurrentPlanForZone\" [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n <button [disabled]=\"planForm.invalid\" type='submit' class=\"btn btn-label-file rounded-pill\">{{'Save' |\r\n translate}}</button>\r\n <button class=\"btn btn-label-file rounded-pill ms-3\" type=\"button\" (click)=\"onCancelUpload()\">{{'Cancel' |\r\n translate}}</button>\r\n </form>\r\n </div>\r\n <ul class=\"col-md-6 list-group list-group-flush\" *ngIf=\"getChoosenPlan()\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate }} : {{getChoosenPlan().name}} </li>\r\n <li class=\"list-group-item bg-transparent\"> {{'Plan is ' | translate }} :\r\n {{getChoosenPlan().calibration ? ('Calibrated' | translate) : ('Not calibrated' | translate)}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Attributed to zone ' | translate }} :\r\n {{getChoosenPlan().zone ? getChoosenPlan().zone.name : 'None'}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Is current plan for zone ' | translate }} :\r\n <input type=\"checkbox\" [(ngModel)]=\"getChoosenPlan().isCurrentForZone\" (change)=\"onCurrentPlanClick()\">\r\n </li>\r\n\r\n </ul>\r\n\r\n <div class=\"row mt-4\">\r\n <div class=\"col-md-10\">\r\n <embed *ngIf=\"getChoosenPlan() && chosenPlanIsPdf\" [src]=\"getChoosenPlan().filepath | safeUrl\"\r\n type=\"application/pdf\" frameBorder=\"0\" scrolling=\"auto\" height=\"650px;\" width=\"100%\" />\r\n <div *ngIf=\"!chosenPlanIsPdf\" class=\"row\" style=\"height: 500px; overflow: hidden;\" id=\"canvasDiv\">\r\n <canvas id=\"canvas\" width=\"4096px\" height=\"4096px\">\r\n <!-- <img *ngIf=\"chosenPlan\" id=\"plan-image\" [src]=\"chosenPlan.filepath\" style=\"width: 100%;\"> -->\r\n </canvas>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}.hidden{visibility:hidden;width:1px;height:1px}\n"], dependencies: [{ kind: "directive", type: i4$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i4$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i4$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i4$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { 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: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2.SafeUrlPipe, name: "safeUrl" }] });
1465
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PlansComponent, decorators: [{
1466
- type: Component,
1467
- args: [{ selector: 'lib-plans', template: "<div class=\"container-fluid\" *ngIf=\"currentSpace\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <div class=\"mt-3\" *ngIf=\"!plans && !loading\">\r\n <h4 style=\"font-weight: bold;\">{{'No imported plans' | translate }}</h4>\r\n <p>{{'For import from 3D visit: go Virtual Visits => Import Images' | translate}}</p>\r\n </div>\r\n <div class=\"row ms-1\">\r\n <div ngbDropdown class=\"d-inline-block me-3\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>{{getChoosenPlan() ?\r\n getChoosenPlan().name: ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\">{{plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"d-inline-block\" ngbDropdown #myDrop=\"ngbDropdown\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownManual\" ngbDropdownToggle>{{'Choose action' |\r\n translate}}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownManual\">\r\n <button (click)=\"onCalibrateClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Calibrate' |\r\n translate}}</button>\r\n <button (click)=\"onEditClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Edit plan' |\r\n translate}}\r\n </button>\r\n <button (click)=\"onUploadClick()\" ngbDropdownItem>{{'Upload new plan' | translate}}</button>\r\n <button (click)=\"onDownloadClick()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">{{'Download plan' |\r\n translate}}</button>\r\n <button (click)=\"onRemoveClick()\" ngbDropdownItem\r\n [disabled]=\"!getChoosenPlan() || getChoosenPlan().isImportedMatterport\">{{'Delete plan' |\r\n translate}}</button>\r\n <!-- <button (click)=\"onDownloadAsPng()\" ngbDropdownItem [disabled]=\"!getChoosenPlan()\">\r\n {{'Download plan as PNG' | translate}}</button> -->\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3 ms-0\">\r\n <h4 *ngIf=\"fileToUpload\">{{'New plan' | translate }}</h4>\r\n <input class=\"hidden\" type=\"file\" id=\"upload-file\" name=\"upload-file\" accept=\"image/png, image/jpeg, .pdf, .svg\"\r\n ngf-max-size=\"6MB\" (change)=\"addPlan($event.target)\">\r\n </div>\r\n <div class=\"col-md-6 mt-3\" *ngIf=\"planForm\">\r\n <form (ngSubmit)=\"onSavePlan()\" [formGroup]=\"planForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Name' | translate}} </label>\r\n <div class=\"col-sm-9\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Zone' | translate}} </label>\r\n <div class=\"col-sm-9\">\r\n <select class=\"form-control\" formControlName=\"zoneID\">\r\n <option *ngFor=\"let zone of zones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3\">{{'Set as current plan for zone' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input type=\"checkbox\" [(ngModel)]=\"isCurrentPlanForZone\" [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n <button [disabled]=\"planForm.invalid\" type='submit' class=\"btn btn-label-file rounded-pill\">{{'Save' |\r\n translate}}</button>\r\n <button class=\"btn btn-label-file rounded-pill ms-3\" type=\"button\" (click)=\"onCancelUpload()\">{{'Cancel' |\r\n translate}}</button>\r\n </form>\r\n </div>\r\n <ul class=\"col-md-6 list-group list-group-flush\" *ngIf=\"getChoosenPlan()\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate }} : {{getChoosenPlan().name}} </li>\r\n <li class=\"list-group-item bg-transparent\"> {{'Plan is ' | translate }} :\r\n {{getChoosenPlan().calibration ? ('Calibrated' | translate) : ('Not calibrated' | translate)}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Attributed to zone ' | translate }} :\r\n {{getChoosenPlan().zone ? getChoosenPlan().zone.name : 'None'}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Is current plan for zone ' | translate }} :\r\n <input type=\"checkbox\" [(ngModel)]=\"getChoosenPlan().isCurrentForZone\" (change)=\"onCurrentPlanClick()\">\r\n </li>\r\n\r\n </ul>\r\n\r\n <div class=\"row mt-4\">\r\n <div class=\"col-md-10\">\r\n <embed *ngIf=\"getChoosenPlan() && chosenPlanIsPdf\" [src]=\"getChoosenPlan().filepath | safeUrl\"\r\n type=\"application/pdf\" frameBorder=\"0\" scrolling=\"auto\" height=\"650px;\" width=\"100%\" />\r\n <div *ngIf=\"!chosenPlanIsPdf\" class=\"row\" style=\"height: 500px; overflow: hidden;\" id=\"canvasDiv\">\r\n <canvas id=\"canvas\" width=\"4096px\" height=\"4096px\">\r\n <!-- <img *ngIf=\"chosenPlan\" id=\"plan-image\" [src]=\"chosenPlan.filepath\" style=\"width: 100%;\"> -->\r\n </canvas>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}.hidden{visibility:hidden;width:1px;height:1px}\n"] }]
1468
- }], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i1.Router }, { type: i2.SpaceService }, { type: i2.PlanService }, { type: i1$2.UntypedFormBuilder }, { type: i3.TranslateService }, { type: i2.NavigatorService }]; } });
1469
-
1470
- class ChevronComponent {
1471
- constructor() {
1472
- this.conditionShowing = false;
1473
- }
1474
- ngOnInit() {
1475
- }
1476
- }
1477
- ChevronComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ChevronComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1478
- ChevronComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ChevronComponent, selector: "lib-chevron", inputs: { conditionShowing: "conditionShowing" }, ngImport: i0, template: "<div style=\"height: 30px; width: 30px;\">\r\n <span class=\"icon-container\" >\r\n <div [class]=\"conditionShowing ? 'icon-img-up' : 'icon-img-down'\"></div>\r\n </span>\r\n</div>\r\n", styles: [".icon-container{height:30px;width:30px}.icon-img-down{width:30px;height:100%;background:url(https://api.iconify.design/mdi-light/chevron-right.svg?width=28) no-repeat center center/contain}.icon-img-up{width:30px;height:100%;background:url(https://api.iconify.design/mdi-light/chevron-down.svg?width=28) no-repeat center center/contain}\n"] });
1479
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ChevronComponent, decorators: [{
1480
- type: Component,
1481
- args: [{ selector: 'lib-chevron', template: "<div style=\"height: 30px; width: 30px;\">\r\n <span class=\"icon-container\" >\r\n <div [class]=\"conditionShowing ? 'icon-img-up' : 'icon-img-down'\"></div>\r\n </span>\r\n</div>\r\n", styles: [".icon-container{height:30px;width:30px}.icon-img-down{width:30px;height:100%;background:url(https://api.iconify.design/mdi-light/chevron-right.svg?width=28) no-repeat center center/contain}.icon-img-up{width:30px;height:100%;background:url(https://api.iconify.design/mdi-light/chevron-down.svg?width=28) no-repeat center center/contain}\n"] }]
1482
- }], ctorParameters: function () { return []; }, propDecorators: { conditionShowing: [{
1483
- type: Input
1484
- }] } });
1485
-
1486
- class VisitsComponent {
1487
- constructor(fb, matterportImportService, captureService, nodeService, spaceService, route, modalService, visitService, validatorsService, translate, navigatorService, router) {
1488
- this.fb = fb;
1489
- this.matterportImportService = matterportImportService;
1490
- this.captureService = captureService;
1491
- this.nodeService = nodeService;
1492
- this.spaceService = spaceService;
1493
- this.route = route;
1494
- this.modalService = modalService;
1495
- this.visitService = visitService;
1496
- this.validatorsService = validatorsService;
1497
- this.translate = translate;
1498
- this.navigatorService = navigatorService;
1499
- this.router = router;
1500
- this.visitIndexDetails = -1;
1501
- this.isEditing = false;
1502
- this.visitSubmitted = false;
1503
- this.currentSpace = { zones: [] };
1504
- this.visits = [];
1505
- this.canCancelImport = false;
1506
- this.imagesProcessed = 0;
1507
- this.totalImages = 0;
1508
- this.imagesUploaded = 0;
1509
- this.menuItems = [];
1510
- this.errorForm = false;
1511
- this.isProcessing = false;
1512
- this.destroy$ = new Subject();
1513
- this.matterportImportService.importingImages.pipe(takeUntil(this.destroy$)).subscribe(() => {
1514
- this.canCancelImport = true;
1515
- });
1516
- this.matterportImportService.sweepProcessedCount.pipe(takeUntil(this.destroy$)).subscribe((count) => {
1517
- this.imagesProcessed = count + 1;
1518
- });
1519
- this.matterportImportService.totalSweepsCount.pipe(takeUntil(this.destroy$)).subscribe((count) => {
1520
- this.totalImages = count;
1521
- });
1522
- this.navigatorService.locationIDChange
1523
- .pipe(takeUntil(this.destroy$))
1524
- .subscribe((spaceID) => {
1525
- this.router.navigate(["dashboard/localisation", spaceID, "visits"]);
1526
- });
1527
- this.route.params.subscribe((params) => {
1528
- this.spaceId = params.id;
1529
- this.resetVisits();
1530
- });
1531
- }
1532
- ngOnInit() {
1533
- return __awaiter(this, void 0, void 0, function* () {
1534
- this.spaceId = this.route.snapshot.paramMap.get('id');
1535
- yield this.resetVisits();
1536
- });
1537
- }
1538
- ngOnDestroy() {
1539
- this.destroy$.next(true);
1540
- this.destroy$.complete();
1541
- }
1542
- /*
1543
- Visit = {
1544
- captureID: string,
1545
- model3d: string,
1546
- takenAt: number,
1547
- spaceID: string,
1548
- viewer: CaptureViewer,
1549
- surface: number,
1550
- node: Node,
1551
- name?: string | null
1552
- }
1553
- */
1554
- setupMenuItems() {
1555
- this.menuItems = [
1556
- { label: 'Locations', url: '/localisation' },
1557
- {
1558
- label: this.currentSpace.name,
1559
- url: `/localisation/${this.currentSpace.id}`,
1560
- },
1561
- {
1562
- label: 'Virtual visits',
1563
- url: `/localisation/${this.currentSpace.id}/visits`,
1564
- },
1565
- ];
1566
- }
1567
- onGoBack() {
1568
- this.onCancel();
1569
- }
1570
- resetVisits() {
1571
- return __awaiter(this, void 0, void 0, function* () {
1572
- this.visits = [];
1573
- this.currentSpace = yield this.spaceService.getSpace(this.spaceId);
1574
- this.setupMenuItems();
1575
- yield this.visitService
1576
- .getVisitsForSpaceForUser(this.spaceId)
1577
- .then((visits) => {
1578
- if (visits) {
1579
- this.visits = visits;
1580
- }
1581
- });
1582
- });
1583
- }
1584
- initVisitForm(input = null) {
1585
- if (input) {
1586
- this.visitForm = this.fb.group({
1587
- captureID: input.captureID,
1588
- nodeID: input.node.id,
1589
- name: [input.name, [Validators.required]],
1590
- model3D: [input.model3d, [Validators.required]],
1591
- viewer: input.viewer ? input.viewer : CaptureViewer.MATTERPORT,
1592
- surface: input.surface ? input.surface : null,
1593
- });
1594
- this.captureDate = input.takenAt;
1595
- }
1596
- else {
1597
- this.visitForm = this.fb.group({
1598
- model3D: [null, [Validators.required]],
1599
- viewer: CaptureViewer.MATTERPORT,
1600
- surface: null,
1601
- name: [null, [Validators.required]],
1602
- });
1603
- }
1604
- }
1605
- onToggleDetail(index) {
1606
- return __awaiter(this, void 0, void 0, function* () {
1607
- this.visitIndexDetails = index === this.visitIndexDetails ? -1 : index;
1608
- this.imagesUploaded = yield this.matterportImportService.getUploadedImageCount(this.visits[index].model3d);
1609
- });
1610
- }
1611
- onAddVisit() {
1612
- this.initVisitForm();
1613
- this.menuItems.push({ label: 'New' });
1614
- }
1615
- onEdit(visit) {
1616
- this.initVisitForm(visit);
1617
- this.isEditing = true;
1618
- this.menuItems.push({ label: visit.name });
1619
- }
1620
- onSubmitVisit() {
1621
- return __awaiter(this, void 0, void 0, function* () {
1622
- this.visitSubmitted = true;
1623
- if (!this.visitForm.valid) {
1624
- this.errorForm = true;
1625
- return;
1626
- }
1627
- this.errorForm = false;
1628
- const formValue = this.visitForm.value;
1629
- const capture = {
1630
- viewer: formValue.viewer,
1631
- takenAt: this.captureDate,
1632
- surface: formValue.surface,
1633
- spaceID: this.currentSpace.id,
1634
- };
1635
- if (this.isEditing) {
1636
- capture.id = formValue.captureID;
1637
- yield this.captureService.updateCapture(capture);
1638
- const node = {
1639
- id: formValue.nodeID,
1640
- model3D: formValue.model3D,
1641
- metadata: formValue.name,
1642
- };
1643
- yield this.nodeService.updateNode(node);
1644
- }
1645
- else {
1646
- let createdNode;
1647
- yield this.captureService.createCapture(capture).then((res) => __awaiter(this, void 0, void 0, function* () {
1648
- if (res) {
1649
- const node = {
1650
- model3D: formValue.model3D,
1651
- captureID: res.id,
1652
- metadata: formValue.name,
1653
- };
1654
- createdNode = yield this.nodeService.createNode(node);
1655
- }
1656
- }));
1657
- this.launchImport(formValue.model3D, formValue.surface, createdNode, false)
1658
- .then((success) => {
1659
- this.modalReference.close('import ended with success');
1660
- })
1661
- .catch((e) => {
1662
- this.modalReference.close(`Error while import: ${e}`);
1663
- alert(`Error while import: ${e} ${JSON.stringify(e)}`);
1664
- this.onDelete({
1665
- node: createdNode,
1666
- captureID: createdNode.captureID,
1667
- }, false);
1668
- });
1669
- }
1670
- yield this.resetVisits();
1671
- this.onCancel();
1672
- });
1673
- }
1674
- get model3D() {
1675
- return this.visitForm.get('model3D');
1676
- }
1677
- get name() {
1678
- return this.visitForm.get('name');
1679
- }
1680
- onCancel() {
1681
- this.visitSubmitted = false;
1682
- this.visitForm = null;
1683
- this.isEditing = false;
1684
- this.canCancelImport = false;
1685
- this.totalImages = 0;
1686
- this.imagesProcessed = 0;
1687
- this.errorForm = false;
1688
- this.setupMenuItems();
1689
- }
1690
- onDelete(visit, needPermission = true) {
1691
- return __awaiter(this, void 0, void 0, function* () {
1692
- const message = this.translate.instant('confirm.deleteVisit');
1693
- // eslint-disable-next-line no-alert
1694
- if (window.confirm(message) || !needPermission) {
1695
- console.log(this.visitIndexDetails);
1696
- this.isProcessing = true;
1697
- yield this.visitService.deleteVisit(visit, this.spaceId);
1698
- yield this.resetVisits();
1699
- this.isProcessing = false;
1700
- }
1701
- });
1702
- }
1703
- getDismissReason(reason) {
1704
- if (reason === ModalDismissReasons.ESC) {
1705
- return 'by pressing ESC';
1706
- }
1707
- if (reason === ModalDismissReasons.BACKDROP_CLICK) {
1708
- return 'by clicking on a backdrop';
1709
- }
1710
- return `with: ${reason}`;
1711
- }
1712
- launchImport(model3D, surface, node, imagesOnly = false, overrideExisting = false) {
1713
- return __awaiter(this, void 0, void 0, function* () {
1714
- this.modalReference = this.modalService.open(this.content, {
1715
- ariaLabelledBy: "modal-basic-title",
1716
- });
1717
- this.modalReference.result.then((result) => {
1718
- this.closeResult = `Closed with: ${result}`;
1719
- console.log(this.closeResult);
1720
- this.cancelImport();
1721
- }, (error) => {
1722
- this.closeResult = `Dismissed ${this.getDismissReason(error)}`;
1723
- console.log(this.closeResult);
1724
- this.cancelImport();
1725
- });
1726
- try {
1727
- yield this.matterportImportService.initSdkForModel(model3D);
1728
- yield this.matterportImportService.importData(this.spaceId, surface, imagesOnly, node, overrideExisting);
1729
- this.modalReference.close();
1730
- }
1731
- catch (error) {
1732
- console.log(error);
1733
- Promise.reject(error);
1734
- }
1735
- });
1736
- }
1737
- cancelImport() {
1738
- this.matterportImportService.abandon();
1739
- this.onCancel();
1740
- this.resetVisits();
1741
- }
1742
- onImportImages(visit, overrideExisting) {
1743
- this.launchImport(visit.model3d, null, visit.node.id, true, overrideExisting);
1744
- }
1745
- isFormError(control) {
1746
- return control && control.invalid && this.errorForm;
1747
- }
1748
- }
1749
- VisitsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VisitsComponent, deps: [{ token: i1$2.UntypedFormBuilder }, { token: i2.MatterportImportService }, { token: i2.CaptureService }, { token: i2.NodeService }, { token: i2.SpaceService }, { token: i1.ActivatedRoute }, { token: i4$1.NgbModal }, { token: i2.VisitService }, { token: i2.ValidatorsService }, { token: i3.TranslateService }, { token: i2.NavigatorService }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
1750
- VisitsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: VisitsComponent, selector: "lib-visits", viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n\r\n <div class=\"row main-form-container\">\r\n <div class=\"col-md-6 form-container\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"!visitForm\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let visit of visits; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\r\n {{visit.name ? visit.name : visit.model3d }}\r\n <lib-chevron [conditionShowing]=\"index==visitIndexDetails\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==visitIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} : {{ visit.name ?\r\n visit.name : \"Not provided\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'3D Model' | translate}} : {{ visit.model3d }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup>: {{\r\n visit.surface ?\r\n visit.surface : 'Not provided' | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Viewer' | translate}} : {{ visit.viewer }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Date of capture' | translate}} : {{\r\n visit.takenAt | timeDateString | async}}\r\n <li class=\"list-group-item bg-transparent\">{{'Images are imported' | translate}} : {{\r\n imagesUploaded }}\r\n </li>\r\n </ul>\r\n \r\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\r\n\r\n <div class=\"action-button-container mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, true)\" [disabled]=\"isProcessing\">{{'Import all images' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"imagesUploaded > 0\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, false)\" [disabled]=\"isProcessing\">{{'Import from image' |\r\n translate}} {{imagesUploaded}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" [disabled]=\"isProcessing\"\r\n (click)=\"onEdit(visit)\">{{'Edit' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" [disabled]=\"isProcessing\"\r\n (click)=\"onDelete(visit)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n <div *ngIf=\"visitForm\">\r\n <form (ngSubmit)=\"onSubmitVisit()\" [formGroup]=\"visitForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Reference 3D model' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" [readonly]=\"isEditing\"\r\n [class.is-invalid]=\"model3D.invalid && visitSubmitted\" required\r\n formControlName=\"model3D\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" \r\n *ngIf=\"validatorsService.isControlError(visitForm.controls['name']) \r\n || isFormError(visitForm.controls['name'])\">\r\n {{validatorsService.getError(visitForm.controls['name']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n <div *ngIf=\"isEditing\" class=\"text-danger\">\r\n {{'Cannot change 3D model reference. Please add new model.' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Viewer' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"viewer\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Capture Date' | translate}}</label>\r\n <div class=\"input-group\">\r\n <input class=\"form-control\" placeholder=\"dd/mm/yyyy\" [(ngModel)]=\"captureDate\" ngbDatepicker\r\n #d1=\"ngbDatepicker\" [ngModelOptions]=\"{standalone: true}\">\r\n <div class=\"input-group-append\">\r\n <button class=\"btn btn-outline-secondary calendar\" (click)=\"d1.toggle()\"\r\n type=\"button\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\">{{'Save' |\r\n translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n \r\n </ngb-alert>\r\n </div>\r\n </form>\r\n </div>\r\n <div *ngIf=\"!visitForm\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onAddVisit()\">{{'Add 3D visit' |\r\n translate}}</button>\r\n </div>\r\n </div>\r\n <div id=\"viewer-frame\" style=\"width: 100%; aspect-ratio: 2/1;\"></div>\r\n </div>\r\n <ng-template #content let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\" id=\"modal-basic-title\">{{'Importing Data' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">\u00D7</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'Please do not leave or refresh this page...' | translate}}\r\n <div *ngIf=\"totalImages != 0\">Imported {{imagesProcessed}} out of {{totalImages}} images.</div>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" [disabled]=\"!canCancelImport\"\r\n (click)=\"modal.close('Cancel click')\">{{'Cancel import of images' | translate}}</button>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".col-form-label{width:180px;margin-bottom:1rem}.btn-outline-primary{width:200px;margin-right:1rem}.input-group{width:83%;height:-moz-fit-content;height:fit-content}.main-form-container{width:60vw;display:flex;flex-direction:column}@media screen and (max-width: 765px){.main-form-container{width:90vw}}.main-form-container .form-container{width:100%}\n"], dependencies: [{ kind: "component", type: i4$1.NgbAlert, selector: "ngb-alert", inputs: ["animation", "dismissible", "type"], outputs: ["closed"], exportAs: ["ngbAlert"] }, { kind: "directive", type: i4$1.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { 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: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2.LoaderComponent, selector: "lib-loader", inputs: ["useLogo", "color"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: ChevronComponent, selector: "lib-chevron", inputs: ["conditionShowing"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2.TimeDateToLocalStringPipe, name: "timeDateString" }] });
1751
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VisitsComponent, decorators: [{
1752
- type: Component,
1753
- args: [{ selector: 'lib-visits', template: "<div class=\"container-fluid\" class=\"dashboard-tab\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n\r\n <div class=\"row main-form-container\">\r\n <div class=\"col-md-6 form-container\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"!visitForm\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let visit of visits; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center\" (click)=\"onToggleDetail(index)\">\r\n {{visit.name ? visit.name : visit.model3d }}\r\n <lib-chevron [conditionShowing]=\"index==visitIndexDetails\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==visitIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Name' | translate}} : {{ visit.name ?\r\n visit.name : \"Not provided\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'3D Model' | translate}} : {{ visit.model3d }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Surface' | translate}}, m<sup>2</sup>: {{\r\n visit.surface ?\r\n visit.surface : 'Not provided' | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Viewer' | translate}} : {{ visit.viewer }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Date of capture' | translate}} : {{\r\n visit.takenAt | timeDateString | async}}\r\n <li class=\"list-group-item bg-transparent\">{{'Images are imported' | translate}} : {{\r\n imagesUploaded }}\r\n </li>\r\n </ul>\r\n \r\n <lib-loader *ngIf=\"isProcessing\"></lib-loader>\r\n\r\n <div class=\"action-button-container mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, true)\" [disabled]=\"isProcessing\">{{'Import all images' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"imagesUploaded > 0\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onImportImages(visit, false)\" [disabled]=\"isProcessing\">{{'Import from image' |\r\n translate}} {{imagesUploaded}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" [disabled]=\"isProcessing\"\r\n (click)=\"onEdit(visit)\">{{'Edit' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" [disabled]=\"isProcessing\"\r\n (click)=\"onDelete(visit)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n <div *ngIf=\"visitForm\">\r\n <form (ngSubmit)=\"onSubmitVisit()\" [formGroup]=\"visitForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"name\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Reference 3D model' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" [readonly]=\"isEditing\"\r\n [class.is-invalid]=\"model3D.invalid && visitSubmitted\" required\r\n formControlName=\"model3D\">\r\n <div class=\"invalid-feedback\">\r\n <ngb-alert data-testid=\"new-location-name-invalid\" [dismissible]=\"false\" type=\"danger\" \r\n *ngIf=\"validatorsService.isControlError(visitForm.controls['name']) \r\n || isFormError(visitForm.controls['name'])\">\r\n {{validatorsService.getError(visitForm.controls['name']) | translate}}\r\n </ngb-alert>\r\n </div>\r\n <div *ngIf=\"isEditing\" class=\"text-danger\">\r\n {{'Cannot change 3D model reference. Please add new model.' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Viewer' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"viewer\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Capture Date' | translate}}</label>\r\n <div class=\"input-group\">\r\n <input class=\"form-control\" placeholder=\"dd/mm/yyyy\" [(ngModel)]=\"captureDate\" ngbDatepicker\r\n #d1=\"ngbDatepicker\" [ngModelOptions]=\"{standalone: true}\">\r\n <div class=\"input-group-append\">\r\n <button class=\"btn btn-outline-secondary calendar\" (click)=\"d1.toggle()\"\r\n type=\"button\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <button type=\"submit\" class=\"btn btn-outline-primary rounded-pill me-2\">{{'Save' |\r\n translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill\">{{'Cancel' |\r\n translate}}</button>\r\n <div class=\"invalid-feedback\" *ngIf=\"errorForm\">\r\n <ngb-alert data-testid=\"new-location-form-invalid\" [dismissible]=\"false\" type=\"danger\">\r\n {{'errorForm.infoBtn' |translate}}\r\n \r\n </ngb-alert>\r\n </div>\r\n </form>\r\n </div>\r\n <div *ngIf=\"!visitForm\">\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onAddVisit()\">{{'Add 3D visit' |\r\n translate}}</button>\r\n </div>\r\n </div>\r\n <div id=\"viewer-frame\" style=\"width: 100%; aspect-ratio: 2/1;\"></div>\r\n </div>\r\n <ng-template #content let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\" id=\"modal-basic-title\">{{'Importing Data' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">\u00D7</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'Please do not leave or refresh this page...' | translate}}\r\n <div *ngIf=\"totalImages != 0\">Imported {{imagesProcessed}} out of {{totalImages}} images.</div>\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" [disabled]=\"!canCancelImport\"\r\n (click)=\"modal.close('Cancel click')\">{{'Cancel import of images' | translate}}</button>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".col-form-label{width:180px;margin-bottom:1rem}.btn-outline-primary{width:200px;margin-right:1rem}.input-group{width:83%;height:-moz-fit-content;height:fit-content}.main-form-container{width:60vw;display:flex;flex-direction:column}@media screen and (max-width: 765px){.main-form-container{width:90vw}}.main-form-container .form-container{width:100%}\n"] }]
1754
- }], ctorParameters: function () { return [{ type: i1$2.UntypedFormBuilder }, { type: i2.MatterportImportService }, { type: i2.CaptureService }, { type: i2.NodeService }, { type: i2.SpaceService }, { type: i1.ActivatedRoute }, { type: i4$1.NgbModal }, { type: i2.VisitService }, { type: i2.ValidatorsService }, { type: i3.TranslateService }, { type: i2.NavigatorService }, { type: i1.Router }]; }, propDecorators: { content: [{
1755
- type: ViewChild,
1756
- args: ['content', { static: false }]
1757
- }] } });
1758
-
1759
- class CarouselComponent {
1760
- constructor() {
1761
- this.currentScan = new EventEmitter();
1762
- }
1763
- ngOnInit() {
1764
- this.currentScan.emit(0);
1765
- }
1766
- onSlide(event) {
1767
- this.dataEvent = JSON.stringify(event);
1768
- const imageIndex = Number.parseInt(event.current.replace("slideId_", ""), 10);
1769
- this.currentScan.emit(imageIndex);
1770
- }
1771
- }
1772
- CarouselComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1773
- CarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CarouselComponent, selector: "lib-carousel", inputs: { images: "images" }, outputs: { currentScan: "currentScan" }, ngImport: i0, template: "<ngb-carousel [interval]=\"5000\" *ngIf=\"images && images.length > 1\" (slide)=\"onSlide($event)\">\r\n <ng-template *ngFor=\"let image of images; let i = index\" ngbSlide [id]=\"'slideId_' + i\">\r\n <div class=\"picsum-img-wrapper\">\r\n <img [src]=\"image.path\" alt=\"Scan\" class=\"d-block w-100\">\r\n </div>\r\n <div class=\"carousel-caption\">\r\n <h3>{{image.title}}</h3>\r\n <p>{{image.description}}</p>\r\n </div>\r\n </ng-template>\r\n</ngb-carousel>\r\n\r\n<img *ngIf=\"images.length === 1\" [src]=\"images[0].path\" alt=\"Scan\" class=\"d-block w-100\">\r\n", styles: [""], dependencies: [{ kind: "component", type: i4$1.NgbCarousel, selector: "ngb-carousel", inputs: ["animation", "activeId", "interval", "wrap", "keyboard", "pauseOnHover", "pauseOnFocus", "showNavigationArrows", "showNavigationIndicators"], outputs: ["slide", "slid"], exportAs: ["ngbCarousel"] }, { kind: "directive", type: i4$1.NgbSlide, selector: "ng-template[ngbSlide]", inputs: ["id"], outputs: ["slid"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
1774
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CarouselComponent, decorators: [{
1775
- type: Component,
1776
- args: [{ selector: 'lib-carousel', template: "<ngb-carousel [interval]=\"5000\" *ngIf=\"images && images.length > 1\" (slide)=\"onSlide($event)\">\r\n <ng-template *ngFor=\"let image of images; let i = index\" ngbSlide [id]=\"'slideId_' + i\">\r\n <div class=\"picsum-img-wrapper\">\r\n <img [src]=\"image.path\" alt=\"Scan\" class=\"d-block w-100\">\r\n </div>\r\n <div class=\"carousel-caption\">\r\n <h3>{{image.title}}</h3>\r\n <p>{{image.description}}</p>\r\n </div>\r\n </ng-template>\r\n</ngb-carousel>\r\n\r\n<img *ngIf=\"images.length === 1\" [src]=\"images[0].path\" alt=\"Scan\" class=\"d-block w-100\">\r\n" }]
1777
- }], ctorParameters: function () { return []; }, propDecorators: { images: [{
1778
- type: Input
1779
- }], currentScan: [{
1780
- type: Output
1781
- }] } });
1782
-
1783
- var SweepState;
1784
- (function (SweepState) {
1785
- SweepState[SweepState["ADDED"] = 0] = "ADDED";
1786
- SweepState[SweepState["REMOVED"] = 1] = "REMOVED";
1787
- SweepState[SweepState["DISABLED"] = 2] = "DISABLED";
1788
- SweepState[SweepState["OCCUPIED"] = 3] = "OCCUPIED";
1789
- SweepState[SweepState["STARTPOINT"] = 4] = "STARTPOINT";
1790
- })(SweepState || (SweepState = {}));
1791
- function isInPolygon(p, polygon) {
1792
- let isInside = false;
1793
- let minX = polygon[0].x;
1794
- let maxX = polygon[0].x;
1795
- let minY = polygon[0].y;
1796
- let maxY = polygon[0].y;
1797
- for (let n = 1; n < polygon.length; n++) {
1798
- const q = polygon[n];
1799
- minX = Math.min(q.x, minX);
1800
- maxX = Math.max(q.x, maxX);
1801
- minY = Math.min(q.y, minY);
1802
- maxY = Math.max(q.y, maxY);
1803
- }
1804
- if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY) {
1805
- return false;
1806
- }
1807
- for (let index = 0, index_ = polygon.length - 1; index < polygon.length; index_ = index++) {
1808
- if (polygon[index].y > p.y !== polygon[index_].y > p.y &&
1809
- p.x <
1810
- ((polygon[index_].x - polygon[index].x) *
1811
- (p.y - polygon[index].y)) /
1812
- (polygon[index_].y - polygon[index].y) +
1813
- polygon[index].x) {
1814
- isInside = !isInside;
1815
- }
1816
- }
1817
- return isInside;
1818
- }
1819
- function rotate(point, center, angle) {
1820
- let xM;
1821
- let yM;
1822
- let x;
1823
- let y;
1824
- angle *= Math.PI / 180;
1825
- xM = point.x - center.x;
1826
- yM = point.y - center.y;
1827
- x = xM * Math.cos(angle) + yM * Math.sin(angle) + center.x;
1828
- y = -xM * Math.sin(angle) + yM * Math.cos(angle) + center.y;
1829
- return { x: Math.round(x), y: Math.round(y) };
1830
- }
1831
- /**
1832
- * Check if an HtmlElement is inside a selection
1833
- * @param button HTMLElement
1834
- * @param selection
1835
- * @returns true if the element is inside the selection, false otherwise
1836
- */
1837
- function buttonIsInSelection(button, selection) {
1838
- const bounds = button.getBoundingClientRect();
1839
- return (bounds.bottom > selection.top &&
1840
- bounds.top < selection.top + selection.height &&
1841
- bounds.right > selection.left &&
1842
- bounds.left < selection.left + selection.width);
1843
- }
1844
- /**
1845
- * Styles the button that represents a sweep on the plan: green-added to zone, red -not added, gray - disabled, orange - occupied
1846
- * @param button HTMLButtonElement, button on the plan,
1847
- * @param isAdded boolean, if the sweep added to the zone
1848
- * @param isOccupied boolean, if the sweep added to any other zone (but not current)
1849
- */
1850
- function styleButton(button, state) {
1851
- switch (state) {
1852
- case SweepState.ADDED:
1853
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
1854
- break;
1855
- case SweepState.DISABLED:
1856
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=black&height=17&width=17")`;
1857
- button.style.cursor = "auto";
1858
- break;
1859
- case SweepState.OCCUPIED:
1860
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
1861
- break;
1862
- case SweepState.STARTPOINT:
1863
- button.style.backgroundImage = `url('https://api.iconify.design/ic/baseline-flag-circle.svg?color=white&width=17&height=17')`;
1864
- break;
1865
- case SweepState.REMOVED:
1866
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
1867
- break;
1868
- default:
1869
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
1870
- break;
1871
- }
1872
- // if (disabled) {
1873
- // button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=#636363&height=17&width=17")`;
1874
- // button.style.cursor = "auto";
1875
- // } else if (isOccupied) {
1876
- // button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
1877
- // } else {
1878
- // button.style.backgroundImage = isAdded
1879
- // ? `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`
1880
- // : `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
1881
- // }
1882
- button.style.backgroundColor = "transparent";
1883
- button.style.position = "absolute";
1884
- button.style.border = "none";
1885
- button.style.width = "17px";
1886
- button.style.height = "17px";
1887
- button.disabled = false;
1888
- button.type = "button";
1889
- }
1890
- /**
1891
- * Check if sweep (button) is chosen; it is reprsented by image style "mdi:adjust"
1892
- * @param button HTMLElement
1893
- * @returns boolean, if button was selected
1894
- */
1895
- function buttonIsChosen(button) {
1896
- return button.style.backgroundImage.includes("adjust");
1897
- }
1898
- /**
1899
- * Visually change the state of a scan button, a selected button is blue
1900
- * @param button HTMLElement
1901
- * @param selected if true the button will be blue, otherwise it will red or green
1902
- */
1903
- function setVisuallySelected(button, selected) {
1904
- if (selected) {
1905
- /** Color in blue */
1906
- button.style.backgroundImage = button.style.backgroundImage
1907
- .replace("red", "blue")
1908
- .replace("green", "blue");
1909
- }
1910
- else {
1911
- /** Get back in red or green */
1912
- const color = buttonIsChosen(button) ? "green" : "red";
1913
- button.style.backgroundImage = button.style.backgroundImage.replace("blue", color);
1914
- }
1915
- }
1916
-
1917
- class SelectionComponent {
1918
- constructor() {
1919
- /**Emit a new selection */
1920
- this.onSelectionChanged = new EventEmitter();
1921
- this.isMousedown = false;
1922
- this.selection = { startX: 0, startY: 0, endX: 0, endY: 0 };
1923
- this.selectionRectangle = { top: 0, left: 0, width: 0, height: 0 };
1924
- }
1925
- ngOnInit() {
1926
- this.selectionableZone = document.querySelector(".selectZone");
1927
- this.selectionElement = document.querySelector("#selection");
1928
- this.selectionableZone.addEventListener("mousedown", this.mousedown.bind(this));
1929
- this.selectionableZone.addEventListener("mousemove", this.mousemove.bind(this));
1930
- this.selectionableZone.addEventListener("mouseup", this.mouseup.bind(this));
1931
- }
1932
- /**
1933
- * Update the current selection
1934
- * Will update the selectionRectangle and Selection HTML element
1935
- * @param shouldEmit if true an event will be emitted through onSelectionChanged (true by default)
1936
- */
1937
- updateSelectionElement(shouldEmit = true) {
1938
- this.selectionRectangle.width = Math.abs(this.selection.endX - this.selection.startX);
1939
- this.selectionRectangle.height = Math.abs(this.selection.endY - this.selection.startY);
1940
- this.selectionRectangle.top = Math.min(this.selection.endY, this.selection.startY);
1941
- this.selectionRectangle.left = Math.min(this.selection.endX, this.selection.startX);
1942
- this.selectionElement.style.top = `${this.selectionRectangle.top}px`;
1943
- this.selectionElement.style.left = `${this.selectionRectangle.left}px`;
1944
- this.selectionElement.style.width = `${this.selectionRectangle.width}px`;
1945
- this.selectionElement.style.height = `${this.selectionRectangle.height}px`;
1946
- if (shouldEmit) {
1947
- this.onSelectionChanged.emit(this.selectionRectangle);
1948
- }
1949
- }
1950
- /**
1951
- * Trigger when mouse is press down on selectionableZone
1952
- * @param event
1953
- */
1954
- mousedown(event) {
1955
- if (event.button !== 2) { /**Selection with the right click, so ignore all other event */
1956
- return;
1957
- }
1958
- this.isMousedown = true;
1959
- this.selection = { startY: event.clientY, startX: event.clientX, endX: event.clientX, endY: event.clientY };
1960
- this.updateSelectionElement();
1961
- }
1962
- /**
1963
- * Trigger when mouse is release on selectionableZone
1964
- * @param event
1965
- */
1966
- mouseup(event) {
1967
- this.isMousedown = false;
1968
- this.selection = { startX: 0, startY: 0, endX: 0, endY: 0 };
1969
- this.updateSelectionElement(false);
1970
- }
1971
- /**
1972
- * Trigger when mouse is moving on selectionableZone
1973
- * @param event
1974
- */
1975
- mousemove(event) {
1976
- if (this.isMousedown) {
1977
- this.selection.endX = event.clientX;
1978
- this.selection.endY = event.clientY;
1979
- this.updateSelectionElement();
1980
- }
1981
- }
1982
- }
1983
- SelectionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SelectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1984
- SelectionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SelectionComponent, selector: "lib-selection", outputs: { onSelectionChanged: "onSelectionChanged" }, ngImport: i0, template: "<ng-content></ng-content>\r\n\r\n<div id=\"selection\"></div>", styles: ["#selection{will-change:top,left,width,height;top:0;left:0;position:fixed;display:block;margin-top:0;margin-left:0;width:0px;height:0px;background:rgba(83,182,187,.3);border-radius:.15em;border:.15em solid rgba(83,182,187,.8);pointer-events:none}\n"] });
1985
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SelectionComponent, decorators: [{
1986
- type: Component,
1987
- args: [{ selector: 'lib-selection', template: "<ng-content></ng-content>\r\n\r\n<div id=\"selection\"></div>", styles: ["#selection{will-change:top,left,width,height;top:0;left:0;position:fixed;display:block;margin-top:0;margin-left:0;width:0px;height:0px;background:rgba(83,182,187,.3);border-radius:.15em;border:.15em solid rgba(83,182,187,.8);pointer-events:none}\n"] }]
1988
- }], ctorParameters: function () { return []; }, propDecorators: { onSelectionChanged: [{
1989
- type: Output
1990
- }] } });
1991
-
1992
- class RadioButtonComponent {
1993
- constructor() {
1994
- this.isCheckedEvent = new EventEmitter();
1995
- }
1996
- ngOnInit() {
1997
- this.isChecked = false;
1998
- }
1999
- onChecked() {
2000
- this.isCheckedEvent.emit(this.isChecked);
2001
- }
2002
- }
2003
- RadioButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RadioButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2004
- RadioButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RadioButtonComponent, selector: "lib-radio-button", inputs: { label: "label" }, outputs: { isCheckedEvent: "isCheckedEvent" }, ngImport: i0, template: "<div class=\"checkboxContainer\">\r\n <div class=\"switchContainer\">\r\n <label class=\"switch switch-success\">\r\n <input type=\"checkbox\" [(ngModel)]=\"isChecked\" (change)=\"onChecked()\">\r\n <span class=\"slider round\"></span>\r\n </label>\r\n </div>\r\n <span class=\"label right\">{{label | translate}}</span>\r\n</div>", styles: [".checkboxContainer{display:flex;flex-direction:row;align-items:center;width:calc(20vw + 1rem)}.checkboxContainer .label{margin-left:1rem}.checkboxContainer .switch{position:relative;display:inline-block;cursor:pointer;width:60px;height:34px;border-radius:34px}.checkboxContainer .switch input{opacity:0;width:0;height:0}.checkboxContainer .switch input:checked+.slider{background-color:#404660;box-shadow:4px 4px 10px #40466080}.checkboxContainer .switch input:checked+.slider:before{background:white;transform:translate(26px)}.checkboxContainer .switch .label{position:absolute;top:7px}.checkboxContainer .switch .label.right{left:60px;margin-left:10px}.checkboxContainer .switch .slider{position:absolute;cursor:pointer;inset:0;border:1px solid #404660;transition:.3s;border-radius:34px}.checkboxContainer .switch .slider:before:hover{background-color:#fff}.checkboxContainer .switch .slider:before{position:absolute;content:\"\";height:26px;width:26px;left:4px;bottom:3px;background-color:#404660;transition:.3s;border-radius:50%}.checkboxContainer .switch.switch-success input:checked+.slider{background-color:var(--smarterplan-primary);box-shadow:2px 2px 10px 0 var(--smarterplan-primary)}.checkboxContainer .switch.switch-success .slider{border:1px solid var(--smarterplan-primary)}.checkboxContainer .switch.switch-success .slider:before{background-color:var(--smarterplan-primary);box-shadow:2px 2px 10px 0 var(--smarterplan-primary)}.checkboxContainer .switch.switch-default input:checked+.slider{background-color:#636983;box-shadow:2px 2px 10px #636983}.checkboxContainer .switch.switch-default .slider{border:1px solid #636983}.checkboxContainer .switch.switch-default .slider:before{background-color:#636983;box-shadow:2px 2px 10px #636983}.checkboxContainer .switch.switch-warning input:checked+.slider{background-color:#973c3c;box-shadow:2px 2px 10px #ff9898}.checkboxContainer .switch.switch-warning .slider{border:1px solid #973c3c}.checkboxContainer .switch.switch-warning .slider:before{background-color:#973c3c;box-shadow:2px 2px 10px #ff9898}.checkboxContainer .switch.switch-dark input:checked+.slider{background-color:#505050;box-shadow:2px 2px 10px #9d9d9d}.checkboxContainer .switch.switch-dark .slider{border:1px solid #505050}.checkboxContainer .switch.switch-dark .slider:before{background-color:#505050;box-shadow:2px 2px 10px #9d9d9d}\n"], dependencies: [{ kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
2005
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RadioButtonComponent, decorators: [{
2006
- type: Component,
2007
- args: [{ selector: 'lib-radio-button', template: "<div class=\"checkboxContainer\">\r\n <div class=\"switchContainer\">\r\n <label class=\"switch switch-success\">\r\n <input type=\"checkbox\" [(ngModel)]=\"isChecked\" (change)=\"onChecked()\">\r\n <span class=\"slider round\"></span>\r\n </label>\r\n </div>\r\n <span class=\"label right\">{{label | translate}}</span>\r\n</div>", styles: [".checkboxContainer{display:flex;flex-direction:row;align-items:center;width:calc(20vw + 1rem)}.checkboxContainer .label{margin-left:1rem}.checkboxContainer .switch{position:relative;display:inline-block;cursor:pointer;width:60px;height:34px;border-radius:34px}.checkboxContainer .switch input{opacity:0;width:0;height:0}.checkboxContainer .switch input:checked+.slider{background-color:#404660;box-shadow:4px 4px 10px #40466080}.checkboxContainer .switch input:checked+.slider:before{background:white;transform:translate(26px)}.checkboxContainer .switch .label{position:absolute;top:7px}.checkboxContainer .switch .label.right{left:60px;margin-left:10px}.checkboxContainer .switch .slider{position:absolute;cursor:pointer;inset:0;border:1px solid #404660;transition:.3s;border-radius:34px}.checkboxContainer .switch .slider:before:hover{background-color:#fff}.checkboxContainer .switch .slider:before{position:absolute;content:\"\";height:26px;width:26px;left:4px;bottom:3px;background-color:#404660;transition:.3s;border-radius:50%}.checkboxContainer .switch.switch-success input:checked+.slider{background-color:var(--smarterplan-primary);box-shadow:2px 2px 10px 0 var(--smarterplan-primary)}.checkboxContainer .switch.switch-success .slider{border:1px solid var(--smarterplan-primary)}.checkboxContainer .switch.switch-success .slider:before{background-color:var(--smarterplan-primary);box-shadow:2px 2px 10px 0 var(--smarterplan-primary)}.checkboxContainer .switch.switch-default input:checked+.slider{background-color:#636983;box-shadow:2px 2px 10px #636983}.checkboxContainer .switch.switch-default .slider{border:1px solid #636983}.checkboxContainer .switch.switch-default .slider:before{background-color:#636983;box-shadow:2px 2px 10px #636983}.checkboxContainer .switch.switch-warning input:checked+.slider{background-color:#973c3c;box-shadow:2px 2px 10px #ff9898}.checkboxContainer .switch.switch-warning .slider{border:1px solid #973c3c}.checkboxContainer .switch.switch-warning .slider:before{background-color:#973c3c;box-shadow:2px 2px 10px #ff9898}.checkboxContainer .switch.switch-dark input:checked+.slider{background-color:#505050;box-shadow:2px 2px 10px #9d9d9d}.checkboxContainer .switch.switch-dark .slider{border:1px solid #505050}.checkboxContainer .switch.switch-dark .slider:before{background-color:#505050;box-shadow:2px 2px 10px #9d9d9d}\n"] }]
2008
- }], ctorParameters: function () { return []; }, propDecorators: { label: [{
2009
- type: Input
2010
- }], isCheckedEvent: [{
2011
- type: Output
2012
- }] } });
2013
-
2014
- class PlanLegendComponent {
2015
- constructor(translate) {
2016
- this.translate = translate;
2017
- this.isAudioZone = false;
2018
- this.buttonsToRender = [];
2019
- this.colorToText = {};
2020
- }
2021
- ngOnInit() {
2022
- return __awaiter(this, void 0, void 0, function* () {
2023
- this.render();
2024
- });
2025
- }
2026
- render() {
2027
- return __awaiter(this, void 0, void 0, function* () {
2028
- this.buttonsToRender = [
2029
- {
2030
- url: `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`,
2031
- text: this.translate.instant("legend.green")
2032
- },
2033
- {
2034
- url: `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`,
2035
- text: this.translate.instant("legend.red")
2036
- }
2037
- ];
2038
- if (this.isAudioZone) {
2039
- let audioPoints = [{
2040
- url: `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=black&height=17&width=17")`,
2041
- text: this.translate.instant("legend.black")
2042
- },
2043
- {
2044
- url: `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`,
2045
- text: this.translate.instant("legend.orange")
2046
- }];
2047
- this.buttonsToRender = this.buttonsToRender.concat(audioPoints);
2048
- }
2049
- });
2050
- }
2051
- }
2052
- PlanLegendComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PlanLegendComponent, deps: [{ token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
2053
- PlanLegendComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PlanLegendComponent, selector: "lib-plan-legend", inputs: { isAudioZone: "isAudioZone" }, ngImport: i0, template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\r\n <h5>{{\"legend.title\" | translate}}</h5>\r\n <div class=\"legendBox\">\r\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\r\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\r\n <span>{{elemnt.text}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#FFF}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
2054
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PlanLegendComponent, decorators: [{
2055
- type: Component,
2056
- args: [{ selector: 'lib-plan-legend', template: "<div class=\"mt-3 ms-3\" class=\"legendContainer\">\r\n <h5>{{\"legend.title\" | translate}}</h5>\r\n <div class=\"legendBox\">\r\n <div class=\"legendRow\" *ngFor=\"let elemnt of buttonsToRender\">\r\n <button class=\"legendIcon\" [ngStyle] = \"{'background-image': elemnt.url}\"></button>\r\n <span>{{elemnt.text}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".legendContainer{padding:1rem;border:solid var(--smarterplan-primary) 2px;border-radius:6px;width:100%;margin-bottom:.5rem;background:#FFF}.legendContainer .legendBox{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.legendContainer .legendBox .legendRow{display:flex;flex-direction:row;align-items:center}.legendContainer .legendBox .legendRow .legendIcon{width:2.5rem;height:2.5rem;background-repeat:no-repeat;background-size:cover;border:none;background-color:transparent;margin-right:.5rem;cursor:auto}.legendContainer .legendBox .legendRow span{margin-right:1rem;cursor:auto}.legendContainer .legendBox .legendRow h5{cursor:auto}\n"] }]
2057
- }], ctorParameters: function () { return [{ type: i3.TranslateService }]; }, propDecorators: { isAudioZone: [{
2058
- type: Input
2059
- }] } });
2060
-
2061
- class SweepPlanSelectionComponent {
2062
- constructor(zoneService, navigationService, planService, translate) {
2063
- this.zoneService = zoneService;
2064
- this.navigationService = navigationService;
2065
- this.planService = planService;
2066
- this.translate = translate;
2067
- this.chosenScansOnPlan = [];
2068
- this.navIDsZoneEdit = [];
2069
- // sweeps belonging to any audio zone
2070
- this.occupiedSweeps = [];
2071
- // sweeps unavailable (cannot be chosen)
2072
- this.unavailableSweeps = [];
2073
- // if choosing sweeps for audio zone
2074
- this.editingAudioZone = false;
2075
- this.multipleFloors = false;
2076
- /** all scan buttons Element */
2077
- this.buttonElements = [];
2078
- /** Scan buttons that are in the current selection */
2079
- this.buttonsInSelection = [];
2080
- this.sweepsSelected = new EventEmitter();
2081
- this.isSettingStartSweep = false;
2082
- this.chosenSweepsPerFloor = new Map(); // map matching floorID to sweeps selected
2083
- this.inputSweepsPerFloor = new Map(); // map matching floorID to sweeps selected for zone in edition
2084
- this.selectionChanged = false;
2085
- }
2086
- ngOnInit() {
2087
- return __awaiter(this, void 0, void 0, function* () {
2088
- yield this.getPlans();
2089
- this.setSweepsOfInputZone();
2090
- });
2091
- }
2092
- ngOnChanges() {
2093
- if (this.chosenPlan) {
2094
- this.setSweepsOfInputZone();
2095
- this.chosenScansOnPlan = [];
2096
- this.clearDivPlan();
2097
- this.addScanPoints();
2098
- }
2099
- }
2100
- setSweepsOfInputZone() {
2101
- this.navIDsZoneEdit = this.inputZone ? this.inputZone.sweepIDs : [];
2102
- if (this.multipleFloors) {
2103
- this.plans.forEach((plan) => {
2104
- if (!this.inputSweepsPerFloor.get(plan.zoneID)) {
2105
- this.inputSweepsPerFloor.set(plan.zoneID, this.navIDsZoneEdit.filter((sweep) => plan.zone.sweepIDs.includes(sweep)));
2106
- }
2107
- });
2108
- }
2109
- else {
2110
- if (this.inputZone) {
2111
- //filter plans only for the parent Zone
2112
- this.plans = this.plans.filter((p) => p.zoneID === this.inputZone.parentID);
2113
- }
2114
- }
2115
- }
2116
- getPlans() {
2117
- return __awaiter(this, void 0, void 0, function* () {
2118
- this.plans = yield this.planService.getSingedPlansForSpace(this.spaceID);
2119
- });
2120
- }
2121
- onPlanClick(plan) {
2122
- return __awaiter(this, void 0, void 0, function* () {
2123
- const switchPlan = () => {
2124
- this.selectionChanged = false;
2125
- this.chosenPlan = plan;
2126
- this.chosenScansOnPlan = [];
2127
- this.clearDivPlan();
2128
- this.addScanPoints();
2129
- };
2130
- if (this.selectionChanged) {
2131
- const message = this.translate.instant("confirm.cancelModifZoneSweeps");
2132
- if (window.confirm(message)) {
2133
- switchPlan();
2134
- }
2135
- }
2136
- else {
2137
- switchPlan();
2138
- }
2139
- });
2140
- }
2141
- addScanPoints() {
2142
- return __awaiter(this, void 0, void 0, function* () {
2143
- let wasModified = false;
2144
- if (this.multipleFloors) {
2145
- // check if we have already validated buttons for this floor
2146
- if (this.chosenSweepsPerFloor.get(this.chosenPlan.zoneID)) {
2147
- this.chosenScansOnPlan = this.chosenSweepsPerFloor.get(this.chosenPlan.zoneID);
2148
- wasModified = true;
2149
- }
2150
- }
2151
- this.divPlan = document.querySelector("#planDiv");
2152
- const zoneOfPlan = yield this.zoneService.getZone(this.chosenPlan.zoneID);
2153
- const navigations = yield this.navigationService.getNavigationsForZone(zoneOfPlan);
2154
- if (this.newZoneData)
2155
- yield this.setScanByDraw(navigations);
2156
- this.buttonElements = yield showScanPointsOnPlanInDiv(this.chosenPlan, this.divPlan, navigations);
2157
- for (const element of this.buttonElements) {
2158
- if (this.unavailableSweeps && this.unavailableSweeps.includes(element.id)) {
2159
- styleButton(element, SweepState.DISABLED);
2160
- }
2161
- else {
2162
- if (wasModified) {
2163
- if (this.chosenScansOnPlan.includes(element.id)) {
2164
- styleButton(element, SweepState.ADDED);
2165
- }
2166
- else {
2167
- styleButton(element, SweepState.REMOVED);
2168
- }
2169
- }
2170
- else {
2171
- if (this.navIDsZoneEdit.length > 0 &&
2172
- this.navIDsZoneEdit.includes(element.id)) {
2173
- styleButton(element, SweepState.ADDED);
2174
- if (!this.chosenScansOnPlan.includes(element.id)) {
2175
- this.chosenScansOnPlan.push(element.id);
2176
- }
2177
- }
2178
- else if (this.occupiedSweeps && this.occupiedSweeps.includes(element.id)) {
2179
- styleButton(element, SweepState.OCCUPIED);
2180
- }
2181
- else {
2182
- styleButton(element, SweepState.REMOVED);
2183
- }
2184
- }
2185
- //start point should be last condition
2186
- if (this.inputZone && this.inputZone.startSweepID === element.id) {
2187
- console.log("setting start point");
2188
- styleButton(element, SweepState.STARTPOINT);
2189
- }
2190
- element.addEventListener("click", (event) => this.onButtonScanClicked(event.target));
2191
- }
2192
- }
2193
- this.panZoom = panzoom(this.divPlan, {
2194
- bounds: true,
2195
- boundsPadding: 0,
2196
- maxZoom: 3.5,
2197
- beforeMouseDown(e) {
2198
- return (e.button === 2); /** Ignore event for right click (use for selecting) */
2199
- },
2200
- });
2201
- if (this.multipleFloors) {
2202
- this.chosenSweepsPerFloor.set(this.chosenPlan.zoneID, [...this.chosenScansOnPlan]);
2203
- }
2204
- });
2205
- }
2206
- /** Function if we are coming for svg editor workflow */
2207
- setScanByDraw(navigations) {
2208
- return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
2209
- const rect = {
2210
- width: this.newZoneData.width,
2211
- height: this.newZoneData.height,
2212
- };
2213
- const img = yield getMetaForImage(this.chosenPlan.filepath);
2214
- const { coeffX, coeffY } = getCoefficientsForImage(img, rect);
2215
- const draw = this.newZoneData.elements;
2216
- draw.map((element) => __awaiter(this, void 0, void 0, function* () {
2217
- switch (element.nodeName) {
2218
- case "rect":
2219
- yield this.setScanInRect(img, coeffX, coeffY, element, navigations);
2220
- break;
2221
- case "ellipse":
2222
- yield this.setScanInCircle(img, coeffX, coeffY, element, navigations);
2223
- break;
2224
- case "path":
2225
- yield this.setScanInPolygon(img, coeffX, coeffY, element, navigations);
2226
- break;
2227
- default:
2228
- break;
2229
- }
2230
- }));
2231
- resolve();
2232
- }));
2233
- }
2234
- setScanInRect(img, coeffX, coeffY, element, navigations) {
2235
- return __awaiter(this, void 0, void 0, function* () {
2236
- const calibrage = JSON.parse(this.chosenPlan.calibration);
2237
- navigations.map((navigation) => {
2238
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
2239
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
2240
- if (positionOnPlan) {
2241
- const realWidth = img.width / coeffX;
2242
- const realHeight = img.height / coeffY;
2243
- const navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
2244
- const navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
2245
- if (navX > element.x &&
2246
- navX < element.x + element.width &&
2247
- navY > element.y &&
2248
- navY < element.y + element.height &&
2249
- !this.navIDsZoneEdit.includes(navigation.id)) {
2250
- this.navIDsZoneEdit.push(navigation.id);
2251
- }
2252
- }
2253
- // old calibration:
2254
- // const position = JSON.parse(navigation.position);
2255
- // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
2256
- // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
2257
- // if (element.angle) {
2258
- // const rotatePos = rotate(
2259
- // { x: navX, y: navY },
2260
- // { x: element.cx, y: element.cy },
2261
- // element.angle,
2262
- // );
2263
- // navX = rotatePos.x;
2264
- // navY = rotatePos.y;
2265
- // }
2266
- /**
2267
- * TODO calculer la rotation du rectangle
2268
- */
2269
- // if (
2270
- // navX > element.x &&
2271
- // navX < element.x + element.width &&
2272
- // navY > element.y &&
2273
- // navY < element.y + element.height &&
2274
- // !this.navIDsZoneEdit.includes(navigation.id)
2275
- // ) {
2276
- // this.navIDsZoneEdit.push(navigation.id);
2277
- // }
2278
- });
2279
- });
2280
- } // EO
2281
- setScanInCircle(img, coeffX, coeffY, element, navigations) {
2282
- return __awaiter(this, void 0, void 0, function* () {
2283
- const calibrage = JSON.parse(this.chosenPlan.calibration);
2284
- navigations.map(navigation => {
2285
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
2286
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
2287
- if (positionOnPlan) {
2288
- const realWidth = img.width / coeffX;
2289
- const realHeight = img.height / coeffY;
2290
- let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
2291
- let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
2292
- if (element.angle) {
2293
- const rotatePos = rotate({ x: navX, y: navY }, { x: element.cx, y: element.cy }, element.angle);
2294
- navX = rotatePos.x;
2295
- navY = rotatePos.y;
2296
- }
2297
- const valueX = Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
2298
- const valueY = Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
2299
- const result = valueX + valueY;
2300
- if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
2301
- this.navIDsZoneEdit.push(navigation.id);
2302
- }
2303
- }
2304
- // old calibration
2305
- // const position = JSON.parse(navigation.position);
2306
- // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
2307
- // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
2308
- // if (element.angle) {
2309
- // const rotatePos = rotate(
2310
- // { x: navX, y: navY },
2311
- // { x: element.cx, y: element.cy },
2312
- // element.angle,
2313
- // );
2314
- // navX = rotatePos.x;
2315
- // navY = rotatePos.y;
2316
- // }
2317
- // const valueX =
2318
- // Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
2319
- // const valueY =
2320
- // Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
2321
- // const result = valueX + valueY;
2322
- // if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
2323
- // this.navIDsZoneEdit.push(navigation.id);
2324
- // }
2325
- });
2326
- });
2327
- } // EO
2328
- setScanInPolygon(img, coeffX, coeffY, element, navigations) {
2329
- return __awaiter(this, void 0, void 0, function* () {
2330
- const calibrage = JSON.parse(this.chosenPlan.calibration);
2331
- navigations.map((navigation) => __awaiter(this, void 0, void 0, function* () {
2332
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
2333
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
2334
- if (positionOnPlan) {
2335
- const realWidth = img.width / coeffX;
2336
- const realHeight = img.height / coeffY;
2337
- let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
2338
- let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
2339
- const p = {
2340
- x: navX,
2341
- y: navY,
2342
- };
2343
- if (isInPolygon(p, element.segList) &&
2344
- !this.navIDsZoneEdit.includes(navigation.id)) {
2345
- this.navIDsZoneEdit.push(navigation.id);
2346
- }
2347
- }
2348
- // old calibration
2349
- // const position = JSON.parse(navigation.position);
2350
- // const p = {
2351
- // x: (calibrage.offsetX + position.x * calibrage.x) / coeffX,
2352
- // y: (calibrage.offsetY + position.z * calibrage.y) / coeffY,
2353
- // };
2354
- // if (element.angle) {
2355
- // p = this.rotate(
2356
- // p,
2357
- // { x: element.cx, y: element.cy },
2358
- // element.angle,
2359
- // );
2360
- // }
2361
- // if (
2362
- // isInPolygon(p, element.segList) &&
2363
- // !this.navIDsZoneEdit.includes(navigation.id)
2364
- // ) {
2365
- // this.navIDsZoneEdit.push(navigation.id);
2366
- // }
2367
- }));
2368
- });
2369
- }
2370
- clearDivPlan() {
2371
- if (this.divPlan)
2372
- this.divPlan.innerHTML = "";
2373
- }
2374
- /**
2375
- * Trigger each by the selectionComponent when selection change
2376
- * Update the current selected scan buttons
2377
- * @param selection new selection
2378
- */
2379
- onSelectionChanged(selection) {
2380
- const unselectedButtons = [];
2381
- const newSelectedButtons = [];
2382
- /** For each button, decide whether will be add to selected list or unselected list */
2383
- for (const button of this.buttonElements) {
2384
- const isSelected = buttonIsInSelection(button, selection);
2385
- if (this.buttonsInSelection.includes(button)) {
2386
- /** If the button is already in the selected list, we check if it should be unselect */
2387
- if (!isSelected) {
2388
- unselectedButtons.push(button);
2389
- }
2390
- }
2391
- else if (isSelected) {
2392
- newSelectedButtons.push(button);
2393
- }
2394
- }
2395
- /** Visually Update unselected list */
2396
- for (const button of unselectedButtons) {
2397
- setVisuallySelected(button, false);
2398
- }
2399
- /** Visually Update selected list */
2400
- for (const button of newSelectedButtons) {
2401
- setVisuallySelected(button, true);
2402
- }
2403
- /** Remove unselected list */
2404
- this.buttonsInSelection = this.buttonsInSelection.filter((button) => {
2405
- return !unselectedButtons.includes(button);
2406
- });
2407
- /** Add new selected buttons */
2408
- this.buttonsInSelection = [
2409
- ...this.buttonsInSelection,
2410
- ...newSelectedButtons,
2411
- ];
2412
- }
2413
- /**
2414
- * Trigger when the user click to add the selected scans
2415
- */
2416
- onSelectionAdd() {
2417
- for (const button of this.buttonsInSelection) {
2418
- if (!this.chosenScansOnPlan.includes(button.id)) {
2419
- this.onButtonScanClicked(button);
2420
- }
2421
- }
2422
- this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
2423
- }
2424
- /**
2425
- * Trigger when the user click to remove the selected scans
2426
- */
2427
- onSelectionRemove() {
2428
- for (const button of this.buttonsInSelection) {
2429
- if (this.chosenScansOnPlan.includes(button.id)) {
2430
- this.onButtonScanClicked(button);
2431
- }
2432
- }
2433
- this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
2434
- }
2435
- /**
2436
- * Trigger when the user click to select all scans
2437
- */
2438
- onSelectAll() {
2439
- this.buttonsInSelection = [...this.buttonElements];
2440
- for (const button of this.buttonsInSelection) {
2441
- setVisuallySelected(button, true);
2442
- }
2443
- }
2444
- /**
2445
- * Trigger when the user change the size of the scan points
2446
- * @param event
2447
- */
2448
- onChangeScanSize(event) {
2449
- const factor = event.target.value;
2450
- for (const button of this.buttonElements) {
2451
- button.style.transform = `scale(${factor})`;
2452
- }
2453
- }
2454
- /**
2455
- * When a button representing a scan is clicked
2456
- * @param button
2457
- */
2458
- onButtonScanClicked(button) {
2459
- this.selectionChanged = true;
2460
- if (this.isSettingStartSweep) {
2461
- if (this.startSweepID === button.id) {
2462
- // we deselect the starting point
2463
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
2464
- this.startSweepID = null;
2465
- return;
2466
- }
2467
- button.style.backgroundImage = `url('https://api.iconify.design/ic/baseline-flag-circle.svg?color=white&width=17&height=17')`;
2468
- if (!this.chosenScansOnPlan.includes(button.id)) {
2469
- this.chosenScansOnPlan.push(button.id);
2470
- }
2471
- if (this.startSweepID) {
2472
- // we are changing start sweep
2473
- const btnChanged = this.buttonElements.find((btn) => btn.id === this.startSweepID);
2474
- btnChanged.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
2475
- }
2476
- this.startSweepID = button.id;
2477
- return;
2478
- }
2479
- if (!this.chosenScansOnPlan.includes(button.id)) {
2480
- // add to selection
2481
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
2482
- this.chosenScansOnPlan.push(button.id);
2483
- }
2484
- else {
2485
- // remove from selection
2486
- if (this.occupiedSweeps.includes(button.id) && !this.navIDsZoneEdit.includes(button.id)) {
2487
- // the sweep belongs to another zone => set orange
2488
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
2489
- }
2490
- else {
2491
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
2492
- }
2493
- const index = this.chosenScansOnPlan.indexOf(button.id);
2494
- this.chosenScansOnPlan.splice(index, 1);
2495
- }
2496
- }
2497
- onSaveSelection() {
2498
- if (this.multipleFloors) {
2499
- // rassemble all sweeps per floors
2500
- let finalSweeps = [];
2501
- Array.from(this.inputSweepsPerFloor.keys()).forEach(floorID => {
2502
- if (this.chosenSweepsPerFloor.get(floorID)) {
2503
- // the sweeps for this floor were modified, we take them
2504
- finalSweeps = [...finalSweeps, ...this.chosenSweepsPerFloor.get(floorID)];
2505
- }
2506
- else {
2507
- // was not modified, we take the previous values
2508
- finalSweeps = [...finalSweeps, ...this.inputSweepsPerFloor.get(floorID)];
2509
- }
2510
- });
2511
- // console.log("final sweeps", finalSweeps);
2512
- this.sweepsSelected.emit({ "sweeps": finalSweeps, "startSweepID": this.startSweepID });
2513
- }
2514
- else {
2515
- this.sweepsSelected.emit({ "sweeps": this.chosenScansOnPlan, "startSweepID": this.startSweepID });
2516
- }
2517
- }
2518
- onCancel() {
2519
- if (this.selectionChanged) {
2520
- const message = this.translate.instant("confirm.cancelModifZoneSweeps");
2521
- if (window.confirm(message)) {
2522
- this.sweepsSelected.emit(null);
2523
- }
2524
- }
2525
- else {
2526
- this.sweepsSelected.emit(null);
2527
- }
2528
- }
2529
- /**
2530
- * Adds current selection of sweeps for current floor (plan) for multifloor zone.
2531
- * It has to be saved anyway with onSaveSelection!
2532
- */
2533
- onValidateForFloor() {
2534
- if (this.multipleFloors) {
2535
- this.chosenSweepsPerFloor.set(this.chosenPlan.zoneID, [...this.chosenScansOnPlan]);
2536
- this.selectionChanged = false;
2537
- }
2538
- }
2539
- }
2540
- SweepPlanSelectionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SweepPlanSelectionComponent, deps: [{ token: i2.ZoneService }, { token: i2.NavigationService }, { token: i2.PlanService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
2541
- SweepPlanSelectionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: { spaceID: "spaceID", chosenScansOnPlan: "chosenScansOnPlan", newZoneData: "newZoneData", occupiedSweeps: "occupiedSweeps", unavailableSweeps: "unavailableSweeps", editingAudioZone: "editingAudioZone", inputZone: "inputZone", multipleFloors: "multipleFloors" }, outputs: { sweepsSelected: "sweepsSelected" }, usesOnChanges: true, ngImport: i0, template: "<div ngbDropdown class=\"sp-row d-inline-block\">\r\n <div class=\"col-sm-3\" *ngIf=\"plans\">\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenPlan ?\r\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\r\n [disabled]=\"!plan.calibration\">{{ plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"sp-row\">\r\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\r\n <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\r\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\r\n <div class=\"sp-row\">\r\n <div style=\"overflow: hidden;width:100%;\">\r\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </lib-selection>\r\n \r\n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\r\n <div class=\"sp-row d-inline-block\">\r\n <h2>{{'selectTool.title' | translate}}</h2>\r\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <div class=\"col-3\" style=\"padding:0px\">\r\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\r\n </div>\r\n <div class=\"col-9\">\r\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\r\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\r\n </div>\r\n \r\n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\r\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\r\n <div class=\"sp-row\">\r\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sp-row\">\r\n <div *ngIf=\"multipleFloors\"> \r\n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\r\n </div>\r\n <div *ngIf=\"!multipleFloors\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\r\n </div>\r\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\r\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\r\n </div>\r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n \r\n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{border-radius:6px;overflow:hidden;background-color:var(--smarterplan-secondary)}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"], dependencies: [{ kind: "directive", type: i4$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i4$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i4$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i4$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { 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: SelectionComponent, selector: "lib-selection", outputs: ["onSelectionChanged"] }, { kind: "component", type: RadioButtonComponent, selector: "lib-radio-button", inputs: ["label"], outputs: ["isCheckedEvent"] }, { kind: "component", type: PlanLegendComponent, selector: "lib-plan-legend", inputs: ["isAudioZone"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
2542
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SweepPlanSelectionComponent, decorators: [{
2543
- type: Component,
2544
- args: [{ selector: 'lib-sweep-plan-selection', template: "<div ngbDropdown class=\"sp-row d-inline-block\">\r\n <div class=\"col-sm-3\" *ngIf=\"plans\">\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenPlan ?\r\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\r\n [disabled]=\"!plan.calibration\">{{ plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"sp-row\">\r\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\r\n <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\r\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\r\n <div class=\"sp-row\">\r\n <div style=\"overflow: hidden;width:100%;\">\r\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </lib-selection>\r\n \r\n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\r\n <div class=\"sp-row d-inline-block\">\r\n <h2>{{'selectTool.title' | translate}}</h2>\r\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <div class=\"col-3\" style=\"padding:0px\">\r\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\r\n </div>\r\n <div class=\"col-9\">\r\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\r\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\r\n </div>\r\n \r\n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\r\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\r\n <div class=\"sp-row\">\r\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sp-row\">\r\n <div *ngIf=\"multipleFloors\"> \r\n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\r\n </div>\r\n <div *ngIf=\"!multipleFloors\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\r\n </div>\r\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\r\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\r\n </div>\r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n \r\n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{border-radius:6px;overflow:hidden;background-color:var(--smarterplan-secondary)}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"] }]
2545
- }], ctorParameters: function () { return [{ type: i2.ZoneService }, { type: i2.NavigationService }, { type: i2.PlanService }, { type: i3.TranslateService }]; }, propDecorators: { spaceID: [{
2546
- type: Input
2547
- }], chosenScansOnPlan: [{
2548
- type: Input
2549
- }], newZoneData: [{
2550
- type: Input
2551
- }], occupiedSweeps: [{
2552
- type: Input
2553
- }], unavailableSweeps: [{
2554
- type: Input
2555
- }], editingAudioZone: [{
2556
- type: Input
2557
- }], inputZone: [{
2558
- type: Input
2559
- }], multipleFloors: [{
2560
- type: Input
2561
- }], sweepsSelected: [{
2562
- type: Output
2563
- }] } });
2564
-
2565
- class AddZoneComponent {
2566
- constructor(fb, zoneService, layerService, userService, navigationService) {
2567
- this.fb = fb;
2568
- this.zoneService = zoneService;
2569
- this.layerService = layerService;
2570
- this.userService = userService;
2571
- this.navigationService = navigationService;
2572
- this.updatedZone = new EventEmitter();
2573
- this.isMuseumVisit = false;
2574
- this.parentZones = [];
2575
- this.carouselIsVisible = false;
2576
- this.isSubmitted = false;
2577
- this.chosenScans = [];
2578
- this.fromPlan = false;
2579
- this.chosenScansOnPlan = [];
2580
- this.zoneInitialNavCount = 0;
2581
- this.zoneIsMatterportFloor = false;
2582
- this.multipleFloors = false;
2583
- }
2584
- ngOnInit() {
2585
- return __awaiter(this, void 0, void 0, function* () {
2586
- this.parentZones = this.zones.filter((zone) => zone.layer && zone.layer.name === 'FLOOR');
2587
- if (!this.defaultZone) {
2588
- this.defaultZone = this.getDefaultZone();
2589
- }
2590
- this.parentZones.unshift(this.defaultZone);
2591
- yield this.updateLayers();
2592
- this.initZoneForm();
2593
- });
2594
- }
2595
- updateLayers() {
2596
- return __awaiter(this, void 0, void 0, function* () {
2597
- this.currentOrgId = this.userService.currentOrganisation(this.spaceID).id;
2598
- const layers = yield this.layerService.getLayerForOrganisation(this.currentOrgId);
2599
- // filter out layers created by the system
2600
- this.layers = layers.filter((l) => l.name !== 'BUILDING' && l.name !== 'FLOOR');
2601
- });
2602
- }
2603
- initZoneForm() {
2604
- return __awaiter(this, void 0, void 0, function* () {
2605
- if (this.zoneEdit) {
2606
- if (this.zoneEdit.metadata) {
2607
- const metadata = JSON.parse(this.zoneEdit.metadata);
2608
- this.zoneIsMatterportFloor = metadata.hasOwnProperty('matterportFloorSequence');
2609
- }
2610
- const isVirtual = this.zoneService.zoneIsVirtual(this.zoneEdit);
2611
- if (!isVirtual) {
2612
- yield this.loadNavigations();
2613
- }
2614
- this.isMuseumVisit = this.zoneEdit.isMuseumVisitZone === true;
2615
- this.multipleFloors = this.zoneEdit.isMultipleFloorZone === true;
2616
- this.zoneForm = this.fb.group({
2617
- id: this.zoneEdit.id,
2618
- name: [this.zoneEdit.name, [Validators.required]],
2619
- code_ref: this.zoneEdit.code_ref ? this.zoneEdit.code_ref : null,
2620
- layerID: this.zoneEdit.layer ? this.zoneEdit.layer.id : null,
2621
- surface: this.zoneEdit.surface ? this.zoneEdit.surface : 0,
2622
- parentID: this.zoneEdit.parentID,
2623
- parent: { value: this.zoneEdit.parent.name, disabled: true },
2624
- newLayer: [null, [this.layerNameValidator()]],
2625
- isMuseumVisitZone: this.isMuseumVisit,
2626
- startSweepID: this.zoneEdit.startSweepID,
2627
- });
2628
- this.onChangeMultipleFloors();
2629
- }
2630
- else {
2631
- this.zoneForm = this.fb.group({
2632
- name: [
2633
- this.newZoneDataFromEditor ? this.newZoneDataFromEditor.name : '',
2634
- [Validators.required],
2635
- ],
2636
- code_ref: null,
2637
- layerID: null,
2638
- surface: 0,
2639
- parentID: this.defaultZone.id,
2640
- newLayer: [null, [this.layerNameValidator()]],
2641
- isMuseumVisitZone: this.isMuseumVisit,
2642
- startSweepID: null,
2643
- });
2644
- }
2645
- });
2646
- }
2647
- onSubmitZone() {
2648
- return __awaiter(this, void 0, void 0, function* () {
2649
- this.isSubmitted = true;
2650
- if (!this.zoneForm.valid) {
2651
- return;
2652
- }
2653
- const formValue = this.zoneForm.getRawValue(); //because we need values of disables controls as well
2654
- if (formValue.newLayer) {
2655
- yield this.createLayer(formValue.newLayer).then((layer) => {
2656
- formValue.layerID = layer.id;
2657
- });
2658
- }
2659
- const zoneInput = {
2660
- name: formValue.name,
2661
- surface: Math.round(formValue.surface * 100) / 100,
2662
- spaceID: this.spaceID,
2663
- layerID: formValue.layerID,
2664
- parentID: formValue.parentID,
2665
- isMuseumVisitZone: this.isMuseumVisit,
2666
- isMultipleFloorZone: this.multipleFloors,
2667
- sweepIDs: [],
2668
- startSweepID: formValue.startSweepID,
2669
- };
2670
- if (formValue.code_ref) {
2671
- zoneInput.code_ref = formValue.code_ref;
2672
- }
2673
- try {
2674
- this.zoneForm = null;
2675
- this.isSubmitted = false;
2676
- if (this.zoneEdit) {
2677
- const zoneUpdate = zoneInput;
2678
- zoneUpdate.sweepIDs = this.zoneEdit.sweepIDs;
2679
- zoneUpdate.id = formValue.id;
2680
- yield this.setSweepsAndNodeForZoneInput(zoneUpdate);
2681
- yield this.zoneService.updateZone(zoneUpdate);
2682
- this.zoneEdit = null;
2683
- this.updatedZone.emit(zoneUpdate.id);
2684
- }
2685
- else {
2686
- yield this.setSweepsAndNodeForZoneInput(zoneInput);
2687
- if (!zoneInput.parentID) {
2688
- // set building as parent
2689
- zoneInput.parentID = this.defaultZone.id;
2690
- }
2691
- yield this.zoneService.create(zoneInput).then((zoneCreated) => {
2692
- this.updatedZone.emit(zoneCreated.id);
2693
- });
2694
- }
2695
- }
2696
- catch (error) {
2697
- console.error(error);
2698
- }
2699
- });
2700
- }
2701
- onCancel() {
2702
- this.isSubmitted = false;
2703
- this.zoneForm = null;
2704
- this.chosenScansOnPlan = [];
2705
- this.chosenScans = [];
2706
- this.updatedZone.emit(false);
2707
- }
2708
- get name() {
2709
- return this.zoneForm.get('name');
2710
- }
2711
- get newLayer() {
2712
- return this.zoneForm.get('newLayer');
2713
- }
2714
- toggleCarousel() {
2715
- this.carouselIsVisible = true;
2716
- this.chosenScansOnPlan = [];
2717
- }
2718
- togglePlan() {
2719
- this.fromPlan = true;
2720
- this.chosenScans = [];
2721
- }
2722
- onAddScan() {
2723
- if (!this.chosenScans.includes(this.currentScanShowing)) {
2724
- // console.log("adding scan", this.currentScanShowing);
2725
- this.chosenScans.push(this.currentScanShowing);
2726
- }
2727
- else {
2728
- alert('Scan already added!');
2729
- }
2730
- }
2731
- onRemoveScanImage(scan) {
2732
- const index = this.chosenScans.indexOf(scan);
2733
- this.chosenScans.splice(index, 1);
2734
- }
2735
- onRemoveScanPlan(scan) {
2736
- const index = this.chosenScansOnPlan.indexOf(scan);
2737
- this.chosenScansOnPlan.splice(index, 1);
2738
- }
2739
- setSweepsAndNodeForZoneInput(zoneInput) {
2740
- return __awaiter(this, void 0, void 0, function* () {
2741
- if (this.chosenScans.length > 0 &&
2742
- this.chosenScans.length !== this.zoneInitialNavCount &&
2743
- !this.fromPlan) {
2744
- // if we chose scans from the carousel
2745
- const sweepIDs = [];
2746
- this.chosenScans.map((scan) => __awaiter(this, void 0, void 0, function* () {
2747
- const imageUuid = this.images360[scan].filename.split('_')[0];
2748
- const sweepID = this.navigationIDs.find((nav) => {
2749
- return nav.includes(imageUuid);
2750
- });
2751
- if (sweepID) {
2752
- sweepIDs.push(sweepID);
2753
- }
2754
- }));
2755
- zoneInput.sweepIDs = sweepIDs;
2756
- }
2757
- else {
2758
- // we are not coming from gallery choice
2759
- if (this.chosenScansOnPlan.length > 0) {
2760
- zoneInput.sweepIDs = this.chosenScansOnPlan;
2761
- }
2762
- }
2763
- if (zoneInput.sweepIDs && zoneInput.sweepIDs.length > 0) {
2764
- const navForSweep = yield this.navigationService.getNavigationsForMatterportIDForSpace(zoneInput.sweepIDs[0], this.spaceID);
2765
- zoneInput.nodeIDs = [navForSweep[0].nodeID];
2766
- }
2767
- });
2768
- }
2769
- createLayer(name) {
2770
- return __awaiter(this, void 0, void 0, function* () {
2771
- return this.layerService.createLayerForOrganisation(name, this.currentOrgId);
2772
- });
2773
- }
2774
- loadNavigations() {
2775
- return __awaiter(this, void 0, void 0, function* () {
2776
- if (this.zoneEdit.sweepIDs.length > 0) {
2777
- this.zoneInitialNavCount = this.zoneEdit.sweepIDs.length;
2778
- const navList = [];
2779
- const scansZoneEdit = [];
2780
- yield Promise.all(this.zoneEdit.sweepIDs.map((sweepID) => __awaiter(this, void 0, void 0, function* () {
2781
- scansZoneEdit.push(sweepID);
2782
- const index = this.images360.findIndex((im) => {
2783
- return im.filename.includes(sweepID.slice(0, 8));
2784
- });
2785
- if (index !== -1) {
2786
- navList.push(index);
2787
- }
2788
- })));
2789
- this.chosenScans = navList;
2790
- this.chosenScansOnPlan = scansZoneEdit;
2791
- return Promise.resolve();
2792
- }
2793
- return Promise.resolve();
2794
- });
2795
- }
2796
- // iniPlanForDraw() {
2797
- // this.togglePlan();
2798
- // setTimeout(() => {
2799
- // this.onPlanClick();
2800
- // }, 500);
2801
- // }
2802
- /**
2803
- * Adds all sweeps of the space
2804
- */
2805
- onAddAll() {
2806
- const defaultZone = this.getDefaultZone();
2807
- if (defaultZone) {
2808
- this.chosenScansOnPlan = defaultZone.sweepIDs;
2809
- this.zoneForm.get('parentID').setValue(defaultZone.id);
2810
- this.zoneForm.get('parentID').disable();
2811
- this.multipleFloors = true;
2812
- }
2813
- }
2814
- getDefaultZone() {
2815
- return this.zones.find((zone) => zone.layer &&
2816
- zone.layer.name === 'BUILDING' &&
2817
- zone.sweepIDs &&
2818
- zone.sweepIDs.length > 0);
2819
- }
2820
- /**
2821
- * Multiple floors
2822
- */
2823
- onChangeMultipleFloors() {
2824
- if (this.multipleFloors) {
2825
- const defaultZone = this.getDefaultZone();
2826
- if (defaultZone) {
2827
- this.zoneForm.get('parentID').setValue(defaultZone.id);
2828
- this.zoneForm.get('parentID').disable();
2829
- }
2830
- }
2831
- else {
2832
- this.zoneForm.get('parentID').enable();
2833
- }
2834
- }
2835
- onSelectedSweepsFromPlan(result) {
2836
- if (result) {
2837
- if (result.sweeps) {
2838
- this.chosenScansOnPlan = result.sweeps;
2839
- }
2840
- if (result.startSweepID) {
2841
- this.zoneForm.controls.startSweepID.setValue(result.startSweepID);
2842
- }
2843
- }
2844
- this.fromPlan = false;
2845
- }
2846
- layerNameValidator() {
2847
- return (control) => {
2848
- if (!control.value) {
2849
- return null;
2850
- }
2851
- const forbidden = this.layers
2852
- .map((l) => l.name.toLowerCase())
2853
- .includes(control.value.toLowerCase());
2854
- return forbidden ? { forbiddenName: { value: control.value } } : null;
2855
- };
2856
- }
2857
- }
2858
- AddZoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddZoneComponent, deps: [{ token: i1$2.UntypedFormBuilder }, { token: i2.ZoneService }, { token: i2.LayerService }, { token: i2.BaseUserService }, { token: i2.NavigationService }], target: i0.ɵɵFactoryTarget.Component });
2859
- AddZoneComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: AddZoneComponent, selector: "lib-add-zone", inputs: { zoneEdit: "zoneEdit", spaceID: "spaceID", images360: "images360", navigationIDs: "navigationIDs", zones: "zones", newZoneDataFromEditor: "newZoneDataFromEditor", chosenPlan: "chosenPlan", isMuseumVisit: "isMuseumVisit", defaultZone: "defaultZone" }, outputs: { updatedZone: "updatedZone" }, ngImport: i0, template: "<div class=\"main-container\" *ngIf=\"zoneForm\">\r\n <div class=\"col-7\">\r\n <form (ngSubmit)=\"onSubmitZone()\" [formGroup]=\"zoneForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"name\">\r\n <!-- <div class=\"invalid-feedback\">\r\n {{'A name is required' | translate}}\r\n </div> -->\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'codeRef' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"code_ref\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!isMuseumVisit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Type of zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <select class=\"form-control\" formControlName=\"layerID\">\r\n <option value=\"null\" selected disabled hidden> {{ zoneEdit && zoneEdit.layer ?\r\n zoneEdit.layer.name : 'Choose type'}}</option>\r\n <option *ngFor=\"let layer of layers\" [value]=\"layer.id\">\r\n {{ layer.name }}\r\n </option>\r\n </select>\r\n <p class=\"mt-1 new-type-text\">{{'or add new type of zone' | translate }}</p>\r\n <input type=\"text\" class=\"form-control new-type-input\" formControlName=\"newLayer\">\r\n <div *ngIf=\"newLayer.invalid && (newLayer.dirty || newLayer.touched)\" class=\"text-danger\">\r\n <div *ngIf=\"newLayer.errors?.['forbiddenName']\">\r\n {{'Layer exists already' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!--If Editing Zone possibility to assign it to museum itinerary-->\r\n <div class=\"mb-3 row\" *ngIf=\"zoneEdit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Museum Itinerary' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"isMuseumVisit\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneEdit || zoneEdit.isMultipleFloorZone\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Multiple Floors' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"multipleFloors\"\r\n [disabled]=\"zoneEdit !== undefined && zoneEdit !== null\" (change)=\"onChangeMultipleFloors()\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n <div class='text-danger' *ngIf=\"zoneEdit\">\r\n {{'cannotChangeMultifloor' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Parent zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input *ngIf=\"zoneEdit\" type=\"text\" class=\"form-control\" formControlName=\"parent\">\r\n <div class=\"text-danger\" *ngIf=\"zoneEdit\">\r\n {{'cannotChangeParent' | translate}}\r\n </div>\r\n <select *ngIf=\"!zoneEdit\" class=\"form-control\" formControlName=\"parentID\">\r\n <option *ngFor=\"let zone of parentZones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" style=\"max-height: 200px; overflow: auto;\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Scan Points' | translate}}</label>\r\n <!-- <p class=\"col-sm-2\" *ngIf=\"zoneEdit\">{{ zoneEdit.sweepIDs.length }} scans</p> -->\r\n <p class=\"col\" *ngIf=\"chosenScansOnPlan.length === 0 && chosenScans.length === 0\">\r\n {{'No scan points chosen' | translate}}</p>\r\n <div class=\"col-sm-5\" *ngIf=\"chosenScansOnPlan && chosenScansOnPlan.length > 0\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}}</p>\r\n <!-- <div *ngFor=\"let scan of chosenScansOnPlan\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ scan | slice:0:8 }}</p>\r\n <div (click)=\"onRemoveScanPlan(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </div>\r\n <div class=\"col-sm-5\" *ngIf=\"carouselIsVisible && chosenScans && chosenScans.length > 0\">\r\n <p>{{ chosenScans.length }} {{'scan points chosen' | translate}}</p>\r\n <div *ngFor=\"let scan of chosenScans\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ images360[scan].filename }}</p>\r\n <div (click)=\"onRemoveScanImage(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3 mt-3\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <div class=\"col\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"togglePlan()\">{{'Choose scan points on plan' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"toggleCarousel()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'Choose scan points from gallery' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAll()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'add-all-scans' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <!-- <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'No visible scan points' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"noScanPoints\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div> -->\r\n\r\n <div *ngIf=\"carouselIsVisible\" class=\"mb-2\">\r\n <lib-carousel *ngIf=\"images360 && images360.length > 0\" [images]=\"images360\"\r\n (currentScan)=\"currentScanShowing=$event\"></lib-carousel>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2 mt-3\"\r\n (click)=\"onAddScan()\">{{'Add to zone' | translate}}</button>\r\n </div>\r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\"\r\n [disabled]=\"fromPlan || !zoneForm.valid\">{{'Save' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [newZoneData]=\"newZoneDataFromEditor\" [spaceID]=\"spaceID\"\r\n [multipleFloors]=\"multipleFloors\" [inputZone]=\"zoneEdit\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>", styles: [".main-container{display:flex;flex-direction:column}.edit-plan{display:flex;margin:8px 0}.form-range{width:100%}h2{color:var(--smarterplan-primary);padding:0}.col-form-label{margin-bottom:1rem}.btn-outline-primary{margin-right:1rem}.new-type-input{margin-bottom:1rem}.new-type-text{margin-bottom:.5rem}.row{margin:0}p{margin:0;padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px)}button{min-width:80px}\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: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.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: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CarouselComponent, selector: "lib-carousel", inputs: ["images"], outputs: ["currentScan"] }, { kind: "component", type: SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: ["spaceID", "chosenScansOnPlan", "newZoneData", "occupiedSweeps", "unavailableSweeps", "editingAudioZone", "inputZone", "multipleFloors"], outputs: ["sweepsSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
2860
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddZoneComponent, decorators: [{
2861
- type: Component,
2862
- args: [{ selector: 'lib-add-zone', template: "<div class=\"main-container\" *ngIf=\"zoneForm\">\r\n <div class=\"col-7\">\r\n <form (ngSubmit)=\"onSubmitZone()\" [formGroup]=\"zoneForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"name\">\r\n <!-- <div class=\"invalid-feedback\">\r\n {{'A name is required' | translate}}\r\n </div> -->\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'codeRef' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"code_ref\">\r\n </div>\r\n </div>\r\n <div class=\"mb-3 row\" *ngIf=\"!isMuseumVisit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Type of zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <select class=\"form-control\" formControlName=\"layerID\">\r\n <option value=\"null\" selected disabled hidden> {{ zoneEdit && zoneEdit.layer ?\r\n zoneEdit.layer.name : 'Choose type'}}</option>\r\n <option *ngFor=\"let layer of layers\" [value]=\"layer.id\">\r\n {{ layer.name }}\r\n </option>\r\n </select>\r\n <p class=\"mt-1 new-type-text\">{{'or add new type of zone' | translate }}</p>\r\n <input type=\"text\" class=\"form-control new-type-input\" formControlName=\"newLayer\">\r\n <div *ngIf=\"newLayer.invalid && (newLayer.dirty || newLayer.touched)\" class=\"text-danger\">\r\n <div *ngIf=\"newLayer.errors?.['forbiddenName']\">\r\n {{'Layer exists already' | translate}}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!--If Editing Zone possibility to assign it to museum itinerary-->\r\n <div class=\"mb-3 row\" *ngIf=\"zoneEdit && !zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Museum Itinerary' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"isMuseumVisit\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneEdit || zoneEdit.isMultipleFloorZone\">\r\n <label class=\"col-sm-2 col-form-label\">{{ 'Multiple Floors' | translate }}</label>\r\n <div class=\"col-sm-10\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"multipleFloors\"\r\n [disabled]=\"zoneEdit !== undefined && zoneEdit !== null\" (change)=\"onChangeMultipleFloors()\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n <div class='text-danger' *ngIf=\"zoneEdit\">\r\n {{'cannotChangeMultifloor' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Surface' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" formControlName=\"surface\">\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Parent zone' | translate}}</label>\r\n <div class=\"col-sm-10\">\r\n <input *ngIf=\"zoneEdit\" type=\"text\" class=\"form-control\" formControlName=\"parent\">\r\n <div class=\"text-danger\" *ngIf=\"zoneEdit\">\r\n {{'cannotChangeParent' | translate}}\r\n </div>\r\n <select *ngIf=\"!zoneEdit\" class=\"form-control\" formControlName=\"parentID\">\r\n <option *ngFor=\"let zone of parentZones\" [ngValue]=\"zone.id\">\r\n {{ zone.name }}\r\n </option>\r\n </select>\r\n\r\n </div>\r\n </div>\r\n\r\n <div class=\"mb-3 row\" style=\"max-height: 200px; overflow: auto;\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Scan Points' | translate}}</label>\r\n <!-- <p class=\"col-sm-2\" *ngIf=\"zoneEdit\">{{ zoneEdit.sweepIDs.length }} scans</p> -->\r\n <p class=\"col\" *ngIf=\"chosenScansOnPlan.length === 0 && chosenScans.length === 0\">\r\n {{'No scan points chosen' | translate}}</p>\r\n <div class=\"col-sm-5\" *ngIf=\"chosenScansOnPlan && chosenScansOnPlan.length > 0\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}}</p>\r\n <!-- <div *ngFor=\"let scan of chosenScansOnPlan\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ scan | slice:0:8 }}</p>\r\n <div (click)=\"onRemoveScanPlan(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </div>\r\n <div class=\"col-sm-5\" *ngIf=\"carouselIsVisible && chosenScans && chosenScans.length > 0\">\r\n <p>{{ chosenScans.length }} {{'scan points chosen' | translate}}</p>\r\n <div *ngFor=\"let scan of chosenScans\">\r\n <div class=\"row\">\r\n <p class=\"me-2\">{{ images360[scan].filename }}</p>\r\n <div (click)=\"onRemoveScanImage(scan)\" [style.cursor]=\"'pointer'\">\r\n <span class=\"iconify\" data-icon=\"mdi:trash-can-outline\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mb-3 mt-3\" *ngIf=\"!zoneIsMatterportFloor\">\r\n <div class=\"col\">\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"togglePlan()\">{{'Choose scan points on plan' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"toggleCarousel()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'Choose scan points from gallery' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAll()\"\r\n [disabled]=\"fromPlan || !images360 || images360.length === 0\">\r\n {{'add-all-scans' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <!-- <div class=\"mb-3 row\">\r\n <label class=\"col-sm-3 col-form-label\">{{'No visible scan points' | translate}}</label>\r\n <div class=\"col-sm-3\">\r\n <input class=\"checkbox-apply mt-3\" type=\"checkbox\" [(ngModel)]=\"noScanPoints\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </div>\r\n </div> -->\r\n\r\n <div *ngIf=\"carouselIsVisible\" class=\"mb-2\">\r\n <lib-carousel *ngIf=\"images360 && images360.length > 0\" [images]=\"images360\"\r\n (currentScan)=\"currentScanShowing=$event\"></lib-carousel>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2 mt-3\"\r\n (click)=\"onAddScan()\">{{'Add to zone' | translate}}</button>\r\n </div>\r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\"\r\n [disabled]=\"fromPlan || !zoneForm.valid\">{{'Save' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [newZoneData]=\"newZoneDataFromEditor\" [spaceID]=\"spaceID\"\r\n [multipleFloors]=\"multipleFloors\" [inputZone]=\"zoneEdit\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>", styles: [".main-container{display:flex;flex-direction:column}.edit-plan{display:flex;margin:8px 0}.form-range{width:100%}h2{color:var(--smarterplan-primary);padding:0}.col-form-label{margin-bottom:1rem}.btn-outline-primary{margin-right:1rem}.new-type-input{margin-bottom:1rem}.new-type-text{margin-bottom:.5rem}.row{margin:0}p{margin:0;padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px)}button{min-width:80px}\n"] }]
2863
- }], ctorParameters: function () { return [{ type: i1$2.UntypedFormBuilder }, { type: i2.ZoneService }, { type: i2.LayerService }, { type: i2.BaseUserService }, { type: i2.NavigationService }]; }, propDecorators: { zoneEdit: [{
2864
- type: Input
2865
- }], spaceID: [{
2866
- type: Input
2867
- }], images360: [{
2868
- type: Input
2869
- }], navigationIDs: [{
2870
- type: Input
2871
- }], zones: [{
2872
- type: Input
2873
- }], newZoneDataFromEditor: [{
2874
- type: Input
2875
- }], updatedZone: [{
2876
- type: Output
2877
- }], chosenPlan: [{
2878
- type: Input
2879
- }], isMuseumVisit: [{
2880
- type: Input
2881
- }], defaultZone: [{
2882
- type: Input
2883
- }] } });
2884
-
2885
- class AddAudioZoneComponent {
2886
- constructor(fb, zoneService, layerService, userService, navigationService, commentService, translate) {
2887
- this.fb = fb;
2888
- this.zoneService = zoneService;
2889
- this.layerService = layerService;
2890
- this.userService = userService;
2891
- this.navigationService = navigationService;
2892
- this.commentService = commentService;
2893
- this.translate = translate;
2894
- this.updatedZone = new EventEmitter();
2895
- this.isSubmitted = false;
2896
- this.fromPlan = false;
2897
- this.chosenScansOnPlan = [];
2898
- this.isAddingAudio = false;
2899
- this.scansModified = false;
2900
- this.occupiedSweeps = [];
2901
- this.unavailableSweeps = [];
2902
- this.working = false;
2903
- this.audioUploaded = false;
2904
- }
2905
- ngOnInit() {
2906
- if (this.currentAudioZone) {
2907
- // we are editing zone
2908
- this.chosenAudio = this.currentAudioZone.audio;
2909
- this.chosenScansOnPlan = this.currentAudioZone.sweepIDs;
2910
- this.parentZone = this.currentAudioZone.parent;
2911
- }
2912
- this.setup();
2913
- }
2914
- setup() {
2915
- return __awaiter(this, void 0, void 0, function* () {
2916
- const mission = this.userService.currentMission(this.spaceID);
2917
- this.currentOrgId = mission.organisationID;
2918
- let layers = yield this.layerService.getLayerForOrganisation(this.currentOrgId);
2919
- this.audioLayer = layers.find((layer) => layer.name === "AUDIO");
2920
- if (!this.audioLayer) {
2921
- // first time creating Audio Zone
2922
- this.audioLayer = yield this.layerService.createLayerForOrganisation("AUDIO", this.currentOrgId);
2923
- }
2924
- if (!this.parentZone) {
2925
- this.parentZone = this.defaultZone;
2926
- }
2927
- this.audioZones = this.zones.filter((zone) => zone.audioID && zone.parentID === this.parentZone.id);
2928
- this.occupiedSweeps = this.audioZones.flatMap((zone) => zone.sweepIDs);
2929
- // unavailable sweeps: sweeps that do not belong to parent zone
2930
- this.unavailableSweeps = this.defaultZone.sweepIDs.filter((sweep) => !this.parentZone.sweepIDs.includes(sweep));
2931
- yield this.getAudios();
2932
- this.commentForm = this.fb.group({
2933
- title: [null, Validators.required],
2934
- spaceID: this.spaceID,
2935
- type: CommentType.AUDIO,
2936
- ownerID: mission.id,
2937
- });
2938
- });
2939
- }
2940
- onSubmit() {
2941
- return __awaiter(this, void 0, void 0, function* () {
2942
- this.isSubmitted = true;
2943
- this.working = true;
2944
- if (this.currentAudioZone) {
2945
- yield this.zoneService.updateZone({
2946
- id: this.currentAudioZone.id,
2947
- sweepIDs: this.chosenScansOnPlan,
2948
- });
2949
- yield this.removeTakenSweepsFromOtherZones();
2950
- this.updatedZone.emit(this.currentAudioZone.id);
2951
- this.working = false;
2952
- }
2953
- else {
2954
- const zoneInput = {
2955
- name: `${this.parentZone.name} - ${this.chosenAudio.title}`,
2956
- surface: 0,
2957
- spaceID: this.spaceID,
2958
- layerID: this.audioLayer.id,
2959
- parentID: this.parentZone.id,
2960
- isMuseumVisitZone: false,
2961
- isMultipleFloorZone: this.parentZone.isMultipleFloorZone,
2962
- audioID: this.chosenAudio.id,
2963
- };
2964
- try {
2965
- yield this.setSweepsAndNodeForZoneInput(zoneInput);
2966
- yield this.zoneService
2967
- .create(zoneInput)
2968
- .then((zoneCreated) => __awaiter(this, void 0, void 0, function* () {
2969
- this.currentAudioZone = zoneCreated;
2970
- yield this.removeTakenSweepsFromOtherZones();
2971
- this.updatedZone.emit(zoneCreated.id);
2972
- }));
2973
- this.working = false;
2974
- }
2975
- catch (error) {
2976
- console.error(error);
2977
- this.working = false;
2978
- }
2979
- }
2980
- });
2981
- }
2982
- setSweepsAndNodeForZoneInput(zoneInput) {
2983
- return __awaiter(this, void 0, void 0, function* () {
2984
- if (this.chosenScansOnPlan.length > 0) {
2985
- zoneInput.sweepIDs = this.chosenScansOnPlan;
2986
- }
2987
- if (zoneInput.sweepIDs && zoneInput.sweepIDs.length > 0) {
2988
- const navForSweep = yield this.navigationService.getNavigationsForMatterportIDForSpace(zoneInput.sweepIDs[0], this.spaceID);
2989
- zoneInput.nodeIDs = [navForSweep[0].nodeID];
2990
- }
2991
- });
2992
- }
2993
- onCancel() {
2994
- if (this.scansModified) {
2995
- const message = this.translate.instant("confirm.cancelEditZone");
2996
- if (!window.confirm(message)) {
2997
- return;
2998
- }
2999
- }
3000
- this.commentForm = null;
3001
- this.chosenScansOnPlan = [];
3002
- this.updatedZone.emit(false);
3003
- }
3004
- togglePlan() {
3005
- this.fromPlan = true;
3006
- }
3007
- onSelectedSweepsFromPlan(result) {
3008
- if (result && result.sweeps) {
3009
- this.chosenScansOnPlan = result.sweeps;
3010
- this.scansModified = true;
3011
- }
3012
- this.fromPlan = false;
3013
- }
3014
- handleFileInput(event) {
3015
- const target = event.target;
3016
- this.fileToUpload = target.files[0];
3017
- }
3018
- onUploadAudio() {
3019
- return __awaiter(this, void 0, void 0, function* () {
3020
- this.working = true;
3021
- const commentInput = this.commentForm.value;
3022
- try {
3023
- const newAudio = yield this.commentService.createCommentWithFile(commentInput, this.fileToUpload);
3024
- this.audiosForSpace.push(newAudio);
3025
- this.isAddingAudio = false;
3026
- this.working = false;
3027
- this.audioUploaded = true;
3028
- }
3029
- catch (e) {
3030
- this.working = false;
3031
- this.audioUploaded = false;
3032
- console.log(e);
3033
- }
3034
- });
3035
- }
3036
- getAudios() {
3037
- return __awaiter(this, void 0, void 0, function* () {
3038
- const attachments = yield this.commentService.getCommentsBySpaceID(this.spaceID);
3039
- if (attachments) {
3040
- this.audiosForSpace = attachments.filter((attachment) => attachment.type === CommentType.AUDIO);
3041
- }
3042
- });
3043
- }
3044
- onCancelAudioUpload() {
3045
- this.commentForm = null;
3046
- this.isAddingAudio = false;
3047
- this.fileToUpload = null;
3048
- }
3049
- onChooseAudio(audio) {
3050
- this.chosenAudio = audio;
3051
- this.currentAudioZone = this.audioZones.find((zone) => zone.audioID === this.chosenAudio.id);
3052
- if (this.currentAudioZone) {
3053
- this.chosenScansOnPlan = this.currentAudioZone.sweepIDs;
3054
- }
3055
- else {
3056
- this.chosenScansOnPlan = [];
3057
- }
3058
- }
3059
- /**
3060
- * Removes newly selected sweeps for current zone (they are in chosenScansOnPlan) from other audio zones.
3061
- * Rule: one sweep = one audio.
3062
- */
3063
- removeTakenSweepsFromOtherZones() {
3064
- return __awaiter(this, void 0, void 0, function* () {
3065
- yield Promise.all(this.audioZones.map((zone) => __awaiter(this, void 0, void 0, function* () {
3066
- if (zone.id !== this.currentAudioZone.id) {
3067
- const newSweeps = zone.sweepIDs.filter((sweepID) => !this.chosenScansOnPlan.includes(sweepID));
3068
- if (newSweeps.length !== zone.sweepIDs.length) {
3069
- yield this.zoneService.updateZone({ id: zone.id, sweepIDs: newSweeps });
3070
- }
3071
- }
3072
- })));
3073
- });
3074
- }
3075
- /**
3076
- * Delete audio as Comment, all its audio Zones and file from S3 (using lambda function)
3077
- */
3078
- onDeleteAudio() {
3079
- return __awaiter(this, void 0, void 0, function* () {
3080
- const message = this.translate.instant("confirm.deleteAudio");
3081
- if (window.confirm(message)) {
3082
- yield this.commentService.deleteComment(this.chosenAudio.id);
3083
- const index = this.audiosForSpace.indexOf(this.chosenAudio);
3084
- this.audiosForSpace.splice(index, 1);
3085
- // delete all zones with this comment audio
3086
- const audioZonesToDelete = this.zones.filter((z) => z.audioID === this.chosenAudio.id);
3087
- yield Promise.all(audioZonesToDelete.map((zone) => __awaiter(this, void 0, void 0, function* () {
3088
- yield this.zoneService.deleteZone(zone.id);
3089
- const indexZone = this.audioZones.indexOf(this.currentAudioZone);
3090
- if (indexZone !== -1) {
3091
- this.audioZones.slice(indexZone, 1);
3092
- }
3093
- })));
3094
- this.currentAudioZone = null;
3095
- this.chosenAudio = null;
3096
- }
3097
- });
3098
- }
3099
- }
3100
- AddAudioZoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddAudioZoneComponent, deps: [{ token: i1$2.UntypedFormBuilder }, { token: i2.ZoneService }, { token: i2.LayerService }, { token: i2.BaseUserService }, { token: i2.NavigationService }, { token: i2.CommentService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
3101
- AddAudioZoneComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: AddAudioZoneComponent, selector: "lib-add-audio-zone", inputs: { spaceID: "spaceID", defaultZone: "defaultZone", zones: "zones", parentZone: "parentZone", currentAudioZone: "currentAudioZone" }, outputs: { updatedZone: "updatedZone" }, ngImport: i0, template: "<div class=\"main-container\">\r\n <div class=\"col-lg-6 col-md-6 col-sm-7\" *ngIf=\"isAddingAudio\">\r\n <form (ngSubmit)=\"onUploadAudio()\" [formGroup]=\"commentForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"title\">\r\n </div>\r\n </div>\r\n <div>\r\n <label for=\"file\" class=\"btn btn-label-file rounded-pill\">\r\n <input type=\"file\" id=\"file\" (change)=\"handleFileInput($event)\" />\r\n {{'Choose File' | translate}}</label>\r\n <p *ngIf=\"fileToUpload\">{{ fileToUpload.name}}</p>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"working\">\r\n <lib-loader></lib-loader>\r\n </div>\r\n \r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\" [disabled]=\"fromPlan || working\">{{'Upload' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancelAudioUpload()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <ngb-alert type=\"success\" [dismissible]=\"true\" *ngIf=\"!working && audioUploaded\" (closed)=\"audioUploaded=false\">\r\n {{ 'add-audio.success' | translate }} !\r\n </ngb-alert>\r\n <div class=\"col-7\" *ngIf=\"!isAddingAudio && audiosForSpace\">\r\n \r\n <div class=\"instruction-row\" >\r\n <p>1.</p>\r\n <div ngbDropdown class=\"d-inline-block\">\r\n <div>\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenAudio ?\r\n chosenAudio.title : ('choose-audio' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let audio of audiosForSpace\" \r\n (click)=\"onChooseAudio(audio)\">{{ audio.title }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <p>{{'or' | translate}}</p>\r\n <button (click)=\"isAddingAudio=true\" class=\"btn btn-primary rounded-pill me-2\"> {{'add-audio.add' | translate}}</button>\r\n </div>\r\n <div class=\"instruction-row\">\r\n <p>2.</p>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"togglePlan()\" [disabled]=\"!chosenAudio\">\r\n {{'Choose scan points on plan' | translate}}</button>\r\n\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onDeleteAudio()\" [disabled]=\"!chosenAudio\">\r\n {{'Delete audio' | translate}}</button>\r\n \r\n </div>\r\n <div class=\"instruction-row\" *ngIf=\"chosenAudio\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scans-chosen-audio' | translate}}</p>\r\n </div>\r\n\r\n <div class=\"mt-3\">\r\n <button class=\"btn btn-primary rounded-pill me-2\" [disabled]=\"fromPlan || !this.chosenAudio\" (click)=\"onSubmit()\">{{'Save' | translate}}</button>\r\n <button (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [inputZone]=\"currentAudioZone\" [spaceID]=\"spaceID\" \r\n [occupiedSweeps]=\"occupiedSweeps\" [unavailableSweeps]=\"unavailableSweeps\" [editingAudioZone]=\"true\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>\r\n", styles: [".instruction-row{display:flex;align-items:center;margin-top:1rem}.instruction-row button{margin-bottom:0}.instruction-row p{margin-bottom:0;margin-left:5px;margin-right:5px}\n"], dependencies: [{ kind: "component", type: i4$1.NgbAlert, selector: "ngb-alert", inputs: ["animation", "dismissible", "type"], outputs: ["closed"], exportAs: ["ngbAlert"] }, { kind: "directive", type: i4$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i4$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i4$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i4$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { 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: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2.LoaderComponent, selector: "lib-loader", inputs: ["useLogo", "color"] }, { kind: "component", type: SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: ["spaceID", "chosenScansOnPlan", "newZoneData", "occupiedSweeps", "unavailableSweeps", "editingAudioZone", "inputZone", "multipleFloors"], outputs: ["sweepsSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
3102
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AddAudioZoneComponent, decorators: [{
3103
- type: Component,
3104
- args: [{ selector: 'lib-add-audio-zone', template: "<div class=\"main-container\">\r\n <div class=\"col-lg-6 col-md-6 col-sm-7\" *ngIf=\"isAddingAudio\">\r\n <form (ngSubmit)=\"onUploadAudio()\" [formGroup]=\"commentForm\">\r\n <div class=\"mb-3 row\">\r\n <label class=\"col-sm-2 col-form-label\">{{'Name' | translate}} *</label>\r\n <div class=\"col-sm-10\">\r\n <input type=\"text\" class=\"form-control\" required formControlName=\"title\">\r\n </div>\r\n </div>\r\n <div>\r\n <label for=\"file\" class=\"btn btn-label-file rounded-pill\">\r\n <input type=\"file\" id=\"file\" (change)=\"handleFileInput($event)\" />\r\n {{'Choose File' | translate}}</label>\r\n <p *ngIf=\"fileToUpload\">{{ fileToUpload.name}}</p>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"working\">\r\n <lib-loader></lib-loader>\r\n </div>\r\n \r\n <div class=\"mt-3\">\r\n <button type=\"submit\" class=\"btn btn-primary rounded-pill me-2\" [disabled]=\"fromPlan || working\">{{'Upload' | translate}}</button>\r\n <button type=\"button\" (click)=\"onCancelAudioUpload()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n <ngb-alert type=\"success\" [dismissible]=\"true\" *ngIf=\"!working && audioUploaded\" (closed)=\"audioUploaded=false\">\r\n {{ 'add-audio.success' | translate }} !\r\n </ngb-alert>\r\n <div class=\"col-7\" *ngIf=\"!isAddingAudio && audiosForSpace\">\r\n \r\n <div class=\"instruction-row\" >\r\n <p>1.</p>\r\n <div ngbDropdown class=\"d-inline-block\">\r\n <div>\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenAudio ?\r\n chosenAudio.title : ('choose-audio' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let audio of audiosForSpace\" \r\n (click)=\"onChooseAudio(audio)\">{{ audio.title }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <p>{{'or' | translate}}</p>\r\n <button (click)=\"isAddingAudio=true\" class=\"btn btn-primary rounded-pill me-2\"> {{'add-audio.add' | translate}}</button>\r\n </div>\r\n <div class=\"instruction-row\">\r\n <p>2.</p>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"togglePlan()\" [disabled]=\"!chosenAudio\">\r\n {{'Choose scan points on plan' | translate}}</button>\r\n\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onDeleteAudio()\" [disabled]=\"!chosenAudio\">\r\n {{'Delete audio' | translate}}</button>\r\n \r\n </div>\r\n <div class=\"instruction-row\" *ngIf=\"chosenAudio\">\r\n <p>{{ chosenScansOnPlan.length }} {{'scans-chosen-audio' | translate}}</p>\r\n </div>\r\n\r\n <div class=\"mt-3\">\r\n <button class=\"btn btn-primary rounded-pill me-2\" [disabled]=\"fromPlan || !this.chosenAudio\" (click)=\"onSubmit()\">{{'Save' | translate}}</button>\r\n <button (click)=\"onCancel()\" class=\"btn btn-outline-primary rounded-pill me-2\">\r\n {{'Cancel' | translate}}</button>\r\n </div>\r\n </div>\r\n <div class=\"edit-plan\" *ngIf=\"fromPlan\">\r\n <lib-sweep-plan-selection style=\"width: 100%;\" [inputZone]=\"currentAudioZone\" [spaceID]=\"spaceID\" \r\n [occupiedSweeps]=\"occupiedSweeps\" [unavailableSweeps]=\"unavailableSweeps\" [editingAudioZone]=\"true\"\r\n (sweepsSelected)=\"onSelectedSweepsFromPlan($event)\"></lib-sweep-plan-selection>\r\n </div>\r\n</div>\r\n", styles: [".instruction-row{display:flex;align-items:center;margin-top:1rem}.instruction-row button{margin-bottom:0}.instruction-row p{margin-bottom:0;margin-left:5px;margin-right:5px}\n"] }]
3105
- }], ctorParameters: function () { return [{ type: i1$2.UntypedFormBuilder }, { type: i2.ZoneService }, { type: i2.LayerService }, { type: i2.BaseUserService }, { type: i2.NavigationService }, { type: i2.CommentService }, { type: i3.TranslateService }]; }, propDecorators: { spaceID: [{
3106
- type: Input
3107
- }], updatedZone: [{
3108
- type: Output
3109
- }], defaultZone: [{
3110
- type: Input
3111
- }], zones: [{
3112
- type: Input
3113
- }], parentZone: [{
3114
- type: Input
3115
- }], currentAudioZone: [{
3116
- type: Input
3117
- }] } });
3118
-
3119
- class CountAudioSweepsPipe {
3120
- constructor(zoneService) {
3121
- this.zoneService = zoneService;
3122
- }
3123
- transform(zone) {
3124
- return __awaiter(this, void 0, void 0, function* () {
3125
- let childrenAudioZones = yield this.zoneService.getZonesByParentZone(zone.id);
3126
- if (childrenAudioZones.length > 0) {
3127
- childrenAudioZones = childrenAudioZones.filter((zone) => zone.audioID);
3128
- if (childrenAudioZones.length > 0) {
3129
- return childrenAudioZones.flatMap((z) => z.sweepIDs).length;
3130
- }
3131
- }
3132
- return 0;
3133
- });
3134
- }
3135
- }
3136
- CountAudioSweepsPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CountAudioSweepsPipe, deps: [{ token: i2.ZoneService }], target: i0.ɵɵFactoryTarget.Pipe });
3137
- CountAudioSweepsPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: CountAudioSweepsPipe, name: "countAudioSweeps" });
3138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CountAudioSweepsPipe, decorators: [{
3139
- type: Pipe,
3140
- args: [{
3141
- name: 'countAudioSweeps'
3142
- }]
3143
- }], ctorParameters: function () { return [{ type: i2.ZoneService }]; } });
3144
-
3145
- class ZonesComponent {
3146
- constructor(route, zoneService, spaceService, visitService, navigationService, userService, planService, translate, navigatorService, router) {
3147
- this.route = route;
3148
- this.zoneService = zoneService;
3149
- this.spaceService = spaceService;
3150
- this.visitService = visitService;
3151
- this.navigationService = navigationService;
3152
- this.userService = userService;
3153
- this.planService = planService;
3154
- this.translate = translate;
3155
- this.navigatorService = navigatorService;
3156
- this.router = router;
3157
- this.lotIndexDetails = -1;
3158
- this.updatedZone = new EventEmitter();
3159
- this.isEditingZone = false;
3160
- this.carouselIsVisible = false;
3161
- this.planIsVisible = false;
3162
- this.loadingPlan = false;
3163
- this.menuItems = [];
3164
- this.isMuseumVisit = false;
3165
- this.isMuseumModule = false;
3166
- this.floorZones = [];
3167
- this.zonesMap = new Map();
3168
- this.floorDetails = -1;
3169
- this.defaultShowing = false;
3170
- this.isAddingAudioTrack = false;
3171
- this.destroy$ = new Subject();
3172
- // listen to the change of location via navigation bar dropdown
3173
- this.navigatorService.locationIDChange
3174
- .pipe(takeUntil(this.destroy$))
3175
- .subscribe((spaceID) => {
3176
- this.router.navigate(["dashboard/localisation", spaceID, "zones"]).catch(e => console.log(e.message));
3177
- });
3178
- this.route.params.subscribe((params) => {
3179
- this.spaceID = params.id;
3180
- this.resetZones().catch(e => console.log(e.message));
3181
- });
3182
- }
3183
- ngOnInit() {
3184
- return __awaiter(this, void 0, void 0, function* () {
3185
- this.isMuseumModule = this.userService.getSpModule() === SpModule.MUSEUM;
3186
- });
3187
- }
3188
- ngOnDestroy() {
3189
- this.destroy$.next(true);
3190
- this.destroy$.complete();
3191
- }
3192
- setupMenuItems() {
3193
- this.menuItems = [
3194
- { label: "Locations", url: "/localisation" },
3195
- {
3196
- label: this.currentSpace.name,
3197
- url: `/localisation/${this.spaceID}`,
3198
- },
3199
- {
3200
- label: "Zones",
3201
- url: `/localisation/${this.currentSpace.id}/zones`,
3202
- },
3203
- ];
3204
- }
3205
- onGoBack() {
3206
- this.editCompleted(null);
3207
- }
3208
- ngOnChanges() {
3209
- this.resetZones().catch(e => console.log(e.message));
3210
- }
3211
- resetZones() {
3212
- return __awaiter(this, void 0, void 0, function* () {
3213
- this.isMuseumVisit = false;
3214
- this.currentSpace = yield this.spaceService.getSpace(this.spaceID);
3215
- this.setupMenuItems();
3216
- this.allZones = yield this.zoneService.getZonesBySpace(this.spaceID);
3217
- this.defaultZone = this.allZones.find((zone) => zone.layer && zone.layer.name === "BUILDING" && zone.sweepIDs);
3218
- this.floorZones = this.allZones.filter((zone) => zone.layer && zone.layer.name === "FLOOR");
3219
- // sort alphabetically
3220
- this.floorZones.sort((a, b) => a.name.localeCompare(b.name));
3221
- // we add only children zones that are not Floors
3222
- if (!!this.defaultZone) {
3223
- this.zonesMap.set(this.defaultZone.id, this.allZones.filter((zone) => zone.parentID === this.defaultZone.id && !this.floorZones.includes(zone)));
3224
- }
3225
- for (const floor of this.floorZones) {
3226
- const zonesForFloor = this.allZones.filter((zone) => zone.parentID === floor.id);
3227
- this.zonesMap.set(floor.id, zonesForFloor.sort((a, b) => a.name.localeCompare(b.name)));
3228
- }
3229
- this.resetNavigations();
3230
- this.images360 = yield this.visitService.loadImagesForSpace(this.currentSpace);
3231
- this.plans = yield this.planService.getPlansWithZonesForSpace(this.spaceID);
3232
- this.plans = this.plans.filter((plan) => plan.isCurrentForZone);
3233
- this.onPlansLoaded().catch(e => console.log(e.message));
3234
- });
3235
- }
3236
- resetNavigations() {
3237
- this.navigations = [];
3238
- const zonesWithSweeps = this.allZones.filter((zone) => zone.sweepIDs);
3239
- this.navigations = [
3240
- ...new Set(zonesWithSweeps.flatMap((zone) => zone.sweepIDs)),
3241
- ];
3242
- }
3243
- onPlansLoaded() {
3244
- return __awaiter(this, void 0, void 0, function* () {
3245
- if (this.planIsVisible && this.currentZone) {
3246
- this.preparePlan().catch(e => console.log(e.message));
3247
- }
3248
- });
3249
- }
3250
- /**
3251
- * onToggleDetail folds/unfolds details for a zone
3252
- * @param index
3253
- * @param zone
3254
- */
3255
- onToggleDetail(index, zone) {
3256
- return __awaiter(this, void 0, void 0, function* () {
3257
- this.lotIndexDetails = index === this.lotIndexDetails ? -1 : index;
3258
- if (this.lotIndexDetails === -1) {
3259
- this.currentZone = null;
3260
- this.planIsVisible = false;
3261
- return;
3262
- }
3263
- this.currentZone = zone;
3264
- this.planIsVisible = true;
3265
- if (!this.plans) {
3266
- return; // wait until the plans are set
3267
- }
3268
- if (this.loadingPlan) {
3269
- // another plan is already loading
3270
- yield wait(1000);
3271
- }
3272
- this.preparePlan().catch(e => console.log(e.message));
3273
- });
3274
- }
3275
- onToggleDetailFloor(index, floor) {
3276
- this.defaultShowing = false;
3277
- this.floorDetails = index === this.floorDetails ? -1 : index;
3278
- if (this.floorDetails === -1) {
3279
- this.currentZone = null;
3280
- this.planIsVisible = false;
3281
- return;
3282
- }
3283
- this.currentZone = floor;
3284
- this.planIsVisible = true;
3285
- if (!this.plans) {
3286
- console.log("plans not ready");
3287
- return; // wait until the plans are set
3288
- }
3289
- this.preparePlan().catch(e => console.log(e.message));
3290
- }
3291
- onToggleDefaultZone() {
3292
- this.defaultShowing = !this.defaultShowing;
3293
- this.currentZone = this.defaultShowing ? this.defaultZone : null;
3294
- }
3295
- preparePlan() {
3296
- return __awaiter(this, void 0, void 0, function* () {
3297
- this.loadingPlan = true;
3298
- this.currentPlan = null;
3299
- if (this.currentZone.virtual) {
3300
- this.currentPlan = null;
3301
- this.loadingPlan = false;
3302
- return;
3303
- }
3304
- this.currentPlan = yield this.planService.getCalibratedPlanForZone(this.currentZone);
3305
- if (this.currentPlan) {
3306
- const scans = yield this.navigationService.getNavigationsForZone(this.currentZone);
3307
- yield this.showScanPointsOnPlan(scans);
3308
- }
3309
- this.loadingPlan = false;
3310
- });
3311
- }
3312
- toggleCarousel() {
3313
- this.carouselIsVisible = true;
3314
- }
3315
- onEdit(zone) {
3316
- this.zoneForEdit = zone;
3317
- if (this.zoneForEdit.layer && this.zoneForEdit.layer.name === "AUDIO") {
3318
- this.isAddingAudioTrack = true;
3319
- }
3320
- else {
3321
- this.isEditingZone = true;
3322
- }
3323
- this.menuItems.push({
3324
- label: `${zone.name}`,
3325
- });
3326
- }
3327
- onAddLot() {
3328
- this.isMuseumVisit = false;
3329
- this.isEditingZone = true;
3330
- this.menuItems.push({
3331
- label: "New",
3332
- });
3333
- }
3334
- onAddMuseumZone() {
3335
- this.isMuseumVisit = true;
3336
- this.isEditingZone = true;
3337
- this.menuItems.push({
3338
- label: "New Museum Itinerary",
3339
- });
3340
- }
3341
- onAddAudioZone(parentZone) {
3342
- this.parentZoneForAudio = parentZone;
3343
- this.isAddingAudioTrack = true;
3344
- this.menuItems.push({
3345
- label: parentZone.name,
3346
- });
3347
- this.menuItems.push({
3348
- label: "add-audio.add",
3349
- });
3350
- }
3351
- onDelete(zone) {
3352
- return __awaiter(this, void 0, void 0, function* () {
3353
- const message = this.translate.instant("confirm.deleteZone");
3354
- // eslint-disable-next-line no-alert
3355
- if (window.confirm(message)) {
3356
- const childrenZones = yield this.zoneService.getZonesByParentZone(zone.id);
3357
- yield Promise.all(childrenZones.map((childZone) => __awaiter(this, void 0, void 0, function* () {
3358
- yield this.zoneService.deleteZone(childZone.id);
3359
- this.allZones.splice(this.allZones.indexOf(childZone), 1);
3360
- })));
3361
- yield this.zoneService.deleteZone(zone.id);
3362
- this.allZones.splice(this.allZones.indexOf(zone), 1);
3363
- // remove current zone from its parent list
3364
- if (zone.parentID && Array.from(this.zonesMap.keys()).includes(zone.parentID)) {
3365
- const zonesForParent = this.zonesMap.get(zone.parentID);
3366
- zonesForParent.splice(zonesForParent.indexOf(zone), 1);
3367
- this.zonesMap.set(zone.parentID, zonesForParent);
3368
- }
3369
- // we send update of location in order to force update of list of zones in nav bar
3370
- this.navigatorService.locationIDChange.next(this.spaceID);
3371
- }
3372
- });
3373
- }
3374
- editCompleted(event) {
3375
- this.lotIndexDetails = -1;
3376
- this.currentPlan = null;
3377
- this.isEditingZone = false;
3378
- this.isAddingAudioTrack = false;
3379
- this.zoneForEdit = null;
3380
- this.planIsVisible = false;
3381
- this.carouselIsVisible = false;
3382
- this.setupMenuItems();
3383
- if (event) {
3384
- this.resetZones().catch(e => console.log(e.message));
3385
- // we send update of location in order to force update of list of zones in nav bar
3386
- this.navigatorService.locationIDChange.next(this.spaceID);
3387
- }
3388
- }
3389
- showScanPointsOnPlan(navigations) {
3390
- return __awaiter(this, void 0, void 0, function* () {
3391
- if (this.currentPlan) {
3392
- const divPlan = document.querySelector("#planDiv");
3393
- yield showScanPointsOnPlanInDiv(this.currentPlan, divPlan, navigations);
3394
- panzoom(divPlan, {
3395
- bounds: true,
3396
- boundsPadding: 0,
3397
- maxZoom: 3.5,
3398
- });
3399
- }
3400
- });
3401
- }
3402
- }
3403
- ZonesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ZonesComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.ZoneService }, { token: i2.SpaceService }, { token: i2.VisitService }, { token: i2.NavigationService }, { token: i2.BaseUserService }, { token: i2.PlanService }, { token: i3.TranslateService }, { token: i2.NavigatorService }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
3404
- ZonesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ZonesComponent, selector: "lib-zones", outputs: { updatedZone: "updatedZone" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"container-fluid\" *ngIf=\"currentSpace\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"row\" *ngIf=\"!isEditingZone && !isAddingAudioTrack\">\r\n <div class=\"col-md-6\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item default-zone-line-item\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\" *ngIf=\"defaultZone\">\r\n {{defaultZone.name}}\r\n <div class=\"default-zone-label\">{{ \"whole space\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"defaultShowing\" (click)=\"onToggleDefaultZone()\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"defaultShowing\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Type of zone' | translate}}:\r\n {{defaultZone.layer ? defaultZone.layer.name : \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"defaultZone.surface\">\r\n {{'Surface' | translate}}, m<sup>2</sup>: {{defaultZone.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!defaultZone.virtual\">{{'Scan Points' | translate}}:\r\n {{defaultZone.sweepIDs ? defaultZone.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n </ul>\r\n <div *ngFor=\"let pair of zonesMap | keyvalue\">\r\n <div *ngIf=\"pair.key == defaultZone.id\">\r\n <h5 style=\"margin: 8px;\" *ngIf=\"pair.value.length > 0\">{{'Children zones'|translate}}</h5>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item list-group-flush list-group-item-action\"\r\n *ngFor=\"let lot of pair.value; index as zoneIndex\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n {{lot.name}}\r\n <div class=\"museum-label\" *ngIf=\"lot.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"zoneIndex==lotIndexDetails\"\r\n (click)=\"onToggleDetail(zoneIndex, lot)\"></lib-chevron>\r\n\r\n </div>\r\n <div *ngIf=\"zoneIndex==lotIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.isMuseumVisitZone\">{{'Type of zone' |\r\n translate}}: {{lot.layer ? lot.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.surface\">\r\n {{'Surface' | translate}},m<sup>2</sup>: {{lot.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual\">{{'Scan Points' | translate}}:\r\n {{lot.sweepIDs ? lot.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.virtual\">\r\n {{'Zone not visible in 3D visit' | translate}}</li>\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"onEdit(lot)\">{{'Edit' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAudioZone(lot)\"\r\n *ngIf=\"isMuseumModule\"> {{'add-audio.add' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"onDelete(lot)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n\r\n <li class=\"list-group-item\" *ngFor=\"let floor of floorZones; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n {{floor.name}}\r\n <!-- <small>({{ lot.metadata ? ('Calibrated' | translate) : ('Not calibrated' | translate)}})</small> -->\r\n <div class=\"museum-label\" *ngIf=\"floor.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"index==floorDetails\"\r\n (click)=\"onToggleDetailFloor(index, floor)\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==floorDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Type of zone' | translate}}: {{floor.layer ?\r\n floor.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"floor.surface\">{{'Surface' | translate}}, m<sup>2</sup>:\r\n {{floor.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!floor.virtual\">{{'Scan Points' | translate}}:\r\n {{floor.sweepIDs ? floor.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"floor.virtual\">{{'Zone not visible in 3D visit' |\r\n translate}}</li>\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onEdit(floor)\">{{'Edit' |\r\n translate}}</button>\r\n\r\n <!-- List of children zones -->\r\n\r\n <div *ngFor=\"let pair of zonesMap | keyvalue\">\r\n <div *ngIf=\"pair.key == floor.id\">\r\n <h5 style=\"margin: 8px;\" *ngIf=\"pair.value.length > 0\">{{'Children zones'|translate}}</h5>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item list-group-flush list-group-item-action\"\r\n *ngFor=\"let lot of pair.value; index as zoneIndex\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n <div><span *ngIf=\"lot.code_ref\">{{lot.code_ref}}_</span>{{lot.name}}</div>\r\n <div class=\"museum-label\" *ngIf=\"lot.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"zoneIndex==lotIndexDetails\"\r\n (click)=\"onToggleDetail(zoneIndex, lot)\"></lib-chevron>\r\n\r\n </div>\r\n <div *ngIf=\"zoneIndex==lotIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.isMuseumVisitZone\">{{'Type of zone' |\r\n translate}}: {{lot.layer ? lot.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.surface\">{{'Surface' | translate}},\r\n m<sup>2</sup>:\r\n {{lot.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual\">{{'Scan Points' | translate}}:\r\n {{lot.sweepIDs ? lot.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual && lot.isMuseumVisitZone\">\r\n {{'Scan Points with audio' | translate}}: {{ lot | countAudioSweeps | async}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.virtual\">\r\n {{'Zone not visible in 3D visit' | translate}}</li> dist\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"onEdit(lot)\">{{'Edit' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAudioZone(lot)\"\r\n *ngIf=\"isMuseumModule\"> {{'add-audio.add' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"onDelete(lot)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddLot()\">{{'Add zone' |\r\n translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddMuseumZone()\" *ngIf=\"isMuseumModule\">\r\n {{'Add museum itinerary' | translate}}</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"planIsVisible\">\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loadingPlan\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <div class=\"row\" style=\"overflow: hidden; flex-direction: column;\">\r\n <div *ngIf=\"currentPlan\">\r\n <lib-plan-legend [isAudioZone]=\"false\"></lib-plan-legend>\r\n <div class=\"planContainer\">\r\n <div class=\"mt-3 ms-3\" style=\"height: 500px; width: 100%;\" id=\"planDiv\"></div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!currentPlan && plans && !loadingPlan && currentZone\">\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"!currentZone.virtual && !currentZone.isMultipleFloorZone\">\r\n {{ 'Plan is not calibrated' | translate}}\r\n </div>\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"currentZone.virtual\">\r\n {{ 'No scan points chosen' | translate}}\r\n </div>\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"currentZone.isMultipleFloorZone\">\r\n {{ 'The zone is on several floors' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"mb-3\" *ngIf=\"isEditingZone\">\r\n <lib-add-zone [zoneEdit]=\"zoneForEdit\" [spaceID]=\"spaceID\" [images360]=\"images360\" [navigationIDs]=\"navigations\"\r\n [zones]=\"allZones\" [defaultZone]=\"defaultZone\" (updatedZone)=\"editCompleted($event)\"\r\n [isMuseumVisit]=\"isMuseumVisit\"></lib-add-zone>\r\n </div>\r\n <div class=\"mb-3\" *ngIf=\"isAddingAudioTrack\">\r\n <lib-add-audio-zone [spaceID]=\"spaceID\" [defaultZone]=\"defaultZone\" [parentZone]=\"parentZoneForAudio\"\r\n [zones]=\"allZones\" [currentAudioZone]=\"zoneForEdit\" (updatedZone)=\"editCompleted($event)\"></lib-add-audio-zone>\r\n </div>\r\n</div>", styles: [".museum-label{background-color:#6f3974;font-size:.95rem;border-radius:10px;padding:5px 10px;color:#fff;text-transform:uppercase;margin-left:auto;margin-right:8px}.default-zone-line-item{border-bottom-width:3px}.default-zone-label{background-color:var(--smarterplan-primary);font-size:.95rem;border-radius:10px;padding:5px 10px;color:#fff;text-transform:uppercase;margin-left:auto;margin-right:8px}.planContainer{overflow:hidden;border-radius:6px;background-color:var(--smarterplan-secondary);height:500px}button{min-width:80px}\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: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: ChevronComponent, selector: "lib-chevron", inputs: ["conditionShowing"] }, { kind: "component", type: AddZoneComponent, selector: "lib-add-zone", inputs: ["zoneEdit", "spaceID", "images360", "navigationIDs", "zones", "newZoneDataFromEditor", "chosenPlan", "isMuseumVisit", "defaultZone"], outputs: ["updatedZone"] }, { kind: "component", type: AddAudioZoneComponent, selector: "lib-add-audio-zone", inputs: ["spaceID", "defaultZone", "zones", "parentZone", "currentAudioZone"], outputs: ["updatedZone"] }, { kind: "component", type: PlanLegendComponent, selector: "lib-plan-legend", inputs: ["isAudioZone"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: CountAudioSweepsPipe, name: "countAudioSweeps" }] });
3405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ZonesComponent, decorators: [{
3406
- type: Component,
3407
- args: [{ selector: 'lib-zones', template: "<div class=\"container-fluid\" *ngIf=\"currentSpace\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"row\" *ngIf=\"!isEditingZone && !isAddingAudioTrack\">\r\n <div class=\"col-md-6\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item default-zone-line-item\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\" *ngIf=\"defaultZone\">\r\n {{defaultZone.name}}\r\n <div class=\"default-zone-label\">{{ \"whole space\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"defaultShowing\" (click)=\"onToggleDefaultZone()\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"defaultShowing\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Type of zone' | translate}}:\r\n {{defaultZone.layer ? defaultZone.layer.name : \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"defaultZone.surface\">\r\n {{'Surface' | translate}}, m<sup>2</sup>: {{defaultZone.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!defaultZone.virtual\">{{'Scan Points' | translate}}:\r\n {{defaultZone.sweepIDs ? defaultZone.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n </ul>\r\n <div *ngFor=\"let pair of zonesMap | keyvalue\">\r\n <div *ngIf=\"pair.key == defaultZone.id\">\r\n <h5 style=\"margin: 8px;\" *ngIf=\"pair.value.length > 0\">{{'Children zones'|translate}}</h5>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item list-group-flush list-group-item-action\"\r\n *ngFor=\"let lot of pair.value; index as zoneIndex\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n {{lot.name}}\r\n <div class=\"museum-label\" *ngIf=\"lot.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"zoneIndex==lotIndexDetails\"\r\n (click)=\"onToggleDetail(zoneIndex, lot)\"></lib-chevron>\r\n\r\n </div>\r\n <div *ngIf=\"zoneIndex==lotIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.isMuseumVisitZone\">{{'Type of zone' |\r\n translate}}: {{lot.layer ? lot.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.surface\">\r\n {{'Surface' | translate}},m<sup>2</sup>: {{lot.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual\">{{'Scan Points' | translate}}:\r\n {{lot.sweepIDs ? lot.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.virtual\">\r\n {{'Zone not visible in 3D visit' | translate}}</li>\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"onEdit(lot)\">{{'Edit' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAudioZone(lot)\"\r\n *ngIf=\"isMuseumModule\"> {{'add-audio.add' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"onDelete(lot)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n\r\n <li class=\"list-group-item\" *ngFor=\"let floor of floorZones; index as index\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n {{floor.name}}\r\n <!-- <small>({{ lot.metadata ? ('Calibrated' | translate) : ('Not calibrated' | translate)}})</small> -->\r\n <div class=\"museum-label\" *ngIf=\"floor.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"index==floorDetails\"\r\n (click)=\"onToggleDetailFloor(index, floor)\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"index==floorDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\">{{'Type of zone' | translate}}: {{floor.layer ?\r\n floor.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"floor.surface\">{{'Surface' | translate}}, m<sup>2</sup>:\r\n {{floor.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!floor.virtual\">{{'Scan Points' | translate}}:\r\n {{floor.sweepIDs ? floor.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"floor.virtual\">{{'Zone not visible in 3D visit' |\r\n translate}}</li>\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onEdit(floor)\">{{'Edit' |\r\n translate}}</button>\r\n\r\n <!-- List of children zones -->\r\n\r\n <div *ngFor=\"let pair of zonesMap | keyvalue\">\r\n <div *ngIf=\"pair.key == floor.id\">\r\n <h5 style=\"margin: 8px;\" *ngIf=\"pair.value.length > 0\">{{'Children zones'|translate}}</h5>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item list-group-flush list-group-item-action\"\r\n *ngFor=\"let lot of pair.value; index as zoneIndex\">\r\n <div class=\"d-flex justify-content-between align-items-center zone-name\">\r\n <div><span *ngIf=\"lot.code_ref\">{{lot.code_ref}}_</span>{{lot.name}}</div>\r\n <div class=\"museum-label\" *ngIf=\"lot.isMuseumVisitZone\">{{ \"itinerary\" | translate }}</div>\r\n <lib-chevron [conditionShowing]=\"zoneIndex==lotIndexDetails\"\r\n (click)=\"onToggleDetail(zoneIndex, lot)\"></lib-chevron>\r\n\r\n </div>\r\n <div *ngIf=\"zoneIndex==lotIndexDetails\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.isMuseumVisitZone\">{{'Type of zone' |\r\n translate}}: {{lot.layer ? lot.layer.name :\r\n \"No type\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.surface\">{{'Surface' | translate}},\r\n m<sup>2</sup>:\r\n {{lot.surface }}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual\">{{'Scan Points' | translate}}:\r\n {{lot.sweepIDs ? lot.sweepIDs.length : \"No scan points\" | translate}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"!lot.virtual && lot.isMuseumVisitZone\">\r\n {{'Scan Points with audio' | translate}}: {{ lot | countAudioSweeps | async}} </li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"lot.virtual\">\r\n {{'Zone not visible in 3D visit' | translate}}</li> dist\r\n </ul>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill me-2\"\r\n (click)=\"onEdit(lot)\">{{'Edit' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddAudioZone(lot)\"\r\n *ngIf=\"isMuseumModule\"> {{'add-audio.add' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\"\r\n (click)=\"onDelete(lot)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddLot()\">{{'Add zone' |\r\n translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill me-2\" (click)=\"onAddMuseumZone()\" *ngIf=\"isMuseumModule\">\r\n {{'Add museum itinerary' | translate}}</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"planIsVisible\">\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loadingPlan\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <div class=\"row\" style=\"overflow: hidden; flex-direction: column;\">\r\n <div *ngIf=\"currentPlan\">\r\n <lib-plan-legend [isAudioZone]=\"false\"></lib-plan-legend>\r\n <div class=\"planContainer\">\r\n <div class=\"mt-3 ms-3\" style=\"height: 500px; width: 100%;\" id=\"planDiv\"></div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!currentPlan && plans && !loadingPlan && currentZone\">\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"!currentZone.virtual && !currentZone.isMultipleFloorZone\">\r\n {{ 'Plan is not calibrated' | translate}}\r\n </div>\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"currentZone.virtual\">\r\n {{ 'No scan points chosen' | translate}}\r\n </div>\r\n <div class=\"mt-3 ms-3\" id=\"no-plan\" *ngIf=\"currentZone.isMultipleFloorZone\">\r\n {{ 'The zone is on several floors' | translate}}\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"mb-3\" *ngIf=\"isEditingZone\">\r\n <lib-add-zone [zoneEdit]=\"zoneForEdit\" [spaceID]=\"spaceID\" [images360]=\"images360\" [navigationIDs]=\"navigations\"\r\n [zones]=\"allZones\" [defaultZone]=\"defaultZone\" (updatedZone)=\"editCompleted($event)\"\r\n [isMuseumVisit]=\"isMuseumVisit\"></lib-add-zone>\r\n </div>\r\n <div class=\"mb-3\" *ngIf=\"isAddingAudioTrack\">\r\n <lib-add-audio-zone [spaceID]=\"spaceID\" [defaultZone]=\"defaultZone\" [parentZone]=\"parentZoneForAudio\"\r\n [zones]=\"allZones\" [currentAudioZone]=\"zoneForEdit\" (updatedZone)=\"editCompleted($event)\"></lib-add-audio-zone>\r\n </div>\r\n</div>", styles: [".museum-label{background-color:#6f3974;font-size:.95rem;border-radius:10px;padding:5px 10px;color:#fff;text-transform:uppercase;margin-left:auto;margin-right:8px}.default-zone-line-item{border-bottom-width:3px}.default-zone-label{background-color:var(--smarterplan-primary);font-size:.95rem;border-radius:10px;padding:5px 10px;color:#fff;text-transform:uppercase;margin-left:auto;margin-right:8px}.planContainer{overflow:hidden;border-radius:6px;background-color:var(--smarterplan-secondary);height:500px}button{min-width:80px}\n"] }]
3408
- }], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i2.ZoneService }, { type: i2.SpaceService }, { type: i2.VisitService }, { type: i2.NavigationService }, { type: i2.BaseUserService }, { type: i2.PlanService }, { type: i3.TranslateService }, { type: i2.NavigatorService }, { type: i1.Router }]; }, propDecorators: { updatedZone: [{
3409
- type: Output
3410
- }] } });
3411
-
3412
- class ImagesComponent {
3413
- constructor(route, spaceService, visitService, nodeService, navigatorService, router) {
3414
- this.route = route;
3415
- this.spaceService = spaceService;
3416
- this.visitService = visitService;
3417
- this.nodeService = nodeService;
3418
- this.navigatorService = navigatorService;
3419
- this.router = router;
3420
- this.loading = false;
3421
- this.menuItems = [];
3422
- this.destroy$ = new Subject();
3423
- this.navigatorService.locationIDChange
3424
- .pipe(takeUntil(this.destroy$))
3425
- .subscribe((spaceID) => {
3426
- this.router.navigate(["dashboard/localisation", spaceID, "images"]);
3427
- });
3428
- this.route.params.subscribe((params) => {
3429
- this.spaceID = params.id;
3430
- ;
3431
- this.loadImages();
3432
- });
3433
- }
3434
- ngOnInit() {
3435
- }
3436
- ngOnDestroy() {
3437
- this.destroy$.next(true);
3438
- this.destroy$.complete();
3439
- }
3440
- setupMenuItems() {
3441
- this.menuItems = [
3442
- { label: "Locations", url: "/localisation" },
3443
- {
3444
- label: this.currentSpace.name,
3445
- url: `/localisation/${this.spaceID}`,
3446
- },
3447
- { label: "360° Images" },
3448
- ];
3449
- if (this.currentVisit) {
3450
- this.menuItems.push({ label: this.currentVisit.name });
3451
- }
3452
- }
3453
- onGoBack() {
3454
- this.currentVisit = null;
3455
- this.currentImages = null;
3456
- this.setupMenuItems();
3457
- }
3458
- loadImages() {
3459
- return __awaiter(this, void 0, void 0, function* () {
3460
- this.loading = true;
3461
- this.currentSpace = yield this.spaceService.getSpace(this.spaceID);
3462
- this.setupMenuItems();
3463
- this.images = yield this.visitService.loadImagesForSpace(this.currentSpace);
3464
- if (this.currentSpace.visits.length === 1) {
3465
- this.setVisit(this.currentSpace.visits[0]);
3466
- }
3467
- this.loading = false;
3468
- });
3469
- }
3470
- setVisit(visit) {
3471
- this.currentVisit = visit;
3472
- this.currentImages = this.images.filter((im) => {
3473
- return im.visit === visit;
3474
- });
3475
- this.setupMenuItems();
3476
- }
3477
- setCurrentScan(id) {
3478
- this.currentScanID = id;
3479
- }
3480
- onInventoryClick() {
3481
- return __awaiter(this, void 0, void 0, function* () {
3482
- const { node } = this.currentVisit;
3483
- const { filename } = this.currentImages[this.currentScanID]; // 110ee452_sweep.jpeg
3484
- // check if node has already errors of inventory
3485
- const missingFilesErrors = [
3486
- InventoryStatus.ERROR_FILE_JSON_NOT_EXIST,
3487
- InventoryStatus.ERROR_FILE_MODEL_NOT_EXIST,
3488
- InventoryStatus.ERROR_FILE_OBJ_NOT_EXIST,
3489
- ];
3490
- if (node.inventoryStatus &&
3491
- missingFilesErrors.includes(node.inventoryStatus)) {
3492
- alert("Files missing for this visit's inventory. Contact your administrator.");
3493
- }
3494
- else {
3495
- yield this.nodeService.updateNode({
3496
- id: node.id,
3497
- inventoryStatus: InventoryStatus.TO_RUN_ONE_IMAGE,
3498
- navigationForInventory: filename.split("_")[0],
3499
- });
3500
- alert("Automatic AI Inventory started! Detected equipments will appear soon in the visit.");
3501
- }
3502
- });
3503
- }
3504
- }
3505
- ImagesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImagesComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.SpaceService }, { token: i2.VisitService }, { token: i2.NodeService }, { token: i2.NavigatorService }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
3506
- ImagesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ImagesComponent, selector: "lib-images", ngImport: i0, template: "<div class=\"container-fluid dashboard-tab col-sm-10 mb-3\" *ngIf=\"currentSpace\" >\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n <div ngbDropdown class=\"d-inline-block\" *ngIf=\"currentSpace.visits && currentSpace.visits.length > 0\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" *ngIf=\"!currentVisit\"\r\n ngbDropdownToggle>{{'Choose 3D visit' | translate}}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let visit of currentSpace.visits\" (click)=\"setVisit(visit)\"> {{ visit.name }}\r\n </button>\r\n </div>\r\n </div>\r\n <h3 *ngIf=\"currentVisit\">{{ currentVisit.name }}</h3>\r\n <div class=\"mt-3\" *ngIf=\"currentVisit && currentImages.length == 0 && !loading\">\r\n <h4>{{'No imported images' | translate }}</h4>\r\n <p>{{'For import: go Virtual Visits => Import Images' | translate}}</p>\r\n </div>\r\n <button *ngIf=\"currentVisit && currentImages.length > 0 && !loading\"\r\n class=\"btn btn-outline-primary rounded-pill no-lowercase mb-2\" (click)=\"onInventoryClick()\">\r\n {{'Run AI inventory on this image' | translate}}</button>\r\n <lib-carousel [images]=\"currentImages\" *ngIf=\"currentImages\" (currentScan)=\"setCurrentScan($event)\"></lib-carousel>\r\n </div>", styles: [""], dependencies: [{ kind: "directive", type: i4$1.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i4$1.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i4$1.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i4$1.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { 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: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: CarouselComponent, selector: "lib-carousel", inputs: ["images"], outputs: ["currentScan"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
3507
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImagesComponent, decorators: [{
3508
- type: Component,
3509
- args: [{ selector: 'lib-images', template: "<div class=\"container-fluid dashboard-tab col-sm-10 mb-3\" *ngIf=\"currentSpace\" >\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems' (onGoBack)=\"onGoBack()\"></lib-tab-navigation>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">{{'Loading' | translate}}...</span>\r\n </div>\r\n </div>\r\n <div ngbDropdown class=\"d-inline-block\" *ngIf=\"currentSpace.visits && currentSpace.visits.length > 0\">\r\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" *ngIf=\"!currentVisit\"\r\n ngbDropdownToggle>{{'Choose 3D visit' | translate}}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button ngbDropdownItem *ngFor=\"let visit of currentSpace.visits\" (click)=\"setVisit(visit)\"> {{ visit.name }}\r\n </button>\r\n </div>\r\n </div>\r\n <h3 *ngIf=\"currentVisit\">{{ currentVisit.name }}</h3>\r\n <div class=\"mt-3\" *ngIf=\"currentVisit && currentImages.length == 0 && !loading\">\r\n <h4>{{'No imported images' | translate }}</h4>\r\n <p>{{'For import: go Virtual Visits => Import Images' | translate}}</p>\r\n </div>\r\n <button *ngIf=\"currentVisit && currentImages.length > 0 && !loading\"\r\n class=\"btn btn-outline-primary rounded-pill no-lowercase mb-2\" (click)=\"onInventoryClick()\">\r\n {{'Run AI inventory on this image' | translate}}</button>\r\n <lib-carousel [images]=\"currentImages\" *ngIf=\"currentImages\" (currentScan)=\"setCurrentScan($event)\"></lib-carousel>\r\n </div>" }]
3510
- }], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i2.SpaceService }, { type: i2.VisitService }, { type: i2.NodeService }, { type: i2.NavigatorService }, { type: i1.Router }]; } });
3511
-
3512
- class EditPlanComponent {
3513
- constructor(planService, route, router, modalService, zoneService, visitService, spaceService, translate, ngZone) {
3514
- this.planService = planService;
3515
- this.route = route;
3516
- this.router = router;
3517
- this.modalService = modalService;
3518
- this.zoneService = zoneService;
3519
- this.visitService = visitService;
3520
- this.spaceService = spaceService;
3521
- this.translate = translate;
3522
- this.ngZone = ngZone;
3523
- this.loading = false;
3524
- this.isNewZone = false;
3525
- /**
3526
- * Options for svgEditor
3527
- */
3528
- this.config = {
3529
- noStorageOnLoad: true,
3530
- forceStorage: true,
3531
- // imgPath: "/assets/editor/images/",
3532
- // extPath: "/assets/editor/extensions/",
3533
- // langPath: "/assets/editor/locale/",
3534
- // canvgPath: "/assets/editor/canvg/",
3535
- // jspdfPath: "/assets/editor/jspdf/",
3536
- // jGraduatePath: "/assets/editor/jgraduate/images/",
3537
- // extIconsPath: "/assets/editor/extensions/",
3538
- // stylesheets: [
3539
- // "/assets/editor/jgraduate/css/jGraduate.css",
3540
- // "/assets/editor/spinbtn/jQuery.SpinButton.css",
3541
- // "/assets/editor/jgraduate/css/jPicker.css",
3542
- // "/assets/editor/svg-editor.css",
3543
- // ],
3544
- dimensions: [10000, 10000],
3545
- showlayers: true,
3546
- noDefaultExtensions: true,
3547
- basePath: "/assets/editor/",
3548
- customExportImage: true,
3549
- extensions: [
3550
- "ext-connector",
3551
- // "ext-eyedropper",
3552
- // "ext-grid",
3553
- // "ext-markers",
3554
- // "ext-overview_window",
3555
- // "ext-spi-library",
3556
- // "ext-spi-icon",
3557
- "ext-sp-zone",
3558
- // "ext-arrows",
3559
- // "ext-sp-css",
3560
- // "ext-placemark",
3561
- ],
3562
- };
3563
- this.menuItems = [];
3564
- this.chosenPlan = this.planService.getChosenPlan();
3565
- }
3566
- ngOnInit() {
3567
- return __awaiter(this, void 0, void 0, function* () {
3568
- this.editorUrl = "/assets/editor/main.html";
3569
- this.spaceID = this.route.snapshot.queryParams.spaceID;
3570
- this.currentSpace = yield this.spaceService.getSpace(this.spaceID);
3571
- this.setupMenuItems();
3572
- if (this.spaceID && !this.planService.getChosenPlan()) {
3573
- this.router.navigate([
3574
- "/dashboard/localisation",
3575
- this.spaceID,
3576
- "plans",
3577
- ]);
3578
- }
3579
- else if (!this.spaceID && !this.planService.getChosenPlan()) {
3580
- this.router.navigate(["/dashboard/localisation"]);
3581
- }
3582
- });
3583
- }
3584
- setupMenuItems() {
3585
- this.menuItems = [
3586
- { label: "Locations", url: "/localisation" },
3587
- {
3588
- label: this.currentSpace.name,
3589
- url: `/localisation/${this.spaceID}`,
3590
- },
3591
- {
3592
- label: "Plans",
3593
- url: `/localisation/${this.currentSpace.id}/plans`,
3594
- },
3595
- {
3596
- label: "Edit",
3597
- url: `/localisation/${this.currentSpace.id}/plan-edit?spaceID=${this.currentSpace.id}`,
3598
- },
3599
- ];
3600
- }
3601
- switchAction(event) {
3602
- return __awaiter(this, void 0, void 0, function* () {
3603
- if (event.origin === window.location.origin) {
3604
- switch (event.data.message) {
3605
- case "save":
3606
- this.onSave(event.data.redirect);
3607
- break;
3608
- case "close":
3609
- this.onCancel();
3610
- break;
3611
- case "new-zone":
3612
- const modalReference = this.modalService.open(this.loadingModal);
3613
- const svg = unescape(encodeURIComponent(this.svgEditor.svgCanvas.getSvgString()));
3614
- const base64 = `data:image/svg+xml;base64,${window.btoa(svg)}`;
3615
- const currentSpace = yield this.spaceService.getSpace(this.spaceID);
3616
- this.images360 = yield this.visitService.loadImagesForSpace(currentSpace);
3617
- this.editedPlan = Object.assign({}, this.chosenPlan);
3618
- this.editedPlan.filepath = base64;
3619
- this.newZoneData = event.data.zoneData;
3620
- if (this.newZoneData.elements.length === 0) {
3621
- modalReference.close();
3622
- alert(this.translate.instant("edition.no-zone"));
3623
- break;
3624
- }
3625
- this.zones = yield this.zoneService.getZonesBySpace(this.spaceID);
3626
- // this.zones = sortAlphabeticallyOnName(this.zones);
3627
- // console.log("zones", this.zones);
3628
- // this.editedZone = this.zones.find(
3629
- // (z) => z.name === this.newZoneData.name,
3630
- // );
3631
- this.resetNavigations();
3632
- modalReference.close();
3633
- this.modalService.open(this.dialogZone);
3634
- break;
3635
- default:
3636
- break;
3637
- }
3638
- }
3639
- });
3640
- }
3641
- resetNavigations() {
3642
- return __awaiter(this, void 0, void 0, function* () {
3643
- this.navigations = [];
3644
- const defaultZone = this.zones.find((zone) => !zone.parentID);
3645
- if (defaultZone.sweepIDs.length > 0) {
3646
- this.navigations = defaultZone.sweepIDs;
3647
- }
3648
- });
3649
- }
3650
- onLoad(svgEditor) {
3651
- return __awaiter(this, void 0, void 0, function* () {
3652
- if (svgEditor.contentWindow.SvgEditor) {
3653
- this.svgEditorIframe = svgEditor;
3654
- this.svgEditor = new svgEditor.contentWindow.SvgEditor();
3655
- yield this.svgEditor.init();
3656
- yield this.svgEditor.setConfig(this.config, {
3657
- allowInitialUserOverride: true,
3658
- });
3659
- if (this.chosenPlan && this.chosenPlan.extension === "svg") {
3660
- this.loadSvg();
3661
- }
3662
- if (this.chosenPlan && this.chosenPlan.extension === "pdf") {
3663
- this.loadPdf();
3664
- }
3665
- if (!this.chosenPlan.calibration || !this.chosenPlan.isModified) {
3666
- setTimeout(() => {
3667
- this.svgEditorIframe.contentWindow.postMessage({ action: "disable-zone" }, "*");
3668
- }, 1000);
3669
- }
3670
- this.svgEditor.svgCanvas.setMode('ext-panning');
3671
- this.svgEditor.bottomPanel.changeZoom(50);
3672
- }
3673
- });
3674
- }
3675
- onSave(redirect) {
3676
- return __awaiter(this, void 0, void 0, function* () {
3677
- const imgBlob = yield new Blob([this.svgEditor.svgCanvas.getSvgString()], {
3678
- type: "image/svg+xml",
3679
- });
3680
- const [name] = this.chosenPlan.name.split(".");
3681
- const imgFile = new File([imgBlob], `${name}-edited.svg`, {
3682
- type: "image/svg+xml",
3683
- lastModified: Date.now(),
3684
- });
3685
- this.planService.setPlanFileCache(imgFile);
3686
- if (this.chosenPlan.isModified) {
3687
- this.ngZone.run(() => this.modalService.open(this.dialog));
3688
- }
3689
- else {
3690
- this.ngZone.run(() => this.router.navigate([
3691
- "/dashboard/localisation",
3692
- this.spaceID,
3693
- "plans",
3694
- ]));
3695
- }
3696
- });
3697
- }
3698
- updateSvg() {
3699
- return __awaiter(this, void 0, void 0, function* () {
3700
- const newUrl = yield this.planService.updatePlanFile();
3701
- yield this.planService.updatePlan({
3702
- id: this.chosenPlan.id,
3703
- annexe: newUrl,
3704
- });
3705
- this.planService.setPlanFileCache(null);
3706
- this.ngZone.run(() => this.router.navigate([
3707
- "/dashboard/localisation",
3708
- this.spaceID,
3709
- "plans",
3710
- ]));
3711
- });
3712
- }
3713
- newSvg() {
3714
- return __awaiter(this, void 0, void 0, function* () {
3715
- this.ngZone.run(() => this.router.navigate([
3716
- "/dashboard/localisation",
3717
- this.spaceID,
3718
- "plans",
3719
- ]));
3720
- });
3721
- }
3722
- onCancel() {
3723
- return __awaiter(this, void 0, void 0, function* () {
3724
- if (window.confirm(this.translate.instant("edition.cancel-alert"))) {
3725
- this.ngZone.run(() => this.router.navigate([
3726
- "/dashboard/localisation",
3727
- this.spaceID,
3728
- "plans",
3729
- ]));
3730
- alert(this.translate.instant("edition.cancel"));
3731
- }
3732
- });
3733
- }
3734
- loadSvg() {
3735
- return __awaiter(this, void 0, void 0, function* () {
3736
- const svgRequest = yield downloadFileAsObject(this.chosenPlan.annexe);
3737
- if (svgRequest) {
3738
- const svgBlob = yield svgRequest.Body;
3739
- const reader = new FileReader();
3740
- reader.onloadend = () => {
3741
- this.svgEditor.loadFromDataURI(reader.result);
3742
- };
3743
- reader.readAsDataURL(svgBlob);
3744
- }
3745
- });
3746
- }
3747
- loadPdf() {
3748
- return __awaiter(this, void 0, void 0, function* () {
3749
- this.svgEditorIframe.contentWindow.postMessage({ action: "disable-zone" }, "*");
3750
- const canvas = document.querySelector("#canvas4pdf");
3751
- const context = canvas.getContext("2d");
3752
- const pdfjs = yield import('pdfjs-dist/build/pdf');
3753
- const pdfjsWorker = yield import('pdfjs-dist/build/pdf.worker.entry');
3754
- pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
3755
- const pdf = yield getDocument(this.chosenPlan.filepath).promise;
3756
- const page = yield pdf.getPage(1);
3757
- const viewPortParameters = { scale: 1.5 };
3758
- const viewport = page.getViewport(viewPortParameters);
3759
- this.svgEditor.svgCanvas.setResolution(viewport.width, viewport.height);
3760
- canvas.height = viewport.height;
3761
- canvas.width = viewport.width;
3762
- const renderContext = {
3763
- canvasContext: context,
3764
- viewport,
3765
- };
3766
- const renderTask = page.render(renderContext).promise;
3767
- renderTask.then(() => {
3768
- const newImage = this.svgEditor.svgCanvas.addSVGElementFromJson({
3769
- element: "image",
3770
- attr: {
3771
- x: 0,
3772
- y: 0,
3773
- width: viewport.width,
3774
- height: viewport.height,
3775
- id: this.svgEditor.svgCanvas.getNextId(),
3776
- style: "pointer-events:inherit",
3777
- },
3778
- });
3779
- this.svgEditor.svgCanvas.setHref(newImage, canvas.toDataURL("image/png"));
3780
- this.svgEditor.svgCanvas.renameCurrentLayer(this.translate.instant("edition.plan-base"));
3781
- this.svgEditor.svgCanvas.createLayer(this.translate.instant("edition.personalization"));
3782
- });
3783
- });
3784
- }
3785
- onLoadImg(img) {
3786
- return __awaiter(this, void 0, void 0, function* () {
3787
- this.svgEditorIframe.contentWindow.postMessage({ action: "disable-zone" }, "*");
3788
- const imgRequest = yield downloadFileAsObject(this.chosenPlan.annexe);
3789
- if (imgRequest) {
3790
- const imgBlob = yield imgRequest.Body;
3791
- const imgWidth = img.naturalWidth;
3792
- const imgHeight = img.naturalHeight;
3793
- // await this.svgEditor.setConfig({
3794
- // dimensions: [imgWidth, imgHeight],
3795
- // });
3796
- this.svgEditor.svgCanvas.setResolution(imgWidth, imgHeight);
3797
- const reader = new FileReader();
3798
- reader.onloadend = () => {
3799
- const newImage = this.svgEditor.svgCanvas.addSVGElementFromJson({
3800
- element: "image",
3801
- attr: {
3802
- x: 0,
3803
- y: 0,
3804
- width: imgWidth,
3805
- height: imgHeight,
3806
- id: this.svgEditor.svgCanvas.getNextId(),
3807
- style: "pointer-events:inherit",
3808
- },
3809
- });
3810
- this.svgEditor.svgCanvas.setHref(newImage, reader.result);
3811
- this.svgEditor.svgCanvas.renameCurrentLayer(this.translate.instant("edition.plan-base"));
3812
- this.svgEditor.svgCanvas.createLayer(this.translate.instant("edition.personalization"));
3813
- };
3814
- reader.readAsDataURL(imgBlob);
3815
- }
3816
- });
3817
- }
3818
- onNewZone(event) {
3819
- this.isNewZone = false;
3820
- if (event) {
3821
- this.svgEditorIframe.contentWindow.postMessage({ action: "rename-layer", name: event }, "*");
3822
- }
3823
- else {
3824
- this.svgEditorIframe.contentWindow.postMessage({ action: "cancel-layer" }, "*");
3825
- }
3826
- }
3827
- }
3828
- EditPlanComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditPlanComponent, deps: [{ token: i2.PlanService }, { token: i1.ActivatedRoute }, { token: i1.Router }, { token: i4$1.NgbModal }, { token: i2.ZoneService }, { token: i2.VisitService }, { token: i2.SpaceService }, { token: i3.TranslateService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3829
- EditPlanComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EditPlanComponent, selector: "lib-edit-plan", host: { listeners: { "window:message": "switchAction($event)" } }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true }, { propertyName: "dialogZone", first: true, predicate: ["dialogZone"], descendants: true }, { propertyName: "loadingModal", first: true, predicate: ["preparing"], descendants: true }], ngImport: i0, template: "<div class=\"row mt-3\">\r\n <div class=\"col\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\r\n </div>\r\n </div>\r\n</div>\r\n<lib-add-zone *ngIf=\"isNewZone\" [images360]=\"images360\" [spaceID]=\"spaceID\" [navigationIDs]=\"navigations\"\r\n [zoneEdit]=\"editedZone\" [zones]=\"zones\" (updatedZone)=\"onNewZone($event)\" [chosenPlan]=\"editedPlan\"\r\n [newZoneDataFromEditor]=\"newZoneData\"></lib-add-zone>\r\n<iframe *ngIf=\"editorUrl\" #svgEditor [src]=\"editorUrl | safeUrl\" frameborder=\"0\"\r\n style=\"height:100%;width:100%;min-height:550px;max-height:750px\" (load)=\"onLoad(svgEditor)\"></iframe>\r\n<!-- chosenPlan && -->\r\n<!-- ./../../../../../../assets/svgeditor/index.html -->\r\n\r\n<img #imgPng *ngIf=\"chosenPlan && chosenPlan.extension !== 'svg' && svgEditor\" [src]=\"chosenPlan.filepath\"\r\n (load)=\"onLoadImg(imgPng)\" style=\"display: none;\">\r\n\r\n<canvas id=\"canvas4pdf\" style=\"display: none;\"></canvas>\r\n\r\n<ng-template #dialog let-modal>\r\n\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Submit' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'save plan edited' | translate}}\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"newSvg();modal.close('Close click')\">{{'Yes' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"updateSvg();modal.close('Close click')\">{{'No' |\r\n translate}}</button>\r\n </div>\r\n\r\n</ng-template>\r\n\r\n<ng-template #dialogZone let-modal>\r\n\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Submit' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'confirm.new-zone-from-plan' | translate}}\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\"\r\n (click)=\"isNewZone = true;modal.close('Close click')\">{{'Validate' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"modal.close('Close click')\">{{'Cancel' |\r\n translate}}</button>\r\n </div>\r\n\r\n</ng-template>\r\n\r\n<ng-template #preparing let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Processing' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n</ng-template>", styles: ["app-add-zone{position:absolute;top:0;left:0;background-color:#fff;width:100%;height:100%;padding:30px}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }, { kind: "component", type: AddZoneComponent, selector: "lib-add-zone", inputs: ["zoneEdit", "spaceID", "images360", "navigationIDs", "zones", "newZoneDataFromEditor", "chosenPlan", "isMuseumVisit", "defaultZone"], outputs: ["updatedZone"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2.SafeUrlPipe, name: "safeUrl" }] });
3830
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditPlanComponent, decorators: [{
3831
- type: Component,
3832
- args: [{ selector: 'lib-edit-plan', template: "<div class=\"row mt-3\">\r\n <div class=\"col\">\r\n <div class=\"m-3\">\r\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\r\n </div>\r\n </div>\r\n</div>\r\n<lib-add-zone *ngIf=\"isNewZone\" [images360]=\"images360\" [spaceID]=\"spaceID\" [navigationIDs]=\"navigations\"\r\n [zoneEdit]=\"editedZone\" [zones]=\"zones\" (updatedZone)=\"onNewZone($event)\" [chosenPlan]=\"editedPlan\"\r\n [newZoneDataFromEditor]=\"newZoneData\"></lib-add-zone>\r\n<iframe *ngIf=\"editorUrl\" #svgEditor [src]=\"editorUrl | safeUrl\" frameborder=\"0\"\r\n style=\"height:100%;width:100%;min-height:550px;max-height:750px\" (load)=\"onLoad(svgEditor)\"></iframe>\r\n<!-- chosenPlan && -->\r\n<!-- ./../../../../../../assets/svgeditor/index.html -->\r\n\r\n<img #imgPng *ngIf=\"chosenPlan && chosenPlan.extension !== 'svg' && svgEditor\" [src]=\"chosenPlan.filepath\"\r\n (load)=\"onLoadImg(imgPng)\" style=\"display: none;\">\r\n\r\n<canvas id=\"canvas4pdf\" style=\"display: none;\"></canvas>\r\n\r\n<ng-template #dialog let-modal>\r\n\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Submit' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'save plan edited' | translate}}\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"newSvg();modal.close('Close click')\">{{'Yes' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"updateSvg();modal.close('Close click')\">{{'No' |\r\n translate}}</button>\r\n </div>\r\n\r\n</ng-template>\r\n\r\n<ng-template #dialogZone let-modal>\r\n\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Submit' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {{'confirm.new-zone-from-plan' | translate}}\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-outline-dark\"\r\n (click)=\"isNewZone = true;modal.close('Close click')\">{{'Validate' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-dark\" (click)=\"modal.close('Close click')\">{{'Cancel' |\r\n translate}}</button>\r\n </div>\r\n\r\n</ng-template>\r\n\r\n<ng-template #preparing let-modal>\r\n <div class=\"modal-header\">\r\n <h4 class=\"modal-title\">{{'Processing' | translate}}</h4>\r\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"d-flex justify-content-center\">\r\n <div class=\"spinner-border\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n</ng-template>", styles: ["app-add-zone{position:absolute;top:0;left:0;background-color:#fff;width:100%;height:100%;padding:30px}\n"] }]
3833
- }], ctorParameters: function () { return [{ type: i2.PlanService }, { type: i1.ActivatedRoute }, { type: i1.Router }, { type: i4$1.NgbModal }, { type: i2.ZoneService }, { type: i2.VisitService }, { type: i2.SpaceService }, { type: i3.TranslateService }, { type: i0.NgZone }]; }, propDecorators: { dialog: [{
3834
- type: ViewChild,
3835
- args: ["dialog"]
3836
- }], dialogZone: [{
3837
- type: ViewChild,
3838
- args: ["dialogZone"]
3839
- }], loadingModal: [{
3840
- type: ViewChild,
3841
- args: ["preparing"]
3842
- }], switchAction: [{
3843
- type: HostListener,
3844
- args: ["window:message", ["$event"]]
3845
- }] } });
3846
-
3847
- const routes = [
3848
- {
3849
- path: "",
3850
- component: LocationsComponent,
3851
- },
3852
- {
3853
- path: ":id",
3854
- children: [
3855
- { path: "", component: DetailLocationComponent },
3856
- { path: "zones", component: ZonesComponent },
3857
- { path: "visits", component: VisitsComponent },
3858
- { path: "plans", component: PlansComponent },
3859
- {
3860
- path: "plan-calibration",
3861
- component: CalibrationComponent,
3862
- },
3863
- {
3864
- path: "plan-edit",
3865
- component: EditPlanComponent,
3866
- },
3867
- { path: "images", component: ImagesComponent },
3868
- ],
3869
- },
3870
- ];
3871
- class LocationsRoutingModule {
3872
- }
3873
- LocationsRoutingModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocationsRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3874
- LocationsRoutingModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: LocationsRoutingModule, imports: [i1.RouterModule], exports: [RouterModule] });
3875
- LocationsRoutingModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocationsRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
3876
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocationsRoutingModule, decorators: [{
3877
- type: NgModule,
3878
- args: [{
3879
- imports: [RouterModule.forChild(routes)],
3880
- exports: [RouterModule],
3881
- }]
3882
- }] });
3883
-
3884
- class NgxSmarterplanLocationsModule {
3885
- }
3886
- NgxSmarterplanLocationsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3887
- NgxSmarterplanLocationsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsModule, declarations: [LocationsComponent,
3888
- DetailLocationComponent,
3889
- CalibrationComponent,
3890
- PlansComponent,
3891
- VisitsComponent,
3892
- ZonesComponent,
3893
- ImagesComponent,
3894
- EditPlanComponent,
3895
- TabNavigationComponent,
3896
- MapComponent,
3897
- MapPopupComponent,
3898
- FormLocationComponent,
3899
- ChevronComponent,
3900
- AddZoneComponent,
3901
- SelectionComponent,
3902
- CarouselComponent,
3903
- SweepPlanSelectionComponent,
3904
- AddAudioZoneComponent,
3905
- RadioButtonComponent,
3906
- PlanLegendComponent,
3907
- CountAudioSweepsPipe], imports: [PdfViewerModule,
3908
- ClipboardModule,
3909
- NgbModule,
3910
- NgbAlertModule,
3911
- CommonModule, i3.TranslateModule, LeafletModule,
3912
- FormsModule,
3913
- ReactiveFormsModule,
3914
- NgxSmarterplanCoreModule,
3915
- LocationsRoutingModule], exports: [MapComponent, TabNavigationComponent] });
3916
- NgxSmarterplanLocationsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsModule, imports: [PdfViewerModule,
3917
- ClipboardModule,
3918
- NgbModule,
3919
- NgbAlertModule,
3920
- CommonModule,
3921
- TranslateModule.forChild({
3922
- extend: true
3923
- }),
3924
- LeafletModule,
3925
- FormsModule,
3926
- ReactiveFormsModule,
3927
- NgxSmarterplanCoreModule,
3928
- LocationsRoutingModule] });
3929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgxSmarterplanLocationsModule, decorators: [{
3930
- type: NgModule,
3931
- args: [{
3932
- declarations: [
3933
- LocationsComponent,
3934
- DetailLocationComponent,
3935
- CalibrationComponent,
3936
- PlansComponent,
3937
- VisitsComponent,
3938
- ZonesComponent,
3939
- ImagesComponent,
3940
- EditPlanComponent,
3941
- TabNavigationComponent,
3942
- MapComponent,
3943
- MapPopupComponent,
3944
- FormLocationComponent,
3945
- ChevronComponent,
3946
- AddZoneComponent,
3947
- SelectionComponent,
3948
- CarouselComponent,
3949
- SweepPlanSelectionComponent,
3950
- AddAudioZoneComponent,
3951
- RadioButtonComponent,
3952
- PlanLegendComponent,
3953
- CountAudioSweepsPipe,
3954
- ],
3955
- imports: [
3956
- PdfViewerModule,
3957
- ClipboardModule,
3958
- NgbModule,
3959
- NgbAlertModule,
3960
- CommonModule,
3961
- TranslateModule.forChild({
3962
- extend: true
3963
- }),
3964
- LeafletModule,
3965
- FormsModule,
3966
- ReactiveFormsModule,
3967
- NgxSmarterplanCoreModule,
3968
- LocationsRoutingModule,
3969
- ],
3970
- exports: [MapComponent, TabNavigationComponent]
3971
- }]
3972
- }] });
3973
-
3974
- /*
3975
- * Public API Surface of ngx-smarterplan-locations
3976
- */
3977
-
3978
- /**
3979
- * Generated bundle index. Do not edit.
3980
- */
3981
-
3982
- export { MapComponent, NgxSmarterplanLocationsModule, NgxSmarterplanLocationsService, TabNavigationComponent };
3983
- //# sourceMappingURL=smarterplan-ngx-smarterplan-locations.mjs.map