@smarterplan/ngx-smarterplan-core 1.4.14 → 1.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/pipes/hashtag-from-id.pipe.mjs +1 -1
- package/esm2022/lib/services/matterport-tag-copy.service.mjs +448 -62
- package/esm2022/lib/services/models/domain.service.mjs +20 -1
- package/esm2022/lib/services/models/equipment.service.mjs +4 -2
- package/esm2022/lib/services/models/feature.service.mjs +1 -7
- package/esm2022/lib/services/models/mission.service.mjs +17 -1
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +555 -141
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/services/matterport-tag-copy.service.d.ts +137 -17
- package/lib/services/models/domain.service.d.ts +8 -0
- package/lib/services/models/feature.service.d.ts +0 -6
- package/lib/services/models/mission.service.d.ts +5 -0
- package/package.json +1 -1
|
@@ -9,7 +9,9 @@ import { FeatureService } from './models/feature.service';
|
|
|
9
9
|
import { MeasurementService } from './models/measurement.service';
|
|
10
10
|
import { CommentService } from './models/comment.service';
|
|
11
11
|
import { HashtagService } from './models/hashtag.service';
|
|
12
|
-
import {
|
|
12
|
+
import { MissionService } from './models/mission.service';
|
|
13
|
+
import { OperationService } from './models/operation.service';
|
|
14
|
+
import { DomainService } from './models/domain.service';
|
|
13
15
|
import { BaseUserService } from './user.service';
|
|
14
16
|
import { Vec3 } from './utils/matterport-transform.util';
|
|
15
17
|
import * as i0 from "@angular/core";
|
|
@@ -22,11 +24,16 @@ export interface CopyProgress {
|
|
|
22
24
|
totalOverall: number;
|
|
23
25
|
percent: number;
|
|
24
26
|
errorCount: number;
|
|
27
|
+
/** Items that already existed in the target space and had missing identity fields
|
|
28
|
+
* filled in, rather than being newly created — see healEquipmentIdentity() and its
|
|
29
|
+
* ticket/feature equivalents. */
|
|
30
|
+
healedCount: number;
|
|
25
31
|
}
|
|
26
|
-
/** A single line in the copy log —
|
|
32
|
+
/** A single line in the copy log — a step status (updated in place), or an error / healed
|
|
33
|
+
* item notice (appended once, permanent). */
|
|
27
34
|
export interface CopyLogEntry {
|
|
28
35
|
id: string;
|
|
29
|
-
type: 'step' | 'error';
|
|
36
|
+
type: 'step' | 'error' | 'healed';
|
|
30
37
|
text: string;
|
|
31
38
|
}
|
|
32
39
|
export declare class MatterportTagCopyService {
|
|
@@ -40,13 +47,16 @@ export declare class MatterportTagCopyService {
|
|
|
40
47
|
private measurementService;
|
|
41
48
|
private commentService;
|
|
42
49
|
private hashtagService;
|
|
43
|
-
private
|
|
50
|
+
private missionService;
|
|
51
|
+
private operationService;
|
|
52
|
+
private domainService;
|
|
44
53
|
private translate;
|
|
45
54
|
copyProgress$: BehaviorSubject<CopyProgress | null>;
|
|
46
55
|
copyLog$: BehaviorSubject<CopyLogEntry[]>;
|
|
47
56
|
private spModule;
|
|
48
57
|
private log;
|
|
49
|
-
|
|
58
|
+
/** Unique-id sequence shared by every permanent (non-step) log line — errors and healed-item notices alike. */
|
|
59
|
+
private logSeq;
|
|
50
60
|
/** source element id -> id of its copy in the target space. */
|
|
51
61
|
private elementIds;
|
|
52
62
|
/** source Comment id -> id of its copy. Needed to remap POI.tagImageID, which is a
|
|
@@ -64,17 +74,39 @@ export declare class MatterportTagCopyService {
|
|
|
64
74
|
/** source ids of the elements whose POIs were already created by an element phase.
|
|
65
75
|
* Guards the standalone POI phase against creating a second, impoverished copy. */
|
|
66
76
|
private handledElementIds;
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
/** source Mission id -> its userID. */
|
|
78
|
+
private sourceMissionUserIds;
|
|
79
|
+
/** userID -> that user's Mission id in the TARGET space (only set when they have one). */
|
|
80
|
+
private targetMissionIdsByUserId;
|
|
81
|
+
/** id -> Domain, for every domain visible from EITHER space's operator mission (its
|
|
82
|
+
* organisationID, its orderedOrganisationID, or generic/no-organisation domains) — a
|
|
83
|
+
* superset covering whatever a source object's domainID could point at. */
|
|
84
|
+
private domainsById;
|
|
85
|
+
/** organisationIDs the TARGET operator's mission can see domains from. A domain whose
|
|
86
|
+
* own organisationID is in this set (or has none at all) is already directly
|
|
87
|
+
* selectable in the target space's own dropdown, so its id is reused unchanged. */
|
|
88
|
+
private targetVisibleDomainOrgIds;
|
|
89
|
+
/** `${type}::${normalised name}` -> that domain's id, among domains visible to the
|
|
90
|
+
* TARGET operator — used to find an equivalent when the exact id isn't reusable. */
|
|
91
|
+
private targetDomainIdsByTypeAndName;
|
|
70
92
|
/** Target space id of the run in progress — used to re-home copied tag icons. */
|
|
71
93
|
private targetSpaceId;
|
|
72
|
-
constructor(navigationService: NavigationService, userService: BaseUserService, poiService: PoiService, ticketService: TicketsService, equipmentService: EquipmentService, object3DService: Object3DService, featureService: FeatureService, measurementService: MeasurementService, commentService: CommentService, hashtagService: HashtagService,
|
|
94
|
+
constructor(navigationService: NavigationService, userService: BaseUserService, poiService: PoiService, ticketService: TicketsService, equipmentService: EquipmentService, object3DService: Object3DService, featureService: FeatureService, measurementService: MeasurementService, commentService: CommentService, hashtagService: HashtagService, missionService: MissionService, operationService: OperationService, domainService: DomainService, translate: TranslateService);
|
|
73
95
|
copyTagsFromVisit(sourceSpaceId: string, targetSpaceId: string, landmarkSourceA: Vec3, landmarkTargetA: Vec3, landmarkSourceB: Vec3, landmarkTargetB: Vec3): Promise<boolean>;
|
|
96
|
+
/**
|
|
97
|
+
* Serialises the current copy log (step lines as last emitted, plus every error and
|
|
98
|
+
* healed-item notice) to a plain-text file and triggers a browser download — wired to a
|
|
99
|
+
* "download log" button in the copy UI, so an operator can keep or share the full report
|
|
100
|
+
* of a run rather than only the ~200px scrollable panel showing it.
|
|
101
|
+
*/
|
|
102
|
+
downloadLog(filename?: string): void;
|
|
74
103
|
/** Adds or updates a step line (identified by stepId) with new text, then republishes the log. */
|
|
75
104
|
private setStepLog;
|
|
76
105
|
/** Appends a new, permanent log line (never overwritten), then republishes the log. */
|
|
77
106
|
private appendErrorLog;
|
|
107
|
+
/** Appends a permanent log line for an item that was repaired rather than newly
|
|
108
|
+
* created — see healEquipmentIdentity() and its ticket/feature equivalents. */
|
|
109
|
+
private appendHealedLog;
|
|
78
110
|
/** Resets the log for a new run. */
|
|
79
111
|
private resetLog;
|
|
80
112
|
/** Clears every id map carried over from a previous run. The service is a root-level
|
|
@@ -85,6 +117,10 @@ export declare class MatterportTagCopyService {
|
|
|
85
117
|
private setStepProgress;
|
|
86
118
|
/** Logs a translated, parameterized error line for a single failed item. */
|
|
87
119
|
private logItemError;
|
|
120
|
+
/** Logs a translated line for an item that already existed in the target space and had
|
|
121
|
+
* its missing identity fields filled in, so the operator can tell it apart from a
|
|
122
|
+
* freshly created item in the copy report. */
|
|
123
|
+
private logHealedItem;
|
|
88
124
|
/** Logs an item-level error, using a specific "missing file / orphaned reference"
|
|
89
125
|
* translation key when the cause is a MissingS3FileError, and the generic per-type
|
|
90
126
|
* key otherwise. Keeps the copy log readable: a missing file is not a bug to
|
|
@@ -100,14 +136,38 @@ export declare class MatterportTagCopyService {
|
|
|
100
136
|
* of fail outright.
|
|
101
137
|
*/
|
|
102
138
|
private isArchivedForOperator;
|
|
139
|
+
/** Normalised lookup key for a domain: type disambiguates same-named domains used for
|
|
140
|
+
* different purposes (equipment vs. ticket vs. feature categories, ...). */
|
|
141
|
+
private domainKey;
|
|
142
|
+
/**
|
|
143
|
+
* READ-ONLY indexing of every domain either operator's Mission can see. Creates
|
|
144
|
+
* nothing — unlike hashtags, a domain is a business taxonomy entry an operator manages
|
|
145
|
+
* deliberately; this tool only ever reuses an EXISTING equivalent, it never invents one.
|
|
146
|
+
*
|
|
147
|
+
* Visibility is keyed to `currentMission(spaceId).organisationID` /
|
|
148
|
+
* `.orderedOrganisationID` for EACH space — exactly what
|
|
149
|
+
* `DomainService.getDomainsForOrgForType()` uses to populate the category dropdown on
|
|
150
|
+
* the equipment/ticket/feature edit forms (see form-equipment.component.ts,
|
|
151
|
+
* batch-edit-equipment.component.ts, form-feature.component.ts). Comparing the spaces'
|
|
152
|
+
* OWN `organisationID` instead — the previous approach — missed every domain reachable
|
|
153
|
+
* only through the operator's `orderedOrganisationID` (set when a mission is created "on
|
|
154
|
+
* behalf of" another organisation — see form-mission.component.ts), which is exactly how
|
|
155
|
+
* a domain ends up visible on two spaces that belong to different organisations.
|
|
156
|
+
*/
|
|
157
|
+
private loadDomainIndex;
|
|
103
158
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
159
|
+
* Resolves a source domainID (equipment/ticket/feature/POI category) for use in the
|
|
160
|
+
* target space.
|
|
161
|
+
*
|
|
162
|
+
* - generic domain (no organisationID of its own — a shared taxonomy entry, e.g. a
|
|
163
|
+
* standard category created by the platform): reused unchanged, valid everywhere.
|
|
164
|
+
* - the domain's own organisationID is already one the TARGET operator's mission can
|
|
165
|
+
* see (its organisationID, or its orderedOrganisationID): reused unchanged too — the
|
|
166
|
+
* id is directly selectable in the target space's own dropdown as-is.
|
|
167
|
+
* - otherwise: matched by (type, name) against the domains visible to the TARGET
|
|
168
|
+
* operator (loadDomainIndex()); dropped when no equivalent exists there.
|
|
109
169
|
*/
|
|
110
|
-
private
|
|
170
|
+
private resolveDomainID;
|
|
111
171
|
/** Normalised lookup key for a hashtag name, so "Moyen Âge" and "moyen âge " match. */
|
|
112
172
|
private hashtagKey;
|
|
113
173
|
/**
|
|
@@ -136,6 +196,29 @@ export declare class MatterportTagCopyService {
|
|
|
136
196
|
* dangling id.
|
|
137
197
|
*/
|
|
138
198
|
private resolveHashtagIds;
|
|
199
|
+
/**
|
|
200
|
+
* READ-ONLY indexing of both spaces' missions.
|
|
201
|
+
*
|
|
202
|
+
* A Mission is scoped to one space (it pairs a userID with a spaceID), so the id a
|
|
203
|
+
* source comment's `ownerID` points at never designates anyone in the target space.
|
|
204
|
+
* This builds the two lookup tables resolveCommentOwnerID() needs to translate it:
|
|
205
|
+
* which user a source Mission id belongs to, and which Mission (if any) that same
|
|
206
|
+
* user already holds in the target space.
|
|
207
|
+
*/
|
|
208
|
+
private loadMissionIndex;
|
|
209
|
+
/**
|
|
210
|
+
* Translates a source comment's `ownerID` (a per-space Mission id) into the Mission of
|
|
211
|
+
* the SAME user in the target space, so the copy keeps crediting its real author.
|
|
212
|
+
*
|
|
213
|
+
* Substituting the current operator's mission — the way `ownerMissionID` legitimately
|
|
214
|
+
* does for tickets/equipment/features, which really do change owner on a copy — would
|
|
215
|
+
* misattribute every comment to whoever ran the copy instead of who actually wrote it.
|
|
216
|
+
*
|
|
217
|
+
* When the original author has no mission in the target space (never granted access
|
|
218
|
+
* there), the comment is left with no owner rather than a wrong one: an absent author
|
|
219
|
+
* is honest, a misattributed one is not.
|
|
220
|
+
*/
|
|
221
|
+
private resolveCommentOwnerID;
|
|
139
222
|
/** Records that these hashtags are now referenced by a feature that really exists, so
|
|
140
223
|
* the end-of-run cleanup leaves them alone. */
|
|
141
224
|
private markHashtagsUsed;
|
|
@@ -222,7 +305,9 @@ export declare class MatterportTagCopyService {
|
|
|
222
305
|
private resolveTagImageID;
|
|
223
306
|
/**
|
|
224
307
|
* Heuristic duplicate-detection: compares several identifying fields together rather than
|
|
225
|
-
* a single label, to reduce false positives when items share one of them.
|
|
308
|
+
* a single label, to reduce false positives when items share one of them. Returns the
|
|
309
|
+
* matched target item (or undefined) rather than a boolean, so the caller can act on the
|
|
310
|
+
* existing record — heal its missing fields — instead of only skipping it.
|
|
226
311
|
*
|
|
227
312
|
* The fields are supplied by the caller because the models do not agree on them. The
|
|
228
313
|
* previous version hard-coded `title`/`description`, which do not exist on Equipment at
|
|
@@ -230,7 +315,42 @@ export declare class MatterportTagCopyService {
|
|
|
230
315
|
* and a target space holding a single equipment silently caused the whole equipment phase
|
|
231
316
|
* to copy nothing.
|
|
232
317
|
*/
|
|
233
|
-
private
|
|
318
|
+
private findExisting;
|
|
319
|
+
/**
|
|
320
|
+
* Builds a patch of whichever fields in `fields` the existing target record is missing
|
|
321
|
+
* (`null`/`undefined`/empty array) but the source has, plus `domainID` when requested —
|
|
322
|
+
* domains are organisation-scoped everywhere in this file, so that one is only ever
|
|
323
|
+
* healed across the SAME organisation, exactly like at creation time.
|
|
324
|
+
*
|
|
325
|
+
* Never overwrites a field the target already carries a value for: a value entered by
|
|
326
|
+
* hand in the target space since an earlier, incomplete copy must not be clobbered by
|
|
327
|
+
* an older or different source value.
|
|
328
|
+
*
|
|
329
|
+
* Returns both the patch to send and the list of healed field names, so the caller can
|
|
330
|
+
* both perform the update and describe it in the copy log.
|
|
331
|
+
*/
|
|
332
|
+
private buildHealPatch;
|
|
333
|
+
/**
|
|
334
|
+
* Fills in whichever identity field a PRE-EXISTING target equipment is missing but the
|
|
335
|
+
* source has — see the call site in the EQUIPMENTS phase for why re-running the copy
|
|
336
|
+
* has to be able to repair a previously-copied equipment, not just skip it again.
|
|
337
|
+
*
|
|
338
|
+
* A failed update is left to bubble up to the caller's existing per-item try/catch, the
|
|
339
|
+
* same as a failed creation — it gets the same visible error line, rather than a silent
|
|
340
|
+
* console warning.
|
|
341
|
+
*
|
|
342
|
+
* Returns the list of fields that were actually healed (empty if nothing was missing).
|
|
343
|
+
*/
|
|
344
|
+
private healEquipmentIdentity;
|
|
345
|
+
/**
|
|
346
|
+
* Same idea as healEquipmentIdentity(), for a pre-existing ticket. `title`/`description`
|
|
347
|
+
* are the pair findExisting() matched on to find this ticket in the first place, so they
|
|
348
|
+
* are never part of the heal — by construction, they already agree with the source.
|
|
349
|
+
*/
|
|
350
|
+
private healTicketIdentity;
|
|
351
|
+
/** Same idea, for a pre-existing feature. Keywords, media and POIs are not healed here
|
|
352
|
+
* for the same reason notes/POIs are not healed on equipment — see healEquipmentIdentity(). */
|
|
353
|
+
private healFeatureIdentity;
|
|
234
354
|
/** Serialises the identifying fields unambiguously, so that ["a", "b"] and ["ab", ""]
|
|
235
355
|
* can never produce the same key. */
|
|
236
356
|
private identityKey;
|
|
@@ -4,6 +4,14 @@ export declare class DomainService {
|
|
|
4
4
|
API: any;
|
|
5
5
|
constructor(apiInjected: any);
|
|
6
6
|
getGenericDomainsAndForOrganisation(organisationID: string): Promise<any | void>;
|
|
7
|
+
/**
|
|
8
|
+
* Same as getGenericDomainsAndForOrganisation(), but drains every page instead of only
|
|
9
|
+
* the first. `ListDomains` has no per-organisation index — every call already scans the
|
|
10
|
+
* WHOLE table across every organisation before filtering client-side — so a catalogue
|
|
11
|
+
* past the first page was silently invisible to callers that need the complete list
|
|
12
|
+
* (e.g. matching an organisation-specific domain by name across a space-to-space copy).
|
|
13
|
+
*/
|
|
14
|
+
getAllGenericDomainsAndForOrganisation(organisationID: string): Promise<Domain[]>;
|
|
7
15
|
getGenericDomainsAndForOrgAndOrderedOrg(orgID: string, orderedOrgID?: string): Promise<Domain[]>;
|
|
8
16
|
getDomainsForOrgExcludingTypes(types: DomainType[], organisationID: string): Promise<Domain[]>;
|
|
9
17
|
getDomain(id: string): Promise<Domain>;
|
|
@@ -51,12 +51,6 @@ export declare class FeatureService extends BaseObjectService {
|
|
|
51
51
|
/**
|
|
52
52
|
* Returns EVERY feature of a space, following `nextToken` until the index is
|
|
53
53
|
* exhausted, with no user/archive filtering at all.
|
|
54
|
-
*
|
|
55
|
-
* `getFeaturesBySpaceWithoutFiltering()` reads a single page (the AppSync default
|
|
56
|
-
* caps it at 100 items) and calls `isArchived()`, which dereferences the current
|
|
57
|
-
* user's mission ON THAT SPACE — so it both truncates large spaces and throws for a
|
|
58
|
-
* space the operator has no mission on. Duplication has to see the raw, complete
|
|
59
|
-
* list, hence this separate accessor rather than a change of the existing one.
|
|
60
54
|
*/
|
|
61
55
|
getAllFeaturesBySpaceRaw(spaceID: string): Promise<Feature[]>;
|
|
62
56
|
isBookingPlace(feature: Feature): void;
|
|
@@ -21,6 +21,11 @@ export declare class MissionService {
|
|
|
21
21
|
getActivatedMissions(missions: Mission[]): Mission[];
|
|
22
22
|
getMissionsForZone(zoneID: string): Promise<Mission[]>;
|
|
23
23
|
getMissionsForSpace(spaceID: string): Promise<Mission[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Same as getMissionsForSpace(), but follows `nextToken` until the connection is
|
|
26
|
+
* exhausted instead of returning only the first page.
|
|
27
|
+
*/
|
|
28
|
+
getAllMissionsForSpace(spaceID: string): Promise<Mission[]>;
|
|
24
29
|
activateMission(mis: Mission): void;
|
|
25
30
|
getMissionsByTemplate(templateID: string): Promise<Mission[]>;
|
|
26
31
|
getMission(missionID: string): Promise<Mission>;
|