@smarterplan/ngx-smarterplan-core 1.4.9 → 1.4.11
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.
- package/esm2022/lib/matterport-extensions/security-camera/SecurityCamera.mjs +10 -4
- package/esm2022/lib/services/filter.service.mjs +19 -16
- package/esm2022/lib/services/matterport-import.service.mjs +190 -18
- package/esm2022/lib/services/matterport-navigation.service.mjs +85 -6
- package/esm2022/lib/services/matterport-tag.service.mjs +32 -17
- package/esm2022/lib/services/matterport.service.mjs +24 -12
- package/esm2022/lib/services/models/comment.service.mjs +6 -3
- package/esm2022/lib/services/models/equipment.service.mjs +51 -59
- package/esm2022/lib/services/models/ticket.service.mjs +33 -33
- package/esm2022/lib/services/navigator.service.mjs +4 -5
- package/esm2022/lib/services/viewer.service.mjs +22 -7
- package/esm2022/lib/tokens/matterport-sdk-key.token.mjs +8 -0
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +466 -166
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/services/matterport-import.service.d.ts +12 -1
- package/lib/services/matterport-navigation.service.d.ts +30 -0
- package/lib/services/matterport.service.d.ts +6 -1
- package/lib/services/models/ticket.service.d.ts +1 -1
- package/lib/services/viewer.service.d.ts +14 -2
- package/lib/tokens/matterport-sdk-key.token.d.ts +7 -0
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Input, Component, Inject, EventEmitter, isDevMode, Output, Pipe, ViewChild, NgModule } from '@angular/core';
|
|
2
|
+
import { Injectable, Input, Component, InjectionToken, Inject, EventEmitter, isDevMode, Output, Pipe, ViewChild, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1 from '@ngx-translate/core';
|
|
4
4
|
import { TranslateModule } from '@ngx-translate/core';
|
|
5
5
|
import { Subject, BehaviorSubject, takeUntil, Observable } from 'rxjs';
|
|
@@ -96,6 +96,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
96
96
|
type: Input
|
|
97
97
|
}] } });
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Injection token holding the Matterport SDK application key.
|
|
101
|
+
* Each consuming app must provide its own value via its environment file
|
|
102
|
+
* (see app.module.ts of each app for the provider registration).
|
|
103
|
+
*/
|
|
104
|
+
const MATTERPORT_SDK_KEY = new InjectionToken('MATTERPORT_SDK_KEY');
|
|
105
|
+
|
|
99
106
|
var CameraMode;
|
|
100
107
|
(function (CameraMode) {
|
|
101
108
|
CameraMode["DOLLHOUSE"] = "mode.dollhouse";
|
|
@@ -734,9 +741,15 @@ class SecurityCamera extends SceneComponent {
|
|
|
734
741
|
this.highlight = new THREE.Mesh(roomMesh.geometry, shader);
|
|
735
742
|
}
|
|
736
743
|
toggleViewFrustum() {
|
|
737
|
-
this.highlight
|
|
738
|
-
|
|
739
|
-
|
|
744
|
+
if (this.highlight) {
|
|
745
|
+
this.highlight.visible = !this.highlight.visible;
|
|
746
|
+
}
|
|
747
|
+
if (this.edges) {
|
|
748
|
+
this.edges.visible = !this.edges.visible;
|
|
749
|
+
}
|
|
750
|
+
if (this.pivot) {
|
|
751
|
+
this.pivot.visible = !this.pivot.visible;
|
|
752
|
+
}
|
|
740
753
|
}
|
|
741
754
|
makeAnimation() {
|
|
742
755
|
const THREE = this.context.three;
|
|
@@ -2227,7 +2240,67 @@ class MatterportNavigationService {
|
|
|
2227
2240
|
currentRooms = [];
|
|
2228
2241
|
/** Sequence number of the floor currently visible in sdk.Floor.current (null = single-floor or unknown). */
|
|
2229
2242
|
currentFloorSequence = null;
|
|
2243
|
+
// ── Bidirectional sid ↔ uuid lookup maps ──
|
|
2244
|
+
// sid = short runtime key used by Matterport SDK (collection keys, Sweep.moveTo, Camera.pose.sweep)
|
|
2245
|
+
// uuid = persistent identifier stored in the database (zone.sweepIDs, poi.matterportSweepID, startSweepID)
|
|
2246
|
+
sidToUuid = new Map();
|
|
2247
|
+
uuidToSid = new Map();
|
|
2230
2248
|
constructor() { }
|
|
2249
|
+
// ── Sweep ID translation helpers ──
|
|
2250
|
+
/**
|
|
2251
|
+
* Builds the bidirectional sid ↔ uuid maps from the sweep collection.
|
|
2252
|
+
* Must be called every time the sweep collection is updated.
|
|
2253
|
+
*/
|
|
2254
|
+
buildSweepIdMaps(collection) {
|
|
2255
|
+
this.sidToUuid.clear();
|
|
2256
|
+
this.uuidToSid.clear();
|
|
2257
|
+
if (!collection)
|
|
2258
|
+
return;
|
|
2259
|
+
for (const sid of Object.keys(collection)) {
|
|
2260
|
+
const sweepData = collection[sid];
|
|
2261
|
+
const uuid = sweepData?.uuid;
|
|
2262
|
+
if (uuid && uuid !== sid) {
|
|
2263
|
+
this.sidToUuid.set(sid, uuid);
|
|
2264
|
+
this.uuidToSid.set(uuid, sid);
|
|
2265
|
+
}
|
|
2266
|
+
// Also map sid→sid and uuid→uuid for pass-through cases
|
|
2267
|
+
this.sidToUuid.set(sid, uuid || sid);
|
|
2268
|
+
if (uuid) {
|
|
2269
|
+
this.uuidToSid.set(uuid, sid);
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
if (isDevMode()) {
|
|
2273
|
+
console.debug(`[MatterportNavigation] Built sweep ID maps: ${this.sidToUuid.size} sids, ${this.uuidToSid.size} uuids`);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Resolves any sweep identifier (sid or uuid) to the SDK runtime **sid**.
|
|
2278
|
+
* This is what sdk.Sweep.moveTo() and sdk.Sweep.disable() expect.
|
|
2279
|
+
* Falls back to the input if no mapping exists.
|
|
2280
|
+
*/
|
|
2281
|
+
resolveSweepSid(idOrUuid) {
|
|
2282
|
+
if (!idOrUuid)
|
|
2283
|
+
return idOrUuid;
|
|
2284
|
+
// If it's already a known sid (exists as a key in sweepCollection), return it
|
|
2285
|
+
if (this.sidToUuid.has(idOrUuid))
|
|
2286
|
+
return idOrUuid;
|
|
2287
|
+
// Otherwise try to map from uuid → sid
|
|
2288
|
+
return this.uuidToSid.get(idOrUuid) ?? idOrUuid;
|
|
2289
|
+
}
|
|
2290
|
+
/**
|
|
2291
|
+
* Resolves any sweep identifier (sid or uuid) to the persistent **uuid**.
|
|
2292
|
+
* This is what the database stores (zone.sweepIDs, poi.matterportSweepID).
|
|
2293
|
+
* Falls back to the input if no mapping exists.
|
|
2294
|
+
*/
|
|
2295
|
+
resolveSweepUuid(sidOrUuid) {
|
|
2296
|
+
if (!sidOrUuid)
|
|
2297
|
+
return sidOrUuid;
|
|
2298
|
+
// If it's already a known uuid, return it
|
|
2299
|
+
if (this.uuidToSid.has(sidOrUuid))
|
|
2300
|
+
return sidOrUuid;
|
|
2301
|
+
// Otherwise try to map from sid → uuid
|
|
2302
|
+
return this.sidToUuid.get(sidOrUuid) ?? sidOrUuid;
|
|
2303
|
+
}
|
|
2231
2304
|
async action_toolbox_floorplan(sdk) {
|
|
2232
2305
|
if (this.inTransitionMode || this.inTransitionSweep) {
|
|
2233
2306
|
console.log('viewer is in transition, cannot go floorplan');
|
|
@@ -2295,15 +2368,23 @@ class MatterportNavigationService {
|
|
|
2295
2368
|
console.warn('No matterport floor found to move to');
|
|
2296
2369
|
}
|
|
2297
2370
|
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Navigate to a sweep. The caller can pass either a sid or a uuid;
|
|
2373
|
+
* this method resolves it to the SDK sid before calling Sweep.moveTo().
|
|
2374
|
+
*/
|
|
2298
2375
|
async action_go_to_sweep(sdk, sweep, rotation) {
|
|
2299
|
-
|
|
2376
|
+
const resolvedSid = this.resolveSweepSid(sweep);
|
|
2377
|
+
if (this.forbiddenSweeps.includes(sweep) || this.forbiddenSweeps.includes(resolvedSid)) {
|
|
2300
2378
|
console.log('user is not allowed to go to this sweep');
|
|
2301
2379
|
return;
|
|
2302
2380
|
}
|
|
2381
|
+
if (isDevMode() && resolvedSid !== sweep) {
|
|
2382
|
+
console.debug(`[action_go_to_sweep] Resolved uuid "${sweep}" → sid "${resolvedSid}"`);
|
|
2383
|
+
}
|
|
2303
2384
|
setTimeout(async () => {
|
|
2304
2385
|
try {
|
|
2305
2386
|
this.inTransitionSweep = true;
|
|
2306
|
-
await sdk.Sweep.moveTo(
|
|
2387
|
+
await sdk.Sweep.moveTo(resolvedSid, {
|
|
2307
2388
|
transition: sdk.Camera.TransitionType.INSTANT,
|
|
2308
2389
|
transitionTime: 1500
|
|
2309
2390
|
});
|
|
@@ -2317,12 +2398,16 @@ class MatterportNavigationService {
|
|
|
2317
2398
|
}
|
|
2318
2399
|
}, 1000);
|
|
2319
2400
|
}
|
|
2401
|
+
/**
|
|
2402
|
+
* Disable forbidden sweeps. Resolves each sweep ID to sid before calling SDK.
|
|
2403
|
+
*/
|
|
2320
2404
|
async removeForbiddenSweeps(sdk, forbiddenSweeps) {
|
|
2321
2405
|
this.forbiddenSweeps = [...forbiddenSweeps];
|
|
2322
2406
|
let removed = 0;
|
|
2323
2407
|
await Promise.all(forbiddenSweeps.map(async (sweep) => {
|
|
2408
|
+
const resolvedSid = this.resolveSweepSid(sweep);
|
|
2324
2409
|
try {
|
|
2325
|
-
await sdk.Sweep.disable(
|
|
2410
|
+
await sdk.Sweep.disable(resolvedSid);
|
|
2326
2411
|
removed += 1;
|
|
2327
2412
|
}
|
|
2328
2413
|
catch (error) {
|
|
@@ -2331,8 +2416,15 @@ class MatterportNavigationService {
|
|
|
2331
2416
|
}));
|
|
2332
2417
|
console.log('removed sweeps:', removed);
|
|
2333
2418
|
}
|
|
2419
|
+
/**
|
|
2420
|
+
* Returns the current sweep as a **uuid** (for database matching).
|
|
2421
|
+
* The SDK's poseCamera.sweep is a sid; we translate it.
|
|
2422
|
+
*/
|
|
2334
2423
|
getCurrentSweep(poseCamera) {
|
|
2335
|
-
|
|
2424
|
+
const sid = poseCamera?.sweep || null;
|
|
2425
|
+
if (!sid)
|
|
2426
|
+
return null;
|
|
2427
|
+
return this.resolveSweepUuid(sid);
|
|
2336
2428
|
}
|
|
2337
2429
|
setCameraMode(mode) {
|
|
2338
2430
|
this.inTransitionSweep = false;
|
|
@@ -3450,8 +3542,12 @@ class MatterportTagService {
|
|
|
3450
3542
|
if (mattertagData.elementID === elementID) {
|
|
3451
3543
|
tagID = mattertagID;
|
|
3452
3544
|
const sweep = mattertagData.getSweepID();
|
|
3453
|
-
if (sweep && sweeps
|
|
3454
|
-
|
|
3545
|
+
if (sweep && sweeps) {
|
|
3546
|
+
// sweep is a uuid; sweeps array contains sids – check both formats
|
|
3547
|
+
const resolvedSid = this.navigationService.resolveSweepSid(sweep);
|
|
3548
|
+
if (sweeps.includes(sweep) || sweeps.includes(resolvedSid)) {
|
|
3549
|
+
sweepID = sweep;
|
|
3550
|
+
}
|
|
3455
3551
|
}
|
|
3456
3552
|
}
|
|
3457
3553
|
}
|
|
@@ -3516,23 +3612,34 @@ class MatterportTagService {
|
|
|
3516
3612
|
else if (sdk) {
|
|
3517
3613
|
const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
|
|
3518
3614
|
if (comment) {
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
label: object.title || 'Media',
|
|
3524
|
-
},
|
|
3525
|
-
});
|
|
3615
|
+
// 1) Register the media attachment by passing the URL string(s).
|
|
3616
|
+
// registerAttachment returns an array of attachment IDs.
|
|
3617
|
+
const [attachmentID] = await sdk.Tag.registerAttachment(comment.externalLink);
|
|
3618
|
+
// 2) Attach the registered media to the tag.
|
|
3526
3619
|
await sdk.Tag.attach(tagID, attachmentID);
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3620
|
+
// 3) Determine media type for the billboard (PHOTO or VIDEO).
|
|
3621
|
+
// Use a simple heuristic: YouTube/Vimeo -> VIDEO, otherwise PHOTO.
|
|
3622
|
+
// The SDK exposes MediaType on the Tag namespace.
|
|
3623
|
+
const isVideo = /youtube\.com|youtu\.be|vimeo\.com/i.test(comment.externalLink);
|
|
3624
|
+
const mediaType = isVideo ? sdk.Mattertag.MediaType.VIDEO : sdk.Mattertag.MediaType.PHOTO;
|
|
3625
|
+
// 4) Update the billboard text and media using editBillboard.
|
|
3626
|
+
// editBillboard accepts Partial<Tag.EditableProperties> such as label, description, media.
|
|
3627
|
+
await sdk.Tag.editBillboard(tagID, {
|
|
3628
|
+
label: object.title || 'Media',
|
|
3629
|
+
description: tagDescription || '',
|
|
3630
|
+
media: {
|
|
3631
|
+
type: mediaType,
|
|
3632
|
+
src: comment.externalLink,
|
|
3532
3633
|
},
|
|
3533
3634
|
});
|
|
3534
|
-
|
|
3535
|
-
this.tagsAttachments[tagID] =
|
|
3635
|
+
// 5) Keep a local reference
|
|
3636
|
+
this.tagsAttachments[tagID] = {
|
|
3637
|
+
attachmentID,
|
|
3638
|
+
title: object.title || 'Media',
|
|
3639
|
+
description: tagDescription || '',
|
|
3640
|
+
mediaSrc: comment.externalLink,
|
|
3641
|
+
mediaType,
|
|
3642
|
+
};
|
|
3536
3643
|
}
|
|
3537
3644
|
}
|
|
3538
3645
|
}
|
|
@@ -3563,6 +3670,7 @@ class Config {
|
|
|
3563
3670
|
}
|
|
3564
3671
|
|
|
3565
3672
|
class MatterportService {
|
|
3673
|
+
sdkKey;
|
|
3566
3674
|
router;
|
|
3567
3675
|
activeRoute;
|
|
3568
3676
|
visibilityService;
|
|
@@ -3726,7 +3834,8 @@ class MatterportService {
|
|
|
3726
3834
|
pointerMiddleClickHandler = (e) => {
|
|
3727
3835
|
this.pointerService.updateCursorDisplay(this.poseMatterport);
|
|
3728
3836
|
};
|
|
3729
|
-
constructor(config, router, activeRoute, visibilityService, ngZone, measurementService, navigationService, pointerService, object3DService, matterportTagService) {
|
|
3837
|
+
constructor(config, sdkKey, router, activeRoute, visibilityService, ngZone, measurementService, navigationService, pointerService, object3DService, matterportTagService) {
|
|
3838
|
+
this.sdkKey = sdkKey;
|
|
3730
3839
|
this.router = router;
|
|
3731
3840
|
this.activeRoute = activeRoute;
|
|
3732
3841
|
this.visibilityService = visibilityService;
|
|
@@ -3771,7 +3880,7 @@ class MatterportService {
|
|
|
3771
3880
|
const showcaseWindow = iframe.contentWindow;
|
|
3772
3881
|
iframe.addEventListener('load', async () => {
|
|
3773
3882
|
try {
|
|
3774
|
-
this.sdk = await showcaseWindow.MP_SDK.connect(showcaseWindow,
|
|
3883
|
+
this.sdk = await showcaseWindow.MP_SDK.connect(showcaseWindow, this.sdkKey, '');
|
|
3775
3884
|
}
|
|
3776
3885
|
catch (e) {
|
|
3777
3886
|
console.error(e);
|
|
@@ -3862,13 +3971,16 @@ class MatterportService {
|
|
|
3862
3971
|
onCollectionUpdated: function subscr(collection) {
|
|
3863
3972
|
this.sweeps = Object.keys(collection);
|
|
3864
3973
|
this.sweepCollection = collection;
|
|
3974
|
+
// Rebuild sid ↔ uuid maps whenever the collection updates
|
|
3975
|
+
this.navigationService.buildSweepIdMaps(collection);
|
|
3865
3976
|
}.bind(this),
|
|
3866
3977
|
});
|
|
3867
|
-
// subscribe to current sweep
|
|
3978
|
+
// subscribe to current sweep – emit uuid (DB format) instead of raw sid
|
|
3868
3979
|
this.sdk.Sweep.current.subscribe(function subscr(currentSweep) {
|
|
3869
3980
|
if (currentSweep.sid === '')
|
|
3870
3981
|
return;
|
|
3871
|
-
this.
|
|
3982
|
+
const uuid = this.navigationService.resolveSweepUuid(currentSweep.sid);
|
|
3983
|
+
this.currentSweep.next(uuid);
|
|
3872
3984
|
}.bind(this));
|
|
3873
3985
|
// Subscribe to Floor data
|
|
3874
3986
|
this.sdk.Floor.data.subscribe({
|
|
@@ -3994,11 +4106,14 @@ class MatterportService {
|
|
|
3994
4106
|
});
|
|
3995
4107
|
});
|
|
3996
4108
|
}
|
|
4109
|
+
/**
|
|
4110
|
+
* @deprecated Use navigationService.resolveSweepUuid() instead.
|
|
4111
|
+
* Kept temporarily for backwards compatibility.
|
|
4112
|
+
*/
|
|
3997
4113
|
getSweepUUIDForSid(sid) {
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
return collection[sid].uuid ?? null;
|
|
4114
|
+
return this.navigationService.resolveSweepUuid(sid) !== sid
|
|
4115
|
+
? this.navigationService.resolveSweepUuid(sid)
|
|
4116
|
+
: null;
|
|
4002
4117
|
}
|
|
4003
4118
|
setLightingOff() {
|
|
4004
4119
|
this.noLightForObjects = true;
|
|
@@ -4374,7 +4489,7 @@ class MatterportService {
|
|
|
4374
4489
|
mattertagData.setPosition(JSON.parse(poi.coordinate));
|
|
4375
4490
|
mattertagData.setPoi(poi); // to keep custom tagIcon and opacity
|
|
4376
4491
|
}
|
|
4377
|
-
mattertagData.setSweepID(this.poseCamera.sweep);
|
|
4492
|
+
mattertagData.setSweepID(this.navigationService.resolveSweepUuid(this.poseCamera.sweep));
|
|
4378
4493
|
mattertagData.setRotation(this.poseCamera.rotation);
|
|
4379
4494
|
mattertagData.setObject(element, poiType);
|
|
4380
4495
|
this.mattertagToFollow = await this.addMattertagToViewer(mattertagData);
|
|
@@ -4387,7 +4502,7 @@ class MatterportService {
|
|
|
4387
4502
|
*/
|
|
4388
4503
|
async addMattertagWhenAdding(poiType) {
|
|
4389
4504
|
const mattertagData = new MattertagData(poiType);
|
|
4390
|
-
mattertagData.setSweepID(this.poseCamera.sweep);
|
|
4505
|
+
mattertagData.setSweepID(this.navigationService.resolveSweepUuid(this.poseCamera.sweep));
|
|
4391
4506
|
mattertagData.setRotation(this.poseCamera.rotation);
|
|
4392
4507
|
this.setInteractionMode(ViewerInteractions.ADDING);
|
|
4393
4508
|
await this.addCursorMattertag(mattertagData);
|
|
@@ -4674,7 +4789,7 @@ class MatterportService {
|
|
|
4674
4789
|
toggleViewFrustum() {
|
|
4675
4790
|
this.object3DService.toggleViewFrustum();
|
|
4676
4791
|
}
|
|
4677
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportService, deps: [{ token: 'config' }, { token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: BaseVisibilityService }, { token: i0.NgZone }, { token: MatterportMeasurementService }, { token: MatterportNavigationService }, { token: MatterportPointerService }, { token: MatterportObject3DService }, { token: MatterportTagService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4792
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportService, deps: [{ token: 'config' }, { token: MATTERPORT_SDK_KEY }, { token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: BaseVisibilityService }, { token: i0.NgZone }, { token: MatterportMeasurementService }, { token: MatterportNavigationService }, { token: MatterportPointerService }, { token: MatterportObject3DService }, { token: MatterportTagService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4678
4793
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportService, providedIn: 'root' });
|
|
4679
4794
|
}
|
|
4680
4795
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportService, decorators: [{
|
|
@@ -4685,6 +4800,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
4685
4800
|
}], ctorParameters: () => [{ type: Config, decorators: [{
|
|
4686
4801
|
type: Inject,
|
|
4687
4802
|
args: ['config']
|
|
4803
|
+
}] }, { type: undefined, decorators: [{
|
|
4804
|
+
type: Inject,
|
|
4805
|
+
args: [MATTERPORT_SDK_KEY]
|
|
4688
4806
|
}] }, { type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: BaseVisibilityService }, { type: i0.NgZone }, { type: MatterportMeasurementService }, { type: MatterportNavigationService }, { type: MatterportPointerService }, { type: MatterportObject3DService }, { type: MatterportTagService }] });
|
|
4689
4807
|
|
|
4690
4808
|
/* eslint-disable no-await-in-loop */
|
|
@@ -4692,6 +4810,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
4692
4810
|
/* eslint-disable no-underscore-dangle */
|
|
4693
4811
|
/* eslint-disable class-methods-use-this */
|
|
4694
4812
|
class ViewerService {
|
|
4813
|
+
sdkKey;
|
|
4695
4814
|
poiService;
|
|
4696
4815
|
matterportService;
|
|
4697
4816
|
viewerMode = 'Matterport';
|
|
@@ -4729,7 +4848,8 @@ class ViewerService {
|
|
|
4729
4848
|
},
|
|
4730
4849
|
};
|
|
4731
4850
|
isObjectLoaded = false;
|
|
4732
|
-
constructor(poiService, matterportService) {
|
|
4851
|
+
constructor(sdkKey, poiService, matterportService) {
|
|
4852
|
+
this.sdkKey = sdkKey;
|
|
4733
4853
|
this.poiService = poiService;
|
|
4734
4854
|
this.matterportService = matterportService;
|
|
4735
4855
|
this.setMode('Matterport');
|
|
@@ -4746,7 +4866,8 @@ class ViewerService {
|
|
|
4746
4866
|
setMode(indexMode) {
|
|
4747
4867
|
this.viewerMode = indexMode;
|
|
4748
4868
|
}
|
|
4749
|
-
setTourUrl(
|
|
4869
|
+
setTourUrl(options) {
|
|
4870
|
+
const { model3d, showIconPlan = true, showIconDollhouse = true, showIconFloors = true, showQuickStart = true, showFullscreen = true, showGuidedTour = true, showHighlightReel = true, showDefurnish = true, showRoomMeasurements = true } = options;
|
|
4750
4871
|
const baseUrl = `/assets/bundle/showcase.html`;
|
|
4751
4872
|
const params = [];
|
|
4752
4873
|
// Modèle
|
|
@@ -4758,7 +4879,7 @@ class ViewerService {
|
|
|
4758
4879
|
params.push(`log=0`);
|
|
4759
4880
|
params.push(`brand=0`);
|
|
4760
4881
|
params.push(`search=0`);
|
|
4761
|
-
params.push(`applicationKey
|
|
4882
|
+
params.push(`applicationKey=${this.sdkKey}`);
|
|
4762
4883
|
params.push(`mds=0`);
|
|
4763
4884
|
// Quick start
|
|
4764
4885
|
if (showQuickStart) {
|
|
@@ -4789,6 +4910,14 @@ class ViewerService {
|
|
|
4789
4910
|
if (!showFullscreen) {
|
|
4790
4911
|
params.push(`fs=0`);
|
|
4791
4912
|
}
|
|
4913
|
+
// Defurnish
|
|
4914
|
+
if (showDefurnish) {
|
|
4915
|
+
params.push(`ad=1`);
|
|
4916
|
+
}
|
|
4917
|
+
// Room Measurements
|
|
4918
|
+
if (showRoomMeasurements) {
|
|
4919
|
+
params.push(`measurements=1`);
|
|
4920
|
+
}
|
|
4792
4921
|
this.tourUrl = `${baseUrl}?${params.join("&")}`;
|
|
4793
4922
|
}
|
|
4794
4923
|
async clearAll() {
|
|
@@ -5100,7 +5229,7 @@ class ViewerService {
|
|
|
5100
5229
|
isObject3DLoadedInPosition() {
|
|
5101
5230
|
return this.isObjectLoaded;
|
|
5102
5231
|
}
|
|
5103
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerService, deps: [{ token: PoiService }, { token: MatterportService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5232
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerService, deps: [{ token: MATTERPORT_SDK_KEY }, { token: PoiService }, { token: MatterportService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5104
5233
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerService, providedIn: 'root' });
|
|
5105
5234
|
}
|
|
5106
5235
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerService, decorators: [{
|
|
@@ -5108,7 +5237,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
5108
5237
|
args: [{
|
|
5109
5238
|
providedIn: 'root',
|
|
5110
5239
|
}]
|
|
5111
|
-
}], ctorParameters: () => [{ type:
|
|
5240
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
5241
|
+
type: Inject,
|
|
5242
|
+
args: [MATTERPORT_SDK_KEY]
|
|
5243
|
+
}] }, { type: PoiService }, { type: MatterportService }] });
|
|
5112
5244
|
|
|
5113
5245
|
class ModalSwitchVisitComponent {
|
|
5114
5246
|
activeModal;
|
|
@@ -6187,26 +6319,29 @@ class FilterService {
|
|
|
6187
6319
|
zoneID = null, zone = null) {
|
|
6188
6320
|
const filteredObjects = [];
|
|
6189
6321
|
await Promise.all(objects.map(async (object) => {
|
|
6190
|
-
const
|
|
6191
|
-
if (
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6322
|
+
const pois = object.pois;
|
|
6323
|
+
if (pois) {
|
|
6324
|
+
const [poi] = pois.items;
|
|
6325
|
+
if (poi && zone) {
|
|
6326
|
+
if (zone.sweepIDs && zone.sweepIDs.includes(poi.matterportSweepID)) {
|
|
6327
|
+
if (this.poiService.poiIsVirtual(poi) && zone.layer && zone.layer.name === "FLOOR") {
|
|
6328
|
+
// we include in Floor zone only
|
|
6329
|
+
filteredObjects.push(object);
|
|
6330
|
+
}
|
|
6331
|
+
if (!this.poiService.poiIsVirtual(poi)) {
|
|
6332
|
+
filteredObjects.push(object);
|
|
6333
|
+
}
|
|
6196
6334
|
}
|
|
6197
|
-
|
|
6335
|
+
}
|
|
6336
|
+
if (poi && !zone && zoneID) {
|
|
6337
|
+
const zones = await this.zoneService.getZonesForObject(object);
|
|
6338
|
+
if (zones &&
|
|
6339
|
+
zones.some((zone_) => zone_.id === zoneID ||
|
|
6340
|
+
zone_.parentID === zoneID)) {
|
|
6198
6341
|
filteredObjects.push(object);
|
|
6199
6342
|
}
|
|
6200
6343
|
}
|
|
6201
6344
|
}
|
|
6202
|
-
if (poi && !zone && zoneID) {
|
|
6203
|
-
const zones = await this.zoneService.getZonesForObject(object);
|
|
6204
|
-
if (zones &&
|
|
6205
|
-
zones.some((zone_) => zone_.id === zoneID ||
|
|
6206
|
-
zone_.parentID === zoneID)) {
|
|
6207
|
-
filteredObjects.push(object);
|
|
6208
|
-
}
|
|
6209
|
-
}
|
|
6210
6345
|
}));
|
|
6211
6346
|
return filteredObjects;
|
|
6212
6347
|
}
|
|
@@ -7166,10 +7301,9 @@ class NavigatorService {
|
|
|
7166
7301
|
if (!this.currentSweep) {
|
|
7167
7302
|
return;
|
|
7168
7303
|
}
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
let zonesForSweep = this.zonesForUserForSpace?.filter((zone) => zone.sweepIDs && zone.sweepIDs.includes(sweepToMatch));
|
|
7304
|
+
// currentSweep is already a uuid (translated at the source in MatterportService),
|
|
7305
|
+
// so it matches directly against zone.sweepIDs which store uuids from the import.
|
|
7306
|
+
let zonesForSweep = this.zonesForUserForSpace?.filter((zone) => zone.sweepIDs && zone.sweepIDs.includes(this.currentSweep));
|
|
7173
7307
|
const audioZones = this.audioZonesForUserForSpace?.filter((zone) => zone.sweepIDs && zone.sweepIDs.includes(this.currentSweep));
|
|
7174
7308
|
this.audioZonesChange.next(audioZones);
|
|
7175
7309
|
this.currentAudioZones = audioZones;
|
|
@@ -7478,7 +7612,7 @@ class TicketsService extends BaseObjectService {
|
|
|
7478
7612
|
awsKinesisAnalytics; //AWS
|
|
7479
7613
|
isMuseumUser = false;
|
|
7480
7614
|
navSubscription;
|
|
7481
|
-
|
|
7615
|
+
filterSubscription;
|
|
7482
7616
|
floorsPerSpace = null;
|
|
7483
7617
|
selectedFloor = null;
|
|
7484
7618
|
destroy$ = new Subject();
|
|
@@ -7506,7 +7640,7 @@ class TicketsService extends BaseObjectService {
|
|
|
7506
7640
|
else {
|
|
7507
7641
|
if (this.navSubscription) {
|
|
7508
7642
|
this.navSubscription.unsubscribe();
|
|
7509
|
-
this.
|
|
7643
|
+
this.filterSubscription.unsubscribe();
|
|
7510
7644
|
}
|
|
7511
7645
|
}
|
|
7512
7646
|
});
|
|
@@ -7517,6 +7651,9 @@ class TicketsService extends BaseObjectService {
|
|
|
7517
7651
|
});
|
|
7518
7652
|
}
|
|
7519
7653
|
async initTickets() {
|
|
7654
|
+
if (this.userService.getSpModule() === SpModule.MUSEUM) {
|
|
7655
|
+
return;
|
|
7656
|
+
}
|
|
7520
7657
|
let ticketsFiltered = [];
|
|
7521
7658
|
if (this.currentSpaceID) {
|
|
7522
7659
|
this.updating.next(true);
|
|
@@ -7689,11 +7826,8 @@ class TicketsService extends BaseObjectService {
|
|
|
7689
7826
|
if (!ticket.ownerMissionID) {
|
|
7690
7827
|
ticket.ownerMissionID = this.userService.currentMission(ticket.spaceID).id;
|
|
7691
7828
|
}
|
|
7692
|
-
// TODO!!! filter missions by space of ticket
|
|
7693
7829
|
try {
|
|
7694
7830
|
const receivedTicket = await this.createTicket(ticket);
|
|
7695
|
-
// console.log('!!! Response from creating ticket :');
|
|
7696
|
-
// console.log(receivedTicket);
|
|
7697
7831
|
this.addEventToTicket(receivedTicket, {
|
|
7698
7832
|
title: 'Création du ticket',
|
|
7699
7833
|
description: `Ticket créé par -`,
|
|
@@ -7750,7 +7884,6 @@ class TicketsService extends BaseObjectService {
|
|
|
7750
7884
|
}
|
|
7751
7885
|
async updateStatusOfTicket(ticket, status) {
|
|
7752
7886
|
const currentStatus = ticket.status;
|
|
7753
|
-
const oldTicketStatus = ticket.status;
|
|
7754
7887
|
ticket.status = status;
|
|
7755
7888
|
if (currentStatus === status) {
|
|
7756
7889
|
return ticket;
|
|
@@ -7916,32 +8049,33 @@ class TicketsService extends BaseObjectService {
|
|
|
7916
8049
|
}
|
|
7917
8050
|
}
|
|
7918
8051
|
initSubscriptions() {
|
|
7919
|
-
if (
|
|
7920
|
-
|
|
7921
|
-
this.currentSpaceID = this.navigatorService.currentSpaceID;
|
|
7922
|
-
if (!this.currentSpaceID) {
|
|
7923
|
-
this.ticketTags.next(null);
|
|
7924
|
-
this.ticketsUpdated.next({ space: [], zone: null });
|
|
7925
|
-
this.ticketTypeFilter = null;
|
|
7926
|
-
this.zoneIDFilter = null;
|
|
7927
|
-
}
|
|
7928
|
-
else if (zone.id !== this.zoneIDFilter) {
|
|
7929
|
-
this.zoneIDFilter = zone.id;
|
|
7930
|
-
// console.log("going to init tickets from zone");
|
|
7931
|
-
this.initTickets().catch((e) => console.log(e.message));
|
|
7932
|
-
}
|
|
7933
|
-
});
|
|
7934
|
-
this.filetrSubscription = this.filterService.subscribeToDataFilterUpdate((dateRange) => {
|
|
7935
|
-
this.dateFilter = dateRange;
|
|
7936
|
-
this.initTickets().catch((e) => console.log(e.message));
|
|
7937
|
-
});
|
|
7938
|
-
this.dateFilter = this.filterService.currentDateFilter;
|
|
7939
|
-
this.updateDone.subscribe(() => {
|
|
7940
|
-
if (this.currentSpaceID) {
|
|
7941
|
-
this.initTickets().catch((e) => console.log(e.message));
|
|
7942
|
-
}
|
|
7943
|
-
});
|
|
8052
|
+
if (this.userService.getSpModule() === SpModule.MUSEUM) {
|
|
8053
|
+
return;
|
|
7944
8054
|
}
|
|
8055
|
+
this.navSubscription = this.zoneChangeService.zoneChange.subscribe((zone) => {
|
|
8056
|
+
this.currentSpaceID = this.navigatorService.currentSpaceID;
|
|
8057
|
+
if (!this.currentSpaceID) {
|
|
8058
|
+
this.ticketTags.next(null);
|
|
8059
|
+
this.ticketsUpdated.next({ space: [], zone: null });
|
|
8060
|
+
this.ticketTypeFilter = null;
|
|
8061
|
+
this.zoneIDFilter = null;
|
|
8062
|
+
}
|
|
8063
|
+
else if (zone.id !== this.zoneIDFilter) {
|
|
8064
|
+
this.zoneIDFilter = zone.id;
|
|
8065
|
+
// console.log("going to init tickets from zone");
|
|
8066
|
+
this.initTickets().catch((e) => console.log(e.message));
|
|
8067
|
+
}
|
|
8068
|
+
});
|
|
8069
|
+
this.filterSubscription = this.filterService.subscribeToDataFilterUpdate((dateRange) => {
|
|
8070
|
+
this.dateFilter = dateRange;
|
|
8071
|
+
this.initTickets().catch((e) => console.log(e.message));
|
|
8072
|
+
});
|
|
8073
|
+
this.dateFilter = this.filterService.currentDateFilter;
|
|
8074
|
+
this.updateDone.subscribe(() => {
|
|
8075
|
+
if (this.currentSpaceID) {
|
|
8076
|
+
this.initTickets().catch((e) => console.log(e.message));
|
|
8077
|
+
}
|
|
8078
|
+
});
|
|
7945
8079
|
}
|
|
7946
8080
|
unsubscribe() {
|
|
7947
8081
|
this.destroy$.next(true);
|
|
@@ -8335,7 +8469,7 @@ class EquipmentService extends BaseObjectService {
|
|
|
8335
8469
|
});
|
|
8336
8470
|
}
|
|
8337
8471
|
async initEquips() {
|
|
8338
|
-
if (!this.currentSpaceID) {
|
|
8472
|
+
if (!this.currentSpaceID || this.userService.getSpModule() === SpModule.MUSEUM) {
|
|
8339
8473
|
return;
|
|
8340
8474
|
}
|
|
8341
8475
|
this.updating.next(true);
|
|
@@ -8563,64 +8697,56 @@ class EquipmentService extends BaseObjectService {
|
|
|
8563
8697
|
}); // for lateral menu
|
|
8564
8698
|
}
|
|
8565
8699
|
initSubscriptions() {
|
|
8566
|
-
if (
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
}
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
// zone,
|
|
8589
|
-
// );
|
|
8590
|
-
this.updateEquipsForZone();
|
|
8591
|
-
}
|
|
8592
|
-
else {
|
|
8593
|
-
this.currentSpaceID = this.navigatorService.currentSpaceID;
|
|
8594
|
-
// console.log(
|
|
8595
|
-
// "going to init equips for zone for new space",
|
|
8596
|
-
// this.currentSpaceID,
|
|
8597
|
-
// );
|
|
8598
|
-
this.initEquips();
|
|
8599
|
-
}
|
|
8600
|
-
}
|
|
8601
|
-
});
|
|
8602
|
-
this.deleteObservable
|
|
8603
|
-
.pipe(takeUntil(this.destroy$))
|
|
8604
|
-
.subscribe((equipment) => {
|
|
8605
|
-
if (this.currentSpaceID) {
|
|
8606
|
-
this.updateDueToDelete(equipment);
|
|
8607
|
-
}
|
|
8608
|
-
});
|
|
8609
|
-
this.createObservable
|
|
8610
|
-
.pipe(takeUntil(this.destroy$))
|
|
8611
|
-
.subscribe((equipment) => {
|
|
8612
|
-
if (this.currentSpaceID) {
|
|
8613
|
-
this.updateDueToCreate(equipment);
|
|
8700
|
+
if (this.userService.getSpModule() === SpModule.MUSEUM) {
|
|
8701
|
+
return;
|
|
8702
|
+
}
|
|
8703
|
+
this.zoneChangeService.zoneChange
|
|
8704
|
+
.pipe(takeUntil(this.destroy$))
|
|
8705
|
+
.subscribe((zone) => {
|
|
8706
|
+
if (!zone || !this.navigatorService.currentSpaceID) {
|
|
8707
|
+
this.currentSpaceID = this.navigatorService.currentSpaceID;
|
|
8708
|
+
this.equipmentsTags.next(null);
|
|
8709
|
+
this.equipmentsUpdated.next({ space: [], zone: null });
|
|
8710
|
+
this.zoneIDFilter = null;
|
|
8711
|
+
this.currentEquipments = {
|
|
8712
|
+
space: [],
|
|
8713
|
+
zonesMap: new Map(),
|
|
8714
|
+
};
|
|
8715
|
+
return;
|
|
8716
|
+
}
|
|
8717
|
+
if (zone.id !== this.zoneIDFilter) {
|
|
8718
|
+
this.zoneIDFilter = zone.id;
|
|
8719
|
+
this.currentZone = zone;
|
|
8720
|
+
if (this.currentSpaceID === this.navigatorService.currentSpaceID) {
|
|
8721
|
+
this.updateEquipsForZone();
|
|
8614
8722
|
}
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
.subscribe((equipment) => {
|
|
8619
|
-
if (this.currentSpaceID) {
|
|
8620
|
-
this.updateDueToEquipUpdated(equipment);
|
|
8723
|
+
else {
|
|
8724
|
+
this.currentSpaceID = this.navigatorService.currentSpaceID;
|
|
8725
|
+
this.initEquips();
|
|
8621
8726
|
}
|
|
8622
|
-
}
|
|
8623
|
-
}
|
|
8727
|
+
}
|
|
8728
|
+
});
|
|
8729
|
+
this.deleteObservable
|
|
8730
|
+
.pipe(takeUntil(this.destroy$))
|
|
8731
|
+
.subscribe((equipment) => {
|
|
8732
|
+
if (this.currentSpaceID) {
|
|
8733
|
+
this.updateDueToDelete(equipment);
|
|
8734
|
+
}
|
|
8735
|
+
});
|
|
8736
|
+
this.createObservable
|
|
8737
|
+
.pipe(takeUntil(this.destroy$))
|
|
8738
|
+
.subscribe((equipment) => {
|
|
8739
|
+
if (this.currentSpaceID) {
|
|
8740
|
+
this.updateDueToCreate(equipment);
|
|
8741
|
+
}
|
|
8742
|
+
});
|
|
8743
|
+
this.updateObservable
|
|
8744
|
+
.pipe(takeUntil(this.destroy$))
|
|
8745
|
+
.subscribe((equipment) => {
|
|
8746
|
+
if (this.currentSpaceID) {
|
|
8747
|
+
this.updateDueToEquipUpdated(equipment);
|
|
8748
|
+
}
|
|
8749
|
+
});
|
|
8624
8750
|
}
|
|
8625
8751
|
unsubscribe() {
|
|
8626
8752
|
this.destroy$.next(true);
|
|
@@ -9632,8 +9758,11 @@ class CommentService {
|
|
|
9632
9758
|
if (comment.ticketID && !comment.ticket) {
|
|
9633
9759
|
comment.ticket = await this.API.__proto__.GetTicket(comment.ticketID);
|
|
9634
9760
|
}
|
|
9635
|
-
|
|
9636
|
-
|
|
9761
|
+
let values = comment.dimensions;
|
|
9762
|
+
let numberPoints = 0;
|
|
9763
|
+
if (values) {
|
|
9764
|
+
numberPoints = values.length + 1;
|
|
9765
|
+
}
|
|
9637
9766
|
const poi = await this.poiService.getPoiByElementId(commentID);
|
|
9638
9767
|
const measure = {
|
|
9639
9768
|
id: comment.id,
|
|
@@ -12500,6 +12629,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
12500
12629
|
}] }] });
|
|
12501
12630
|
|
|
12502
12631
|
class MatterportImportService {
|
|
12632
|
+
sdkKey;
|
|
12503
12633
|
navigationService;
|
|
12504
12634
|
zoneService;
|
|
12505
12635
|
viewerService;
|
|
@@ -12529,7 +12659,8 @@ class MatterportImportService {
|
|
|
12529
12659
|
importingImages = new Subject();
|
|
12530
12660
|
sweepProcessedCount = new Subject();
|
|
12531
12661
|
totalSweepsCount = new Subject();
|
|
12532
|
-
constructor(navigationService, zoneService, viewerService, layerService, userService, planService) {
|
|
12662
|
+
constructor(sdkKey, navigationService, zoneService, viewerService, layerService, userService, planService) {
|
|
12663
|
+
this.sdkKey = sdkKey;
|
|
12533
12664
|
this.navigationService = navigationService;
|
|
12534
12665
|
this.zoneService = zoneService;
|
|
12535
12666
|
this.viewerService = viewerService;
|
|
@@ -12546,7 +12677,7 @@ class MatterportImportService {
|
|
|
12546
12677
|
if (!iframe) {
|
|
12547
12678
|
throw new Error('Cannot create iframe');
|
|
12548
12679
|
}
|
|
12549
|
-
this.viewerService.setTourUrl(modelID);
|
|
12680
|
+
this.viewerService.setTourUrl({ model3d: modelID });
|
|
12550
12681
|
const url = this.viewerService.getTourUrl();
|
|
12551
12682
|
iframe.setAttribute('src', url);
|
|
12552
12683
|
iframe.allow = 'xr-spatial-tracking';
|
|
@@ -12560,7 +12691,7 @@ class MatterportImportService {
|
|
|
12560
12691
|
return new Promise((res, rej) => {
|
|
12561
12692
|
iframe.addEventListener('load', async () => {
|
|
12562
12693
|
try {
|
|
12563
|
-
this.sdk = await showcaseWindow.MP_SDK.connect(iframe,
|
|
12694
|
+
this.sdk = await showcaseWindow.MP_SDK.connect(iframe, this.sdkKey, '');
|
|
12564
12695
|
// Subscribe to Floor data
|
|
12565
12696
|
this.sdk.Floor.data.subscribe({
|
|
12566
12697
|
onCollectionUpdated: function upd(collection) {
|
|
@@ -12680,20 +12811,47 @@ class MatterportImportService {
|
|
|
12680
12811
|
const newLocal = await this.zoneService.create(zoneInput);
|
|
12681
12812
|
return newLocal;
|
|
12682
12813
|
}
|
|
12814
|
+
// --- Main import function (complete) ---
|
|
12683
12815
|
async import360images(overrideExisting = true) {
|
|
12684
12816
|
console.log('Importing 360 images');
|
|
12685
12817
|
this.importingImages.next(true);
|
|
12686
12818
|
return new Promise(async (resolve) => {
|
|
12687
12819
|
const scans = Object.values(this.sweeps);
|
|
12688
|
-
const nmbScans =
|
|
12820
|
+
const nmbScans = scans.length;
|
|
12689
12821
|
this.totalSweepsCount.next(nmbScans);
|
|
12690
12822
|
const start = overrideExisting ? 0 : await this.getUploadedImageCount(this.modelID);
|
|
12691
12823
|
for (let index = start; index < nmbScans; index += 1) {
|
|
12692
|
-
if (
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12824
|
+
if (this.stop) {
|
|
12825
|
+
console.log('Abandoning import because it was cancelled');
|
|
12826
|
+
resolve(false);
|
|
12827
|
+
this.removeFrame();
|
|
12828
|
+
break;
|
|
12829
|
+
}
|
|
12830
|
+
const sweep = scans[index];
|
|
12831
|
+
console.log('Moving to sweep:', sweep);
|
|
12832
|
+
// Prefer legacy .id first, then uuid, then sid as last resort
|
|
12833
|
+
const moveId = sweep.id || sweep.uuid || sweep.sid;
|
|
12834
|
+
try {
|
|
12835
|
+
// Move to sweep (use the best available id)
|
|
12836
|
+
await this.sdk.Sweep.moveTo(moveId, {
|
|
12837
|
+
rotation: { x: 0, y: 0 },
|
|
12838
|
+
transition: this.sdk.Camera && this.sdk.Camera.TransitionType
|
|
12839
|
+
? this.sdk.Camera.TransitionType.INSTANT
|
|
12840
|
+
: undefined,
|
|
12841
|
+
transitionTime: 0,
|
|
12842
|
+
});
|
|
12843
|
+
// Capture with automatic retry (ensures renderer readiness each attempt)
|
|
12844
|
+
const img = await this.captureEquirectangularWithRetry({ width: 2048, height: 1024 }, { mattertags: false, sweeps: true }, {
|
|
12845
|
+
maxAttempts: 3,
|
|
12846
|
+
initialBackoffMs: 500,
|
|
12847
|
+
perAttemptTimeoutMs: 8000,
|
|
12848
|
+
sweepIdForReadyCheck: moveId,
|
|
12849
|
+
waitForSweepTimeoutMs: 12000
|
|
12850
|
+
});
|
|
12851
|
+
// Upload asynchronously (do not await to keep throughput)
|
|
12852
|
+
uploadBase64ImageWithRetry(img,
|
|
12853
|
+
// prefer using uuid for storage name if available, else fallback to moveId
|
|
12854
|
+
sweep.uuid || moveId, `visits/${this.modelID}/sweeps/`, 'sweep', 5).then(() => {
|
|
12697
12855
|
this.sweepProcessedCount.next(index);
|
|
12698
12856
|
if (index === nmbScans - 1) {
|
|
12699
12857
|
console.log('Import 360 done');
|
|
@@ -12705,17 +12863,156 @@ class MatterportImportService {
|
|
|
12705
12863
|
console.log("Error uploading scan : ", e);
|
|
12706
12864
|
});
|
|
12707
12865
|
}
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
this.
|
|
12712
|
-
|
|
12866
|
+
catch (err) {
|
|
12867
|
+
// capture failed after retries — log and continue to next sweep
|
|
12868
|
+
console.error(`Failed to capture sweep ${moveId} after retries:`, err);
|
|
12869
|
+
this.sweepProcessedCount.next(index);
|
|
12870
|
+
// continue to next sweep (change to `throw err` if you want to abort on first failure)
|
|
12871
|
+
continue;
|
|
12713
12872
|
}
|
|
12714
12873
|
}
|
|
12874
|
+
// If loop finishes without hitting the final resolve in upload promise:
|
|
12715
12875
|
resolve(true);
|
|
12716
12876
|
this.removeFrame();
|
|
12717
12877
|
});
|
|
12718
12878
|
}
|
|
12879
|
+
// --- capture with retry and backoff ---
|
|
12880
|
+
// options: renderer size; renderOptions: renderer flags; cfg: retry config
|
|
12881
|
+
async captureEquirectangularWithRetry(options, renderOptions, { maxAttempts = 3, initialBackoffMs = 500, perAttemptTimeoutMs = 8000, sweepIdForReadyCheck = null, waitForSweepTimeoutMs = 12000 } = {}) {
|
|
12882
|
+
let attempt = 0;
|
|
12883
|
+
let lastError = null;
|
|
12884
|
+
while (attempt < maxAttempts) {
|
|
12885
|
+
attempt += 1;
|
|
12886
|
+
try {
|
|
12887
|
+
// Ensure sweep is ready before each attempt if requested
|
|
12888
|
+
if (sweepIdForReadyCheck) {
|
|
12889
|
+
await this.waitForSweepReady(sweepIdForReadyCheck, waitForSweepTimeoutMs);
|
|
12890
|
+
// small safety delay to let renderer finalize
|
|
12891
|
+
await this.sleep(120);
|
|
12892
|
+
}
|
|
12893
|
+
// Race the takeEquirectangular call against a per-attempt timeout
|
|
12894
|
+
const img = await Promise.race([
|
|
12895
|
+
this.sdk.Renderer.takeEquirectangular(options, renderOptions),
|
|
12896
|
+
this.timeoutPromise(perAttemptTimeoutMs, `takeEquirectangular timed out after ${perAttemptTimeoutMs}ms`)
|
|
12897
|
+
]);
|
|
12898
|
+
// success
|
|
12899
|
+
return img;
|
|
12900
|
+
}
|
|
12901
|
+
catch (err) {
|
|
12902
|
+
lastError = err;
|
|
12903
|
+
console.warn(`takeEquirectangular attempt ${attempt} failed:`, err);
|
|
12904
|
+
if (attempt >= maxAttempts) {
|
|
12905
|
+
throw lastError;
|
|
12906
|
+
}
|
|
12907
|
+
// exponential backoff before next attempt
|
|
12908
|
+
const backoff = initialBackoffMs * Math.pow(2, attempt - 1);
|
|
12909
|
+
// add small jitter to reduce thundering herd
|
|
12910
|
+
const jitter = Math.floor(Math.random() * 100);
|
|
12911
|
+
await this.sleep(backoff + jitter);
|
|
12912
|
+
// loop to next attempt
|
|
12913
|
+
}
|
|
12914
|
+
}
|
|
12915
|
+
throw lastError || new Error('captureEquirectangularWithRetry failed without error');
|
|
12916
|
+
}
|
|
12917
|
+
// --- Wait until the SDK reports the target sweep as current ---
|
|
12918
|
+
// Tries: sdk.Sweep.current.waitUntil -> sdk.Sweep.current.subscribe -> polling getCurrent/value
|
|
12919
|
+
// This function matches targetId against multiple fields and prioritizes .id matching.
|
|
12920
|
+
waitForSweepReady(targetId, timeoutMs = 10000) {
|
|
12921
|
+
const sdk = this.sdk;
|
|
12922
|
+
// helper to match multiple id fields, prioritizing id first
|
|
12923
|
+
const matchesTarget = (data) => {
|
|
12924
|
+
if (!data)
|
|
12925
|
+
return false;
|
|
12926
|
+
// check .id first (legacy), then uuid, sid, uid
|
|
12927
|
+
const fields = [data.id, data.uuid, data.sid, data.uid];
|
|
12928
|
+
return fields.some(f => !!f && String(f) === String(targetId));
|
|
12929
|
+
};
|
|
12930
|
+
// 1) prefer waitUntil if available on the observable
|
|
12931
|
+
if (sdk.Sweep && sdk.Sweep.current && typeof sdk.Sweep.current.waitUntil === 'function') {
|
|
12932
|
+
return Promise.race([
|
|
12933
|
+
sdk.Sweep.current.waitUntil((data) => matchesTarget(data)),
|
|
12934
|
+
this.timeoutPromise(timeoutMs, `Timeout waiting for sweep ${targetId}`)
|
|
12935
|
+
]);
|
|
12936
|
+
}
|
|
12937
|
+
// 2) subscribe if available
|
|
12938
|
+
if (sdk.Sweep && sdk.Sweep.current && typeof sdk.Sweep.current.subscribe === 'function') {
|
|
12939
|
+
return new Promise((resolve, reject) => {
|
|
12940
|
+
const timer = setTimeout(() => {
|
|
12941
|
+
if (off)
|
|
12942
|
+
off();
|
|
12943
|
+
reject(new Error(`Timeout waiting for sweep ${targetId}`));
|
|
12944
|
+
}, timeoutMs);
|
|
12945
|
+
let off = null;
|
|
12946
|
+
try {
|
|
12947
|
+
// subscribe may return an unsubscribe function or an object with unsubscribe()
|
|
12948
|
+
const subResult = sdk.Sweep.current.subscribe((data) => {
|
|
12949
|
+
if (matchesTarget(data)) {
|
|
12950
|
+
clearTimeout(timer);
|
|
12951
|
+
try {
|
|
12952
|
+
if (typeof subResult === 'function')
|
|
12953
|
+
subResult();
|
|
12954
|
+
else if (subResult && typeof subResult.unsubscribe === 'function')
|
|
12955
|
+
subResult.unsubscribe();
|
|
12956
|
+
}
|
|
12957
|
+
catch (e) { /*ignore*/ }
|
|
12958
|
+
resolve();
|
|
12959
|
+
}
|
|
12960
|
+
});
|
|
12961
|
+
// if subscribe returned an unsubscribe function, keep it as off
|
|
12962
|
+
if (typeof subResult === 'function')
|
|
12963
|
+
off = subResult;
|
|
12964
|
+
else if (subResult && typeof subResult.unsubscribe === 'function')
|
|
12965
|
+
off = () => subResult.unsubscribe();
|
|
12966
|
+
}
|
|
12967
|
+
catch (e) {
|
|
12968
|
+
clearTimeout(timer);
|
|
12969
|
+
reject(new Error('sdk.Sweep.current.subscribe not usable'));
|
|
12970
|
+
}
|
|
12971
|
+
});
|
|
12972
|
+
}
|
|
12973
|
+
// 3) polling fallback: try getCurrent(), sdk.Sweep.current() function, or .value, else poll renderer readiness
|
|
12974
|
+
return new Promise(async (resolve, reject) => {
|
|
12975
|
+
const pollInterval = 200;
|
|
12976
|
+
const timer = setTimeout(() => {
|
|
12977
|
+
clearInterval(interval);
|
|
12978
|
+
reject(new Error(`Timeout waiting for sweep ${targetId}`));
|
|
12979
|
+
}, timeoutMs);
|
|
12980
|
+
const checkNow = async () => {
|
|
12981
|
+
try {
|
|
12982
|
+
let current = null;
|
|
12983
|
+
if (sdk.Sweep && typeof sdk.Sweep.getCurrent === 'function') {
|
|
12984
|
+
current = await sdk.Sweep.getCurrent();
|
|
12985
|
+
}
|
|
12986
|
+
else if (sdk.Sweep && typeof sdk.Sweep.current === 'function') {
|
|
12987
|
+
// some builds expose a function
|
|
12988
|
+
current = await sdk.Sweep.current();
|
|
12989
|
+
}
|
|
12990
|
+
else if (sdk.Sweep && sdk.Sweep.current && sdk.Sweep.current.value) {
|
|
12991
|
+
// some observables expose a .value
|
|
12992
|
+
current = sdk.Sweep.current.value;
|
|
12993
|
+
}
|
|
12994
|
+
if (matchesTarget(current)) {
|
|
12995
|
+
clearTimeout(timer);
|
|
12996
|
+
clearInterval(interval);
|
|
12997
|
+
resolve();
|
|
12998
|
+
}
|
|
12999
|
+
}
|
|
13000
|
+
catch (e) {
|
|
13001
|
+
// ignore and retry until timeout
|
|
13002
|
+
}
|
|
13003
|
+
};
|
|
13004
|
+
// initial immediate check
|
|
13005
|
+
await checkNow();
|
|
13006
|
+
const interval = setInterval(checkNow, pollInterval);
|
|
13007
|
+
});
|
|
13008
|
+
}
|
|
13009
|
+
// --- small helpers ---
|
|
13010
|
+
sleep(ms) {
|
|
13011
|
+
return new Promise(res => setTimeout(res, ms));
|
|
13012
|
+
}
|
|
13013
|
+
timeoutPromise(ms, message) {
|
|
13014
|
+
return new Promise((_, reject) => setTimeout(() => reject(new Error(message)), ms));
|
|
13015
|
+
}
|
|
12719
13016
|
async getUploadedImageCount(modelID) {
|
|
12720
13017
|
try {
|
|
12721
13018
|
const images = await listFilesInFolder(`visits/${modelID}/sweeps/`);
|
|
@@ -12830,7 +13127,7 @@ class MatterportImportService {
|
|
|
12830
13127
|
// create then
|
|
12831
13128
|
return this.layerService.createLayerForOrganisation(name, currentOrgId);
|
|
12832
13129
|
}
|
|
12833
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportImportService, deps: [{ token: NavigationService }, { token: ZoneService }, { token: ViewerService }, { token: LayerService }, { token: BaseUserService }, { token: PlanService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
13130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportImportService, deps: [{ token: MATTERPORT_SDK_KEY }, { token: NavigationService }, { token: ZoneService }, { token: ViewerService }, { token: LayerService }, { token: BaseUserService }, { token: PlanService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
12834
13131
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportImportService, providedIn: 'root' });
|
|
12835
13132
|
}
|
|
12836
13133
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportImportService, decorators: [{
|
|
@@ -12838,7 +13135,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
12838
13135
|
args: [{
|
|
12839
13136
|
providedIn: 'root',
|
|
12840
13137
|
}]
|
|
12841
|
-
}], ctorParameters: () => [{ type:
|
|
13138
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
13139
|
+
type: Inject,
|
|
13140
|
+
args: [MATTERPORT_SDK_KEY]
|
|
13141
|
+
}] }, { type: NavigationService }, { type: ZoneService }, { type: ViewerService }, { type: LayerService }, { type: BaseUserService }, { type: PlanService }] });
|
|
12842
13142
|
|
|
12843
13143
|
/* eslint-disable class-methods-use-this */
|
|
12844
13144
|
class Object3DService {
|
|
@@ -13413,5 +13713,5 @@ function floatValidator() {
|
|
|
13413
13713
|
* Generated bundle index. Do not edit.
|
|
13414
13714
|
*/
|
|
13415
13715
|
|
|
13416
|
-
export { AffectationService, AvatarComponent, BaseLateralTabService, BaseTagService, BaseUserService, BaseVisibilityService, CameraMode, CaptureService, CaptureViewer, CommentService, CommentType, Config, ContentService, CsvExportComponent, DomainService, DomainType, DurationToStringPipe, EmailStatus, EquipmentService, EventService, EventStatus, EventType, FeatureService, FeatureType, FilterService, HashtagFromIdPipe, HashtagService, InterventionService, InventoryStatus, LayerService, LevelStatus, LoaderComponent, Locale, LocaleService, MatterportImportService, MatterportService, MattertagActionMode, MattertagData, MeasurementService, MenuBarComponent, MissionService, NavigationService, NavigatorService, NgxSmarterplanCoreModule, NgxSmarterplanCoreService, NodeService, Object3DService, OperationService, OrganisationService, PaymentStatus, PlanService, PoiService, PoiType, ProfileEntity, ProfileService, ProfileStatus, PropertyService, PropertyType, RoleStatus, SafeUrlPipe, SearchBarComponent, SearchObjectType, SearchService, SpModule, SpaceService, SpaceStatus, StatusEquipment, SupportModalComponent, SupportService, TagAction, TemplateService, TicketPriority, TicketStatus, TicketType, TicketsService, TimeDateToLocalStringPipe, TypeNote, UsernameFromIdPipe, ValidatorsService, ViewerInteractions, ViewerService, VisitService, ZoneChangeService, ZoneService, arraysContainSameElements, checkElementById, convertTimestampToLocalZone, dateHasExpired, dateTimeToLocalString, deleteFromS3, downloadBlob, downloadEquipmentDocument, downloadFile, downloadFileAsObject, durationToString, emailValidator, enumToArray, filterUniqueArrayByID, floatValidator, getBufferForFileFromS3, getCoefficientsForImage, getCurrentLang, getDistanceBetweenTwoPoints, getHighestLevelForMissions, getHighestRoleForMissions, getLevelsBelow, getLocaleLong, getLocaleShort, getMetaForImage, getRolesBelowForManager, getSignedFile, getSignedImageUrlForEquipment, getSignedImageUrlForProfile, getSignedImageUrlForSpace, getSpaceIDFromUrl, getVisitUrl, isEmptyObject, listFilesInFolder, mean, noEmptyValidator, numberToDateString, openDocument, openModalForVisitSwitch, poiTypeToString, pointToString, removeAllFilesFromFolderS3, removeNullKeysFromObject, showScanPointsOnPlanInDiv, shuffleArray, sortAlphabeticallyOnName, stringLocaleToEnum, stringToLowercaseNoSpaces, styleButton, textValidator, translateDatePeriod, uploadBase64Image, uploadBase64ImageWithRetry, uploadFileToS3, uploadJsonToS3, validEmail, wait, waitUntil };
|
|
13716
|
+
export { AffectationService, AvatarComponent, BaseLateralTabService, BaseTagService, BaseUserService, BaseVisibilityService, CameraMode, CaptureService, CaptureViewer, CommentService, CommentType, Config, ContentService, CsvExportComponent, DomainService, DomainType, DurationToStringPipe, EmailStatus, EquipmentService, EventService, EventStatus, EventType, FeatureService, FeatureType, FilterService, HashtagFromIdPipe, HashtagService, InterventionService, InventoryStatus, LayerService, LevelStatus, LoaderComponent, Locale, LocaleService, MATTERPORT_SDK_KEY, MatterportImportService, MatterportService, MattertagActionMode, MattertagData, MeasurementService, MenuBarComponent, MissionService, NavigationService, NavigatorService, NgxSmarterplanCoreModule, NgxSmarterplanCoreService, NodeService, Object3DService, OperationService, OrganisationService, PaymentStatus, PlanService, PoiService, PoiType, ProfileEntity, ProfileService, ProfileStatus, PropertyService, PropertyType, RoleStatus, SafeUrlPipe, SearchBarComponent, SearchObjectType, SearchService, SpModule, SpaceService, SpaceStatus, StatusEquipment, SupportModalComponent, SupportService, TagAction, TemplateService, TicketPriority, TicketStatus, TicketType, TicketsService, TimeDateToLocalStringPipe, TypeNote, UsernameFromIdPipe, ValidatorsService, ViewerInteractions, ViewerService, VisitService, ZoneChangeService, ZoneService, arraysContainSameElements, checkElementById, convertTimestampToLocalZone, dateHasExpired, dateTimeToLocalString, deleteFromS3, downloadBlob, downloadEquipmentDocument, downloadFile, downloadFileAsObject, durationToString, emailValidator, enumToArray, filterUniqueArrayByID, floatValidator, getBufferForFileFromS3, getCoefficientsForImage, getCurrentLang, getDistanceBetweenTwoPoints, getHighestLevelForMissions, getHighestRoleForMissions, getLevelsBelow, getLocaleLong, getLocaleShort, getMetaForImage, getRolesBelowForManager, getSignedFile, getSignedImageUrlForEquipment, getSignedImageUrlForProfile, getSignedImageUrlForSpace, getSpaceIDFromUrl, getVisitUrl, isEmptyObject, listFilesInFolder, mean, noEmptyValidator, numberToDateString, openDocument, openModalForVisitSwitch, poiTypeToString, pointToString, removeAllFilesFromFolderS3, removeNullKeysFromObject, showScanPointsOnPlanInDiv, shuffleArray, sortAlphabeticallyOnName, stringLocaleToEnum, stringToLowercaseNoSpaces, styleButton, textValidator, translateDatePeriod, uploadBase64Image, uploadBase64ImageWithRetry, uploadFileToS3, uploadJsonToS3, validEmail, wait, waitUntil };
|
|
13417
13717
|
//# sourceMappingURL=smarterplan-ngx-smarterplan-core.mjs.map
|