@collabdt/core 0.3.2 → 0.3.3
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/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/Comment.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +5 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.js +37 -9
- package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +1 -2
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +66 -94
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.d.ts +16 -3
- package/dist/core/components/ui/Sensors/Sensor.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.js +76 -37
- package/dist/core/components/ui/Sensors/Sensor.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.d.ts +12 -2
- package/dist/core/components/ui/Sensors/SensorChart.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.js +49 -12
- package/dist/core/components/ui/Sensors/SensorChart.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts +9 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js +128 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js.map +1 -0
- package/dist/core/components/ui/Sensors/SensorInput.d.ts +6 -1
- package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorInput.js +94 -8
- package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts +3 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js +4 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts +1 -3
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js +33 -8
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts +7 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js +56 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts +42 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.js +118 -0
- package/dist/core/components/ui/Sensors/sensorData.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts +24 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.js +34 -0
- package/dist/core/components/ui/Sensors/sensorRange.js.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts +15 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js +63 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js.map +1 -0
- package/dist/core/components/viewers/Viewer.js +1 -1
- package/dist/core/components/viewers/Viewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +1 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +25 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +1 -22
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +2 -105
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts +8 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +15 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +2 -23
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +2 -24
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts +33 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js +90 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +26 -230
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +39 -11
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts +1 -2
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +2 -2
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +1 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +74 -39
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts +19 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js +108 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts +24 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js +27 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts +66 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.js +1 -0
- package/dist/core/components/viewers/shared/markers/types.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts +22 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js +233 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js.map +1 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -1
- package/dist/core/i18n/messages/en.json +5 -1
- package/dist/core/i18n/messages/es.json +5 -1
- package/dist/core/i18n/messages/fr.json +5 -1
- package/dist/core/store/AppConfig/context.d.ts.map +1 -1
- package/dist/core/store/AppConfig/context.js +4 -1
- package/dist/core/store/AppConfig/context.js.map +1 -1
- package/dist/core/store/AppConfig/reducer.d.ts +10 -0
- package/dist/core/store/AppConfig/reducer.d.ts.map +1 -1
- package/dist/core/store/AppConfig/reducer.js +10 -0
- package/dist/core/store/AppConfig/reducer.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js +5 -2
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Menus/reducer.d.ts +45 -1
- package/dist/core/store/Menus/reducer.d.ts.map +1 -1
- package/dist/core/store/Menus/reducer.js +21 -3
- package/dist/core/store/Menus/reducer.js.map +1 -1
- package/dist/core/utils/timeUtils.d.ts +24 -1
- package/dist/core/utils/timeUtils.d.ts.map +1 -1
- package/dist/core/utils/timeUtils.js +52 -3
- package/dist/core/utils/timeUtils.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BimSensor.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,UAAU,WAAW;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,gBAAgB,CAAA;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,WAAW,EAAE,KAAK,CAAC,MAAM,CAAA;IACzB,WAAW,EAAE,KAAK,CAAC,OAAO,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,IAAI,CAAA;IACf,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"BimSensor.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAC;AAC9F,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,UAAU,WAAW;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,gBAAgB,CAAA;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,WAAW,EAAE,KAAK,CAAC,MAAM,CAAA;IACzB,WAAW,EAAE,KAAK,CAAC,OAAO,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,IAAI,CAAA;IACf,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,mBAAmB,CAAA;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,UAAU,EACV,UAAU,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,eAAe,EACf,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,SAAiB,EACjB,QAAQ,EACR,WAAmB,EACnB,OAAc,EACd,SAAgB,EAChB,YAAY,GACb,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CA+BlC"}
|
|
@@ -11,11 +11,16 @@ function BimSensor({
|
|
|
11
11
|
updateFrequency,
|
|
12
12
|
onRemove,
|
|
13
13
|
onEdit,
|
|
14
|
+
onExpand,
|
|
14
15
|
onClose,
|
|
15
16
|
buildingId,
|
|
16
17
|
timestamp,
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
highlight = false,
|
|
19
|
+
timeZone,
|
|
20
|
+
showActions = false,
|
|
21
|
+
canEdit = true,
|
|
22
|
+
canDelete = true,
|
|
23
|
+
actionLabels
|
|
19
24
|
}) {
|
|
20
25
|
return /* @__PURE__ */ jsx(
|
|
21
26
|
"div",
|
|
@@ -34,11 +39,18 @@ function BimSensor({
|
|
|
34
39
|
updateFrequency,
|
|
35
40
|
createdAt: timestamp,
|
|
36
41
|
onRemove,
|
|
42
|
+
onEdit,
|
|
43
|
+
onExpand,
|
|
37
44
|
onClose,
|
|
45
|
+
showActions,
|
|
46
|
+
canEdit,
|
|
47
|
+
canDelete,
|
|
48
|
+
actionLabels,
|
|
38
49
|
enableCollapse: true,
|
|
39
50
|
defaultCollapsed: true,
|
|
40
51
|
size: "sm",
|
|
41
|
-
highlight
|
|
52
|
+
highlight,
|
|
53
|
+
timeZone
|
|
42
54
|
}
|
|
43
55
|
)
|
|
44
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\n\r\nimport Sensor from '../../../../../../ui/Sensors/Sensor'\r\n\r\nimport { markerStyle, markerStyleHighlight } from './markerUtils'\r\n\r\nimport type { SensorDataFormat, SensorType } from '../../../../../../../types/dbTypes';\r\nimport type * as THREE from 'three'\r\n\r\ninterface SensorProps {\r\n sensorName: string\r\n sensorType: SensorType\r\n dataUrl: string\r\n dataFormat: SensorDataFormat\r\n updateFrequency: number\r\n tags?: string[]\r\n worldCamera: THREE.Camera\r\n targetPoint: THREE.Vector3\r\n onRemove?: () => void\r\n onEdit?: () => void\r\n onClose: () => void\r\n buildingId?: number\r\n timestamp: Date\r\n sphere: THREE.Object3D\r\n highlight?: boolean\r\n}\r\n\r\nexport default function BimSensor({\r\n sensorName,\r\n sensorType,\r\n tags,\r\n dataUrl,\r\n dataFormat,\r\n updateFrequency,\r\n onRemove,\r\n onEdit,\r\n onClose,\r\n buildingId,\r\n timestamp,\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\n\r\nimport Sensor from '../../../../../../ui/Sensors/Sensor'\r\n\r\nimport { markerStyle, markerStyleHighlight } from './markerUtils'\r\n\r\nimport type { SensorDataFormat, SensorType } from '../../../../../../../types/dbTypes';\r\nimport type { CommentActionLabels } from '../../../../../../ui/Comments/CommentActionButtons';\r\nimport type * as THREE from 'three'\r\n\r\ninterface SensorProps {\r\n sensorName: string\r\n sensorType: SensorType\r\n dataUrl: string\r\n dataFormat: SensorDataFormat\r\n updateFrequency: number\r\n tags?: string[]\r\n worldCamera: THREE.Camera\r\n targetPoint: THREE.Vector3\r\n onRemove?: () => void\r\n onEdit?: () => void\r\n onExpand?: () => void\r\n onClose: () => void\r\n buildingId?: number\r\n timestamp: Date\r\n sphere: THREE.Object3D\r\n highlight?: boolean\r\n timeZone?: string\r\n showActions?: boolean\r\n canEdit?: boolean\r\n canDelete?: boolean\r\n actionLabels?: CommentActionLabels\r\n}\r\n\r\nexport default function BimSensor({\r\n sensorName,\r\n sensorType,\r\n tags,\r\n dataUrl,\r\n dataFormat,\r\n updateFrequency,\r\n onRemove,\r\n onEdit,\r\n onExpand,\r\n onClose,\r\n buildingId,\r\n timestamp,\r\n highlight = false,\r\n timeZone,\r\n showActions = false,\r\n canEdit = true,\r\n canDelete = true,\r\n actionLabels,\r\n}: SensorProps): React.ReactElement {\r\n return (\r\n <div\r\n className={highlight ? markerStyleHighlight : markerStyle}\r\n >\r\n <Sensor\r\n buildingId={buildingId}\r\n sensorName={sensorName}\r\n sensorType={sensorType}\r\n tags={tags}\r\n tagsVariant=\"read-only\"\r\n dataUrl={dataUrl}\r\n dataFormat={dataFormat}\r\n updateFrequency={updateFrequency}\r\n createdAt={timestamp}\r\n onRemove={onRemove}\r\n onEdit={onEdit}\r\n onExpand={onExpand}\r\n onClose={onClose}\r\n showActions={showActions}\r\n canEdit={canEdit}\r\n canDelete={canDelete}\r\n actionLabels={actionLabels}\r\n enableCollapse\r\n defaultCollapsed\r\n size=\"sm\"\r\n highlight={highlight}\r\n timeZone={timeZone}\r\n />\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AA+DM;AAxDN,OAAO,YAAY;AAEnB,SAAS,aAAa,4BAA4B;AA8BnC,SAAR,UAA2B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,cAAc;AAAA,EACd,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AACF,GAAoC;AAClC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,YAAY,uBAAuB;AAAA,MAE9C;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAY;AAAA,UACZ;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAc;AAAA,UACd,kBAAgB;AAAA,UAChB,MAAK;AAAA,UACL;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2025 Collab Digital Twins\n\nimport * as THREE from 'three'\n\n/**\n * Screen-space clustering for 3D (BIM) comment markers.\n *\n * The BIM viewer renders each comment as an independent CSS2DObject at a world\n * position, so markers that are close together (or aligned along the camera\n * axis) overlap on screen. This groups markers whose projected screen positions\n * fall within `threshold` pixels of each other so the caller can draw a single\n * numbered cluster bubble instead of a pile of overlapping avatars.\n *\n * Pure and side-effect free (no scene mutation) so it can be unit tested.\n */\n\nexport interface HasWorldPosition {\n id: number\n x?: number | null\n y?: number | null\n z?: number | null\n}\n\nexport interface ScreenCluster<T> {\n /** Stable key derived from member ids (sorted) — used for registry diffing. */\n key: string\n screenX: number\n screenY: number\n worldCenter: { x: number; y: number; z: number }\n members: T[]\n}\n\nexport interface ClusterResult<T> {\n clusters: ScreenCluster<T>[]\n singles: T[]\n}\n\nexport interface ProjectedPoint {\n screenX: number\n screenY: number\n /** false when the point is behind the camera. */\n onScreen: boolean\n}\n\n/** Project a world point to pixel coordinates for the given camera/viewport. */\nexport function projectPoint(\n x: number,\n y: number,\n z: number,\n camera: THREE.Camera,\n width: number,\n height: number,\n): ProjectedPoint {\n const pos = new THREE.Vector3(x, y, z)\n // Camera-space z is positive when the point is behind the camera (it looks down -z).\n const cameraSpace = pos.clone().applyMatrix4(camera.matrixWorldInverse)\n const behind = cameraSpace.z >= 0\n\n const ndc = pos.project(camera)\n return {\n screenX: (ndc.x * 0.5 + 0.5) * width,\n screenY: (-ndc.y * 0.5 + 0.5) * height,\n onScreen: !behind,\n }\n}\n\nfunction average(values: number[]): number {\n if (values.length === 0) return 0\n return values.reduce((sum, v) => sum + v, 0) / values.length\n}\n\nexport function clusterMarkersByScreenSpace<T extends HasWorldPosition>(\n items: T[],\n camera: THREE.Camera,\n width: number,\n height: number,\n threshold = 44,\n): ClusterResult<T> {\n const projected = items\n .filter((it): it is T & { x: number; y: number; z: number } =>\n it.x != null && it.y != null && it.z != null,\n )\n .map((item) => ({ item, ...projectPoint(item.x, item.y, item.z, camera, width, height) }))\n\n const onScreen = projected.filter((p) => p.onScreen)\n const clusters: ScreenCluster<T>[] = []\n // Points behind the camera are never clustered; they fall through as singles.\n const singles: T[] = projected.filter((p) => !p.onScreen).map((p) => p.item)\n\n const used = new Array(onScreen.length).fill(false)\n\n for (let i = 0; i < onScreen.length; i++) {\n if (used[i]) continue\n used[i] = true\n const group = [onScreen[i]]\n\n for (let j = i + 1; j < onScreen.length; j++) {\n if (used[j]) continue\n const dx = onScreen[i].screenX - onScreen[j].screenX\n const dy = onScreen[i].screenY - onScreen[j].screenY\n if (Math.hypot(dx, dy) <= threshold) {\n used[j] = true\n group.push(onScreen[j])\n }\n }\n\n if (group.length === 1) {\n singles.push(group[0].item)\n continue\n }\n\n const members = group.map((g) => g.item)\n clusters.push({\n key: members.map((m) => m.id).sort((a, b) => a - b).join('-'),\n screenX: average(group.map((g) => g.screenX)),\n screenY: average(group.map((g) => g.screenY)),\n worldCenter: {\n x: average(members.map((m) => m.x as number)),\n y: average(members.map((m) => m.y as number)),\n z: average(members.map((m) => m.z as number)),\n },\n members,\n })\n }\n\n return { clusters, singles }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAGA,YAAY,WAAW;AA2ChB,SAAS,aACd,GACA,GACA,GACA,QACA,OACA,QACgB;AAChB,QAAM,MAAM,IAAI,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErC,QAAM,cAAc,IAAI,MAAM,EAAE,aAAa,OAAO,kBAAkB;AACtE,QAAM,SAAS,YAAY,KAAK;AAEhC,QAAM,MAAM,IAAI,QAAQ,MAAM;AAC9B,SAAO;AAAA,IACL,UAAU,IAAI,IAAI,MAAM,OAAO;AAAA,IAC/B,UAAU,CAAC,IAAI,IAAI,MAAM,OAAO;AAAA,IAChC,UAAU,CAAC;AAAA,EACb;AACF;AAEA,SAAS,QAAQ,QAA0B;AACzC,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO;AACxD;AAEO,SAAS,4BACd,OACA,QACA,OACA,QACA,YAAY,IACM;AAClB,QAAM,YAAY,MACf;AAAA,IAAO,CAAC,OACP,GAAG,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,KAAK;AAAA,EAC1C,EACC,IAAI,CAAC,SAAU,iBAAE,QAAS,aAAa,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,OAAO,MAAM,EAAI;AAE3F,QAAM,WAAW,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ;AACnD,QAAM,WAA+B,CAAC;AAEtC,QAAM,UAAe,UAAU,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAE3E,QAAM,OAAO,IAAI,MAAM,SAAS,MAAM,EAAE,KAAK,KAAK;AAElD,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,KAAK,CAAC,EAAG;AACb,SAAK,CAAC,IAAI;AACV,UAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;AAE1B,aAAS,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAI,KAAK,CAAC,EAAG;AACb,YAAM,KAAK,SAAS,CAAC,EAAE,UAAU,SAAS,CAAC,EAAE;AAC7C,YAAM,KAAK,SAAS,CAAC,EAAE,UAAU,SAAS,CAAC,EAAE;AAC7C,UAAI,KAAK,MAAM,IAAI,EAAE,KAAK,WAAW;AACnC,aAAK,CAAC,IAAI;AACV,cAAM,KAAK,SAAS,CAAC,CAAC;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,KAAK,MAAM,CAAC,EAAE,IAAI;AAC1B;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACvC,aAAS,KAAK;AAAA,MACZ,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG;AAAA,MAC5D,SAAS,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5C,SAAS,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5C,aAAa;AAAA,QACX,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,QAC5C,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,QAC5C,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,MAC9C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,UAAU,QAAQ;AAC7B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as THREE from 'three'\r\n\r\n/**\r\n * Screen-space clustering for 3D (BIM) comment markers.\r\n *\r\n * The BIM viewer renders each comment as an independent CSS2DObject at a world\r\n * position, so markers that are close together (or aligned along the camera\r\n * axis) overlap on screen. This groups markers whose projected screen positions\r\n * fall within `threshold` pixels of each other so the caller can draw a single\r\n * numbered cluster bubble instead of a pile of overlapping avatars.\r\n *\r\n * Pure and side-effect free (no scene mutation) so it can be unit tested.\r\n */\r\n\r\nexport interface HasWorldPosition {\r\n id: number\r\n x?: number | null\r\n y?: number | null\r\n z?: number | null\r\n}\r\n\r\nexport interface ScreenCluster<T> {\r\n /** Stable key derived from member ids (sorted) — used for registry diffing. */\r\n key: string\r\n screenX: number\r\n screenY: number\r\n worldCenter: { x: number; y: number; z: number }\r\n members: T[]\r\n}\r\n\r\nexport interface ClusterResult<T> {\r\n clusters: ScreenCluster<T>[]\r\n singles: T[]\r\n}\r\n\r\nexport interface ProjectedPoint {\r\n screenX: number\r\n screenY: number\r\n /** false when the point is behind the camera. */\r\n onScreen: boolean\r\n}\r\n\r\n/** Project a world point to pixel coordinates for the given camera/viewport. */\r\nexport function projectPoint(\r\n x: number,\r\n y: number,\r\n z: number,\r\n camera: THREE.Camera,\r\n width: number,\r\n height: number,\r\n): ProjectedPoint {\r\n const pos = new THREE.Vector3(x, y, z)\r\n // Camera-space z is positive when the point is behind the camera (it looks down -z).\r\n const cameraSpace = pos.clone().applyMatrix4(camera.matrixWorldInverse)\r\n const behind = cameraSpace.z >= 0\r\n\r\n const ndc = pos.project(camera)\r\n return {\r\n screenX: (ndc.x * 0.5 + 0.5) * width,\r\n screenY: (-ndc.y * 0.5 + 0.5) * height,\r\n onScreen: !behind,\r\n }\r\n}\r\n\r\nfunction average(values: number[]): number {\r\n if (values.length === 0) return 0\r\n return values.reduce((sum, v) => sum + v, 0) / values.length\r\n}\r\n\r\nexport function clusterMarkersByScreenSpace<T extends HasWorldPosition>(\r\n items: T[],\r\n camera: THREE.Camera,\r\n width: number,\r\n height: number,\r\n threshold = 44,\r\n): ClusterResult<T> {\r\n const projected = items\r\n .filter((it): it is T & { x: number; y: number; z: number } =>\r\n it.x != null && it.y != null && it.z != null,\r\n )\r\n .map((item) => ({ item, ...projectPoint(item.x, item.y, item.z, camera, width, height) }))\r\n\r\n const onScreen = projected.filter((p) => p.onScreen)\r\n const clusters: ScreenCluster<T>[] = []\r\n // Points behind the camera are never clustered; they fall through as singles.\r\n const singles: T[] = projected.filter((p) => !p.onScreen).map((p) => p.item)\r\n\r\n const used = new Array(onScreen.length).fill(false)\r\n\r\n for (let i = 0; i < onScreen.length; i++) {\r\n if (used[i]) continue\r\n used[i] = true\r\n const group = [onScreen[i]]\r\n\r\n for (let j = i + 1; j < onScreen.length; j++) {\r\n if (used[j]) continue\r\n const dx = onScreen[i].screenX - onScreen[j].screenX\r\n const dy = onScreen[i].screenY - onScreen[j].screenY\r\n if (Math.hypot(dx, dy) <= threshold) {\r\n used[j] = true\r\n group.push(onScreen[j])\r\n }\r\n }\r\n\r\n if (group.length === 1) {\r\n singles.push(group[0].item)\r\n continue\r\n }\r\n\r\n const members = group.map((g) => g.item)\r\n clusters.push({\r\n key: members.map((m) => m.id).sort((a, b) => a - b).join('-'),\r\n screenX: average(group.map((g) => g.screenX)),\r\n screenY: average(group.map((g) => g.screenY)),\r\n worldCenter: {\r\n x: average(members.map((m) => m.x as number)),\r\n y: average(members.map((m) => m.y as number)),\r\n z: average(members.map((m) => m.z as number)),\r\n },\r\n members,\r\n })\r\n }\r\n\r\n return { clusters, singles }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;AAGA,YAAY,WAAW;AA2ChB,SAAS,aACd,GACA,GACA,GACA,QACA,OACA,QACgB;AAChB,QAAM,MAAM,IAAI,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErC,QAAM,cAAc,IAAI,MAAM,EAAE,aAAa,OAAO,kBAAkB;AACtE,QAAM,SAAS,YAAY,KAAK;AAEhC,QAAM,MAAM,IAAI,QAAQ,MAAM;AAC9B,SAAO;AAAA,IACL,UAAU,IAAI,IAAI,MAAM,OAAO;AAAA,IAC/B,UAAU,CAAC,IAAI,IAAI,MAAM,OAAO;AAAA,IAChC,UAAU,CAAC;AAAA,EACb;AACF;AAEA,SAAS,QAAQ,QAA0B;AACzC,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO;AACxD;AAEO,SAAS,4BACd,OACA,QACA,OACA,QACA,YAAY,IACM;AAClB,QAAM,YAAY,MACf;AAAA,IAAO,CAAC,OACP,GAAG,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,KAAK;AAAA,EAC1C,EACC,IAAI,CAAC,SAAU,iBAAE,QAAS,aAAa,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,OAAO,MAAM,EAAI;AAE3F,QAAM,WAAW,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ;AACnD,QAAM,WAA+B,CAAC;AAEtC,QAAM,UAAe,UAAU,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAE3E,QAAM,OAAO,IAAI,MAAM,SAAS,MAAM,EAAE,KAAK,KAAK;AAElD,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,KAAK,CAAC,EAAG;AACb,SAAK,CAAC,IAAI;AACV,UAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;AAE1B,aAAS,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAI,KAAK,CAAC,EAAG;AACb,YAAM,KAAK,SAAS,CAAC,EAAE,UAAU,SAAS,CAAC,EAAE;AAC7C,YAAM,KAAK,SAAS,CAAC,EAAE,UAAU,SAAS,CAAC,EAAE;AAC7C,UAAI,KAAK,MAAM,IAAI,EAAE,KAAK,WAAW;AACnC,aAAK,CAAC,IAAI;AACV,cAAM,KAAK,SAAS,CAAC,CAAC;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,KAAK,MAAM,CAAC,EAAE,IAAI;AAC1B;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACvC,aAAS,KAAK;AAAA,MACZ,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG;AAAA,MAC5D,SAAS,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5C,SAAS,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5C,aAAa;AAAA,QACX,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,QAC5C,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,QAC5C,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAW,CAAC;AAAA,MAC9C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,UAAU,QAAQ;AAC7B;","names":[]}
|
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
x: number;
|
|
4
|
-
y: number;
|
|
5
|
-
z: number;
|
|
6
|
-
}
|
|
7
|
-
/** Camera pose in the shape `camera-controls` `setLookAt` expects. */
|
|
8
|
-
export interface LookAt {
|
|
9
|
-
camX: number;
|
|
10
|
-
camY: number;
|
|
11
|
-
camZ: number;
|
|
12
|
-
tarX: number;
|
|
13
|
-
tarY: number;
|
|
14
|
-
tarZ: number;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Frame a comment without changing the current view direction: keep looking along
|
|
18
|
-
* the same axis the user already has, but re-target the comment and pull the camera
|
|
19
|
-
* to `distance` away from it. Used for double-click "zoom to comment".
|
|
20
|
-
*
|
|
21
|
-
* Pure and three.js-free so it can be unit tested with plain objects.
|
|
22
|
-
*/
|
|
23
|
-
export declare function computeCommentLookAt(camPos: Vec3, target: Vec3, commentPoint: Vec3, distance?: number): LookAt;
|
|
1
|
+
export type { Vec3, LookAt } from "../../../../../shared/markers/computeMarkerLookAt";
|
|
2
|
+
export { computeMarkerLookAt as computeCommentLookAt } from "../../../../../shared/markers/computeMarkerLookAt";
|
|
24
3
|
//# sourceMappingURL=commentCameraUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commentCameraUtils.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commentCameraUtils.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,mDAAmD,CAAA;AACrF,OAAO,EAAE,mBAAmB,IAAI,oBAAoB,EAAE,MAAM,mDAAmD,CAAA"}
|
|
@@ -1,27 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
function computeCommentLookAt(camPos, target, commentPoint, distance = 8) {
|
|
3
|
-
let dx = camPos.x - target.x;
|
|
4
|
-
let dy = camPos.y - target.y;
|
|
5
|
-
let dz = camPos.z - target.z;
|
|
6
|
-
let length = Math.hypot(dx, dy, dz);
|
|
7
|
-
if (length < 1e-6) {
|
|
8
|
-
dx = DEFAULT_DIRECTION.x;
|
|
9
|
-
dy = DEFAULT_DIRECTION.y;
|
|
10
|
-
dz = DEFAULT_DIRECTION.z;
|
|
11
|
-
length = Math.hypot(dx, dy, dz);
|
|
12
|
-
}
|
|
13
|
-
const safeDistance = distance > 0 ? distance : 8;
|
|
14
|
-
const scale = safeDistance / length;
|
|
15
|
-
return {
|
|
16
|
-
camX: commentPoint.x + dx * scale,
|
|
17
|
-
camY: commentPoint.y + dy * scale,
|
|
18
|
-
camZ: commentPoint.z + dz * scale,
|
|
19
|
-
tarX: commentPoint.x,
|
|
20
|
-
tarY: commentPoint.y,
|
|
21
|
-
tarZ: commentPoint.z
|
|
22
|
-
};
|
|
23
|
-
}
|
|
1
|
+
import { computeMarkerLookAt } from "../../../../../shared/markers/computeMarkerLookAt";
|
|
24
2
|
export {
|
|
25
|
-
computeCommentLookAt
|
|
3
|
+
computeMarkerLookAt as computeCommentLookAt
|
|
26
4
|
};
|
|
27
5
|
//# sourceMappingURL=commentCameraUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2025 Collab Digital Twins\
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Re-export shim: logic moved to the shared marker framework.\r\nexport type { Vec3, LookAt } from \"../../../../../shared/markers/computeMarkerLookAt\"\r\nexport { computeMarkerLookAt as computeCommentLookAt } from \"../../../../../shared/markers/computeMarkerLookAt\"\r\n"],"mappings":"AAKA,SAAgC,2BAA4B;","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BimMarkerConfig } from "../../../../../shared/markers/types";
|
|
2
|
+
/** A BIM comment enriched with author display fields, shaped for the marker layer. */
|
|
3
|
+
export interface CommentItem {
|
|
4
|
+
id: number;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
z: number;
|
|
8
|
+
/** Omitted on the pending (being-created) placeholder — never read before a comment is real. */
|
|
9
|
+
authorId?: number;
|
|
10
|
+
authorName: string;
|
|
11
|
+
imageFileId: number | null;
|
|
12
|
+
image: number | string | null;
|
|
13
|
+
text: string;
|
|
14
|
+
createdAt: string | Date;
|
|
15
|
+
buildingId?: number | null;
|
|
16
|
+
isPending?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface CommentMarkerDeps {
|
|
19
|
+
currentUserId: string | null;
|
|
20
|
+
onRemove: (id: number) => void;
|
|
21
|
+
/** Reply is comment-only — the generic marker `ctx` has no reply handler, so the wrapper injects it. */
|
|
22
|
+
onReply: (id: number) => void;
|
|
23
|
+
/** Building context closed over for the pending placeholder item. */
|
|
24
|
+
buildingId: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Builds the comment-specific `BimMarkerConfig` consumed by `useMarkerLayerBim`. A factory
|
|
28
|
+
* (not a plain object) because `isAuthor`, `onRemove`, `onReply` and the pending placeholder's
|
|
29
|
+
* `buildingId` all need runtime values supplied by the `useCommentMarkers` wrapper.
|
|
30
|
+
*/
|
|
31
|
+
export declare function makeCommentMarkerConfig(deps: CommentMarkerDeps): BimMarkerConfig<CommentItem>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=commentMarkerConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentMarkerConfig.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAE1E,sFAAsF;AACtF,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,UAAU,iBAAiB;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,wGAAwG;IACxG,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAAC,WAAW,CAAC,CAkE7F"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
import { BimMarkerCluster } from "../../../../../shared/markers/BimMarkerCluster";
|
|
21
|
+
import BimComment from "./BimComment";
|
|
22
|
+
function makeCommentMarkerConfig(deps) {
|
|
23
|
+
const { currentUserId, onRemove, onReply, buildingId } = deps;
|
|
24
|
+
return {
|
|
25
|
+
markerIdKey: "commentId",
|
|
26
|
+
sphereColor: "white",
|
|
27
|
+
focusDistance: 8,
|
|
28
|
+
component: BimComment,
|
|
29
|
+
clusterComponent: BimMarkerCluster,
|
|
30
|
+
// Exact reproduction of the pre-refactor `makeCommentPropsMapper`. Any user can select/focus/
|
|
31
|
+
// reply to any comment (showActions/onSelect/onFocus/onReply are NOT author-gated) — only
|
|
32
|
+
// canEdit/canDelete/onEdit/onRemove are, matching the original conditional structure.
|
|
33
|
+
propsMapper: (comment, ctx) => {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const base = {
|
|
36
|
+
userName: comment.authorName,
|
|
37
|
+
userImageFileId: (_a = comment.imageFileId) != null ? _a : null,
|
|
38
|
+
userImage: (_b = comment.imageFileId) != null ? _b : null,
|
|
39
|
+
buildingId: comment.buildingId,
|
|
40
|
+
timestamp: new Date(comment.createdAt),
|
|
41
|
+
text: comment.text,
|
|
42
|
+
isPending: comment.isPending || false,
|
|
43
|
+
highlight: ctx.highlight,
|
|
44
|
+
focused: ctx.focused
|
|
45
|
+
};
|
|
46
|
+
if (comment.isPending) return base;
|
|
47
|
+
return __spreadProps(__spreadValues({}, base), {
|
|
48
|
+
showActions: true,
|
|
49
|
+
canEdit: ctx.isAuthor,
|
|
50
|
+
canDelete: ctx.isAuthor,
|
|
51
|
+
onSelect: ctx.onSelect,
|
|
52
|
+
onFocus: ctx.onFocus,
|
|
53
|
+
onReply: () => onReply(comment.id),
|
|
54
|
+
onEdit: ctx.isAuthor ? ctx.onEdit : void 0,
|
|
55
|
+
onRemove: ctx.isAuthor ? ctx.onRemove : void 0
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
clusterMemberMapper: (c) => {
|
|
59
|
+
var _a;
|
|
60
|
+
return {
|
|
61
|
+
id: c.id,
|
|
62
|
+
userName: c.authorName,
|
|
63
|
+
imageFileId: (_a = c.imageFileId) != null ? _a : null
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
dataHashPart: (c) => {
|
|
67
|
+
var _a;
|
|
68
|
+
return `${c.id}:${(_a = c.text) != null ? _a : ""}:${c.isPending ? 1 : 0}`;
|
|
69
|
+
},
|
|
70
|
+
isAuthor: (c) => currentUserId != null && String(c.authorId) === currentUserId,
|
|
71
|
+
onRemove,
|
|
72
|
+
makePendingItem: (id, pos) => ({
|
|
73
|
+
id,
|
|
74
|
+
x: pos.x,
|
|
75
|
+
y: pos.y,
|
|
76
|
+
z: pos.z,
|
|
77
|
+
authorName: "Loading...",
|
|
78
|
+
imageFileId: null,
|
|
79
|
+
image: "",
|
|
80
|
+
text: "Creating comment...",
|
|
81
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
82
|
+
buildingId,
|
|
83
|
+
isPending: true
|
|
84
|
+
})
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export {
|
|
88
|
+
makeCommentMarkerConfig
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=commentMarkerConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport { BimMarkerCluster } from \"../../../../../shared/markers/BimMarkerCluster\"\r\n\r\nimport BimComment from \"./BimComment\"\r\n\r\nimport type { BimMarkerConfig } from \"../../../../../shared/markers/types\"\r\n\r\n/** A BIM comment enriched with author display fields, shaped for the marker layer. */\r\nexport interface CommentItem {\r\n id: number\r\n x: number\r\n y: number\r\n z: number\r\n /** Omitted on the pending (being-created) placeholder — never read before a comment is real. */\r\n authorId?: number\r\n authorName: string\r\n imageFileId: number | null\r\n image: number | string | null\r\n text: string\r\n createdAt: string | Date\r\n buildingId?: number | null\r\n isPending?: boolean\r\n}\r\n\r\ninterface CommentMarkerDeps {\r\n currentUserId: string | null\r\n onRemove: (id: number) => void\r\n /** Reply is comment-only — the generic marker `ctx` has no reply handler, so the wrapper injects it. */\r\n onReply: (id: number) => void\r\n /** Building context closed over for the pending placeholder item. */\r\n buildingId: number\r\n}\r\n\r\n/**\r\n * Builds the comment-specific `BimMarkerConfig` consumed by `useMarkerLayerBim`. A factory\r\n * (not a plain object) because `isAuthor`, `onRemove`, `onReply` and the pending placeholder's\r\n * `buildingId` all need runtime values supplied by the `useCommentMarkers` wrapper.\r\n */\r\nexport function makeCommentMarkerConfig(deps: CommentMarkerDeps): BimMarkerConfig<CommentItem> {\r\n const { currentUserId, onRemove, onReply, buildingId } = deps\r\n\r\n return {\r\n markerIdKey: \"commentId\",\r\n sphereColor: \"white\",\r\n focusDistance: 8,\r\n component: BimComment,\r\n clusterComponent: BimMarkerCluster,\r\n\r\n // Exact reproduction of the pre-refactor `makeCommentPropsMapper`. Any user can select/focus/\r\n // reply to any comment (showActions/onSelect/onFocus/onReply are NOT author-gated) — only\r\n // canEdit/canDelete/onEdit/onRemove are, matching the original conditional structure.\r\n propsMapper: (comment, ctx) => {\r\n const base = {\r\n userName: comment.authorName,\r\n userImageFileId: comment.imageFileId ?? null,\r\n userImage: comment.imageFileId ?? null,\r\n buildingId: comment.buildingId,\r\n timestamp: new Date(comment.createdAt),\r\n text: comment.text,\r\n isPending: comment.isPending || false,\r\n highlight: ctx.highlight,\r\n focused: ctx.focused,\r\n }\r\n if (comment.isPending) return base\r\n\r\n return {\r\n ...base,\r\n showActions: true,\r\n canEdit: ctx.isAuthor,\r\n canDelete: ctx.isAuthor,\r\n onSelect: ctx.onSelect,\r\n onFocus: ctx.onFocus,\r\n onReply: () => onReply(comment.id),\r\n onEdit: ctx.isAuthor ? ctx.onEdit : undefined,\r\n onRemove: ctx.isAuthor ? ctx.onRemove : undefined,\r\n }\r\n },\r\n\r\n clusterMemberMapper: (c) => ({\r\n id: c.id,\r\n userName: c.authorName,\r\n imageFileId: c.imageFileId ?? null,\r\n }),\r\n\r\n dataHashPart: (c) => `${c.id}:${c.text ?? \"\"}:${c.isPending ? 1 : 0}`,\r\n\r\n isAuthor: (c) => currentUserId != null && String(c.authorId) === currentUserId,\r\n\r\n onRemove,\r\n\r\n makePendingItem: (id, pos) => ({\r\n id,\r\n x: pos.x,\r\n y: pos.y,\r\n z: pos.z,\r\n authorName: \"Loading...\",\r\n imageFileId: null,\r\n image: \"\",\r\n text: \"Creating comment...\",\r\n createdAt: new Date().toISOString(),\r\n buildingId,\r\n isPending: true,\r\n }),\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAGA,SAAS,wBAAwB;AAEjC,OAAO,gBAAgB;AAmChB,SAAS,wBAAwB,MAAuD;AAC7F,QAAM,EAAE,eAAe,UAAU,SAAS,WAAW,IAAI;AAEzD,SAAO;AAAA,IACL,aAAa;AAAA,IACb,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,kBAAkB;AAAA;AAAA;AAAA;AAAA,IAKlB,aAAa,CAAC,SAAS,QAAQ;AArDnC;AAsDM,YAAM,OAAO;AAAA,QACX,UAAU,QAAQ;AAAA,QAClB,kBAAiB,aAAQ,gBAAR,YAAuB;AAAA,QACxC,YAAW,aAAQ,gBAAR,YAAuB;AAAA,QAClC,YAAY,QAAQ;AAAA,QACpB,WAAW,IAAI,KAAK,QAAQ,SAAS;AAAA,QACrC,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ,aAAa;AAAA,QAChC,WAAW,IAAI;AAAA,QACf,SAAS,IAAI;AAAA,MACf;AACA,UAAI,QAAQ,UAAW,QAAO;AAE9B,aAAO,iCACF,OADE;AAAA,QAEL,aAAa;AAAA,QACb,SAAS,IAAI;AAAA,QACb,WAAW,IAAI;AAAA,QACf,UAAU,IAAI;AAAA,QACd,SAAS,IAAI;AAAA,QACb,SAAS,MAAM,QAAQ,QAAQ,EAAE;AAAA,QACjC,QAAQ,IAAI,WAAW,IAAI,SAAS;AAAA,QACpC,UAAU,IAAI,WAAW,IAAI,WAAW;AAAA,MAC1C;AAAA,IACF;AAAA,IAEA,qBAAqB,CAAC,MAAG;AAhF7B;AAgFiC;AAAA,QAC3B,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,cAAa,OAAE,gBAAF,YAAiB;AAAA,MAChC;AAAA;AAAA,IAEA,cAAc,CAAC,MAAG;AAtFtB;AAsFyB,gBAAG,EAAE,EAAE,KAAI,OAAE,SAAF,YAAU,EAAE,IAAI,EAAE,YAAY,IAAI,CAAC;AAAA;AAAA,IAEnE,UAAU,CAAC,MAAM,iBAAiB,QAAQ,OAAO,EAAE,QAAQ,MAAM;AAAA,IAEjE;AAAA,IAEA,iBAAiB,CAAC,IAAI,SAAS;AAAA,MAC7B;AAAA,MACA,GAAG,IAAI;AAAA,MACP,GAAG,IAAI;AAAA,MACP,GAAG,IAAI;AAAA,MACP,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,OAAO;AAAA,MACP,MAAM;AAAA,MACN,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin wrapper over the generic `useMarkerLayerBim`: owns comment data fetching, the
|
|
3
|
+
* author-cascade delete, and the sidebar reply/edit handoff, then hands rendering off to the
|
|
4
|
+
* shared marker layer via `commentMarkerConfig`. Signature and return shape are unchanged —
|
|
5
|
+
* `AddToBim/index.tsx` consumes `{ addPendingComment, removePendingComment, commentCount }`.
|
|
6
|
+
*/
|
|
1
7
|
export declare function useCommentMarkers(world: any, buildingId: number): {
|
|
2
|
-
addPendingComment: (
|
|
8
|
+
addPendingComment: (pos: {
|
|
3
9
|
x: number;
|
|
4
10
|
y: number;
|
|
5
11
|
z: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCommentMarkers.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCommentMarkers.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM;;;;;;;;EAmF/D"}
|
|
@@ -20,163 +20,17 @@ var __spreadValues = (a, b) => {
|
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
21
|
import { useSession } from "next-auth/react";
|
|
22
22
|
import * as React from "react";
|
|
23
|
-
import { createRoot } from "react-dom/client";
|
|
24
|
-
import * as THREE from "three";
|
|
25
|
-
import { CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
|
|
26
23
|
import { useComments, useDeleteComments } from "../../../../../../../hooks/comments/comments";
|
|
27
|
-
import {
|
|
24
|
+
import { useCoreHooks } from "../../../../../../../hooks/provider";
|
|
28
25
|
import { useUsers } from "../../../../../../../hooks/users/users";
|
|
29
26
|
import { MenusContext } from "../../../../../../../store";
|
|
30
27
|
import { ViewerNames } from "../../../../../../../types/dbTypes";
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import { clusterMarkersByScreenSpace } from "./clusterMarkersByScreenSpace";
|
|
34
|
-
import { computeCommentLookAt } from "./commentCameraUtils";
|
|
35
|
-
import { renderCSS2DMarkers } from "./renderCSS2DMarkers";
|
|
36
|
-
function makeCommentPropsMapper(state) {
|
|
37
|
-
const { currentCommentId, focusedCommentId, currentUserId, onSelect, onFocus, onEdit, onReply, onRemove } = state;
|
|
38
|
-
return (comment) => {
|
|
39
|
-
var _a, _b;
|
|
40
|
-
const base = {
|
|
41
|
-
userName: comment.authorName,
|
|
42
|
-
userImageFileId: (_a = comment.imageFileId) != null ? _a : null,
|
|
43
|
-
userImage: (_b = comment.imageFileId) != null ? _b : null,
|
|
44
|
-
buildingId: comment.buildingId,
|
|
45
|
-
timestamp: new Date(comment.createdAt),
|
|
46
|
-
text: comment.text,
|
|
47
|
-
isPending: comment.isPending || false,
|
|
48
|
-
highlight: currentCommentId === comment.id,
|
|
49
|
-
focused: focusedCommentId === comment.id
|
|
50
|
-
};
|
|
51
|
-
if (comment.isPending) return base;
|
|
52
|
-
const isAuthor = currentUserId != null && String(comment.authorId) === currentUserId;
|
|
53
|
-
return __spreadProps(__spreadValues({}, base), {
|
|
54
|
-
showActions: true,
|
|
55
|
-
canEdit: isAuthor,
|
|
56
|
-
canDelete: isAuthor,
|
|
57
|
-
onSelect: () => onSelect(comment.id),
|
|
58
|
-
onFocus: () => onFocus(comment.id),
|
|
59
|
-
onReply: () => onReply(comment.id),
|
|
60
|
-
onEdit: isAuthor ? () => onEdit(comment.id) : void 0,
|
|
61
|
-
onRemove: isAuthor ? () => onRemove(comment.id) : void 0
|
|
62
|
-
});
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function clearSingles(world, registry) {
|
|
66
|
-
renderCSS2DMarkers(world, {
|
|
67
|
-
items: [],
|
|
68
|
-
markerIdKey: "commentId",
|
|
69
|
-
registry,
|
|
70
|
-
component: BimComment,
|
|
71
|
-
propsMapper: () => ({}),
|
|
72
|
-
sphereColor: "white",
|
|
73
|
-
isVisible: false,
|
|
74
|
-
onRemove: () => {
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
function clearClusters(world, registry) {
|
|
79
|
-
registry.current.forEach(({ root, css2dObject }) => {
|
|
80
|
-
world.scene.three.remove(css2dObject);
|
|
81
|
-
const el = css2dObject.element;
|
|
82
|
-
el == null ? void 0 : el.remove();
|
|
83
|
-
root.unmount();
|
|
84
|
-
});
|
|
85
|
-
registry.current.clear();
|
|
86
|
-
}
|
|
87
|
-
function renderMarkers(state, singleRegistry, clusterRegistry, lastSignatureRef) {
|
|
88
|
-
var _a, _b, _c;
|
|
89
|
-
const { world, items, pending, isVisible, currentCommentId, focusedCommentId, coreHooks, onRemove, onSelect, onFocus } = state;
|
|
90
|
-
if (!world) return;
|
|
91
|
-
if (!isVisible) {
|
|
92
|
-
if (lastSignatureRef.current === "hidden") return;
|
|
93
|
-
clearSingles(world, singleRegistry);
|
|
94
|
-
clearClusters(world, clusterRegistry);
|
|
95
|
-
lastSignatureRef.current = "hidden";
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const camera = (_a = world.camera) == null ? void 0 : _a.three;
|
|
99
|
-
const dom = (_c = (_b = world.renderer) == null ? void 0 : _b.three) == null ? void 0 : _c.domElement;
|
|
100
|
-
if (!camera || !dom) return;
|
|
101
|
-
const width = dom.clientWidth || dom.width || 0;
|
|
102
|
-
const height = dom.clientHeight || dom.height || 0;
|
|
103
|
-
if (!width || !height) return;
|
|
104
|
-
const { clusters, singles } = clusterMarkersByScreenSpace(items, camera, width, height, 44);
|
|
105
|
-
const singleItems = [...singles, ...pending];
|
|
106
|
-
const clusterKeys = clusters.map((c) => c.key);
|
|
107
|
-
const dataHash = [...items, ...pending].map((c) => {
|
|
108
|
-
var _a2;
|
|
109
|
-
return `${c.id}:${(_a2 = c.text) != null ? _a2 : ""}:${c.isPending ? 1 : 0}`;
|
|
110
|
-
}).join(";");
|
|
111
|
-
const signature = `v2|${currentCommentId}|${focusedCommentId}|C:${clusterKeys.join(",")}|S:${singleItems.map((s) => s.id).join(",")}|D:${dataHash}`;
|
|
112
|
-
if (signature === lastSignatureRef.current) return;
|
|
113
|
-
lastSignatureRef.current = signature;
|
|
114
|
-
renderCSS2DMarkers(world, {
|
|
115
|
-
items: singleItems,
|
|
116
|
-
markerIdKey: "commentId",
|
|
117
|
-
registry: singleRegistry,
|
|
118
|
-
component: BimComment,
|
|
119
|
-
hooksContextValue: coreHooks,
|
|
120
|
-
propsMapper: makeCommentPropsMapper(state),
|
|
121
|
-
sphereColor: "white",
|
|
122
|
-
isVisible: true,
|
|
123
|
-
onRemove
|
|
124
|
-
});
|
|
125
|
-
singleRegistry.current.forEach((ref, id) => {
|
|
126
|
-
const nid = Number(id);
|
|
127
|
-
ref.css2dObject.renderOrder = nid === currentCommentId || nid === focusedCommentId ? 1 : 0;
|
|
128
|
-
});
|
|
129
|
-
const reg = clusterRegistry.current;
|
|
130
|
-
const wanted = new Set(clusterKeys);
|
|
131
|
-
for (const [key, ref] of reg) {
|
|
132
|
-
if (!wanted.has(key)) {
|
|
133
|
-
world.scene.three.remove(ref.css2dObject);
|
|
134
|
-
const el = ref.css2dObject.element;
|
|
135
|
-
el == null ? void 0 : el.remove();
|
|
136
|
-
ref.root.unmount();
|
|
137
|
-
reg.delete(key);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
for (const cluster of clusters) {
|
|
141
|
-
const members = cluster.members.map((m) => {
|
|
142
|
-
var _a2;
|
|
143
|
-
return {
|
|
144
|
-
id: m.id,
|
|
145
|
-
userName: m.authorName,
|
|
146
|
-
imageFileId: (_a2 = m.imageFileId) != null ? _a2 : null
|
|
147
|
-
};
|
|
148
|
-
});
|
|
149
|
-
const highlight = currentCommentId != null && members.some((m) => m.id === currentCommentId);
|
|
150
|
-
const element = React.createElement(BimCommentCluster, { members, highlight, onSelect, onFocus });
|
|
151
|
-
const wrapped = coreHooks ? React.createElement(HooksCtx.Provider, { value: coreHooks }, element) : element;
|
|
152
|
-
const existing = reg.get(cluster.key);
|
|
153
|
-
if (existing) {
|
|
154
|
-
existing.root.render(wrapped);
|
|
155
|
-
existing.css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z);
|
|
156
|
-
existing.css2dObject.renderOrder = highlight ? 1 : 0;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const labelDiv = document.createElement("div");
|
|
160
|
-
labelDiv.style.pointerEvents = "auto";
|
|
161
|
-
const root = createRoot(labelDiv);
|
|
162
|
-
root.render(wrapped);
|
|
163
|
-
const css2dObject = new CSS2DObject(labelDiv);
|
|
164
|
-
css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z);
|
|
165
|
-
css2dObject.element.style.pointerEvents = "auto";
|
|
166
|
-
css2dObject.renderOrder = highlight ? 1 : 0;
|
|
167
|
-
world.scene.three.add(css2dObject);
|
|
168
|
-
reg.set(cluster.key, { root, css2dObject });
|
|
169
|
-
}
|
|
170
|
-
}
|
|
28
|
+
import { useMarkerLayerBim } from "../../../../../shared/markers/useMarkerLayerBim";
|
|
29
|
+
import { makeCommentMarkerConfig } from "./commentMarkerConfig";
|
|
171
30
|
function useCommentMarkers(world, buildingId) {
|
|
172
31
|
var _a, _b, _c, _d;
|
|
173
32
|
const { state: menusState, dispatch: menusDispatch, setIsSidebarOpen } = React.useContext(MenusContext);
|
|
174
33
|
const { commentsVisibleInViewer, currentCommentId, focusedCommentId, focusRequestId } = menusState.menus;
|
|
175
|
-
const singleRegistry = React.useRef(/* @__PURE__ */ new Map());
|
|
176
|
-
const clusterRegistry = React.useRef(/* @__PURE__ */ new Map());
|
|
177
|
-
const lastSignatureRef = React.useRef("");
|
|
178
|
-
const stateRef = React.useRef(null);
|
|
179
|
-
const commentsRef = React.useRef([]);
|
|
180
34
|
const { comments } = useComments();
|
|
181
35
|
const { users } = useUsers();
|
|
182
36
|
const coreHooks = useCoreHooks();
|
|
@@ -197,105 +51,47 @@ function useCommentMarkers(world, buildingId) {
|
|
|
197
51
|
image: (_c2 = user == null ? void 0 : user.imageFileId) != null ? _c2 : null
|
|
198
52
|
});
|
|
199
53
|
});
|
|
200
|
-
commentsRef.current = eligibleComments;
|
|
201
54
|
const handleRemoveComment = React.useCallback((commentId) => {
|
|
202
55
|
const replyIds = comments.filter((c) => c.replyToId === commentId).map((c) => c.id);
|
|
203
56
|
void deleteComments({ ids: [commentId, ...replyIds] });
|
|
204
57
|
}, [comments, deleteComments]);
|
|
205
|
-
const handleSelectComment = React.useCallback((commentId) => {
|
|
206
|
-
menusDispatch({ type: "SET_CURRENT_COMMENT_ID", payload: { commentId } });
|
|
207
|
-
}, [menusDispatch]);
|
|
208
|
-
const handleFocusComment = React.useCallback((commentId) => {
|
|
209
|
-
menusDispatch({ type: "SET_CURRENT_COMMENT_ID", payload: { commentId } });
|
|
210
|
-
menusDispatch({ type: "SET_FOCUSED_COMMENT_ID", payload: { commentId } });
|
|
211
|
-
}, [menusDispatch]);
|
|
212
58
|
const requestSidebarAction = React.useCallback((commentId, action) => {
|
|
213
59
|
setIsSidebarOpen(true);
|
|
214
60
|
menusDispatch({ type: "SET_SIDEBAR_SELECTED_TAB", payload: { selectedTab: "communication" } });
|
|
215
61
|
menusDispatch({ type: "SET_CURRENT_COMMENT_ID", payload: { commentId } });
|
|
216
62
|
menusDispatch({ type: "REQUEST_COMMENT_ACTION", payload: { commentId, action } });
|
|
217
63
|
}, [menusDispatch, setIsSidebarOpen]);
|
|
218
|
-
const handleEditComment = React.useCallback((commentId) => {
|
|
219
|
-
requestSidebarAction(commentId, "edit");
|
|
220
|
-
}, [requestSidebarAction]);
|
|
221
64
|
const handleReplyComment = React.useCallback((commentId) => {
|
|
222
65
|
requestSidebarAction(commentId, "reply");
|
|
223
66
|
}, [requestSidebarAction]);
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
items: eligibleComments.map((c) => __spreadProps(__spreadValues({}, c), { isPending: false })),
|
|
237
|
-
pending: pendingComments.map((p) => ({
|
|
238
|
-
id: p.id,
|
|
239
|
-
x: p.x,
|
|
240
|
-
y: p.y,
|
|
241
|
-
z: p.z,
|
|
242
|
-
authorName: "Loading...",
|
|
243
|
-
imageFileId: null,
|
|
244
|
-
image: "",
|
|
245
|
-
text: "Creating comment...",
|
|
246
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
247
|
-
buildingId,
|
|
248
|
-
isPending: true
|
|
249
|
-
})),
|
|
250
|
-
isVisible,
|
|
251
|
-
currentCommentId,
|
|
252
|
-
focusedCommentId,
|
|
67
|
+
const store = {
|
|
68
|
+
currentId: currentCommentId,
|
|
69
|
+
focusedId: focusedCommentId,
|
|
70
|
+
focusRequestId,
|
|
71
|
+
setCurrentId: (id) => menusDispatch({ type: "SET_CURRENT_COMMENT_ID", payload: { commentId: id } }),
|
|
72
|
+
setFocusedId: (id) => {
|
|
73
|
+
menusDispatch({ type: "SET_CURRENT_COMMENT_ID", payload: { commentId: id } });
|
|
74
|
+
menusDispatch({ type: "SET_FOCUSED_COMMENT_ID", payload: { commentId: id } });
|
|
75
|
+
},
|
|
76
|
+
requestEdit: (id) => requestSidebarAction(id, "edit")
|
|
77
|
+
};
|
|
78
|
+
const config = makeCommentMarkerConfig({
|
|
253
79
|
currentUserId,
|
|
254
|
-
coreHooks,
|
|
255
80
|
onRemove: handleRemoveComment,
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if ((frame++ & 1) === 0 && stateRef.current) {
|
|
267
|
-
renderMarkers(stateRef.current, singleRegistry, clusterRegistry, lastSignatureRef);
|
|
268
|
-
}
|
|
269
|
-
raf = requestAnimationFrame(loop);
|
|
270
|
-
};
|
|
271
|
-
raf = requestAnimationFrame(loop);
|
|
272
|
-
return () => {
|
|
273
|
-
cancelAnimationFrame(raf);
|
|
274
|
-
clearClusters(world, clusterRegistry);
|
|
275
|
-
clearSingles(world, singleRegistry);
|
|
276
|
-
lastSignatureRef.current = "";
|
|
277
|
-
};
|
|
278
|
-
}, [world]);
|
|
279
|
-
React.useEffect(() => {
|
|
280
|
-
var _a2;
|
|
281
|
-
if (focusedCommentId == null || !world) return;
|
|
282
|
-
const target = commentsRef.current.find((c) => c.id === focusedCommentId);
|
|
283
|
-
if (!target || target.x == null || target.y == null || target.z == null) return;
|
|
284
|
-
const controls = (_a2 = world.camera) == null ? void 0 : _a2.controls;
|
|
285
|
-
if (!controls) return;
|
|
286
|
-
const camPos = controls.getPosition(new THREE.Vector3());
|
|
287
|
-
const camTarget = controls.getTarget(new THREE.Vector3());
|
|
288
|
-
const lookAt = computeCommentLookAt(
|
|
289
|
-
{ x: camPos.x, y: camPos.y, z: camPos.z },
|
|
290
|
-
{ x: camTarget.x, y: camTarget.y, z: camTarget.z },
|
|
291
|
-
{ x: target.x, y: target.y, z: target.z }
|
|
292
|
-
);
|
|
293
|
-
void controls.setLookAt(lookAt.camX, lookAt.camY, lookAt.camZ, lookAt.tarX, lookAt.tarY, lookAt.tarZ, true);
|
|
294
|
-
}, [focusRequestId, world]);
|
|
81
|
+
onReply: handleReplyComment,
|
|
82
|
+
buildingId
|
|
83
|
+
});
|
|
84
|
+
const itemsForLayer = eligibleComments.map((c) => __spreadProps(__spreadValues({}, c), { isPending: false }));
|
|
85
|
+
const { addPending, removePending } = useMarkerLayerBim(world, itemsForLayer, {
|
|
86
|
+
isVisible: (_d = commentsVisibleInViewer == null ? void 0 : commentsVisibleInViewer.includes(ViewerNames.bim)) != null ? _d : false,
|
|
87
|
+
store,
|
|
88
|
+
coreHooks,
|
|
89
|
+
config
|
|
90
|
+
});
|
|
295
91
|
const commentCount = comments.filter(
|
|
296
92
|
(c) => c.viewer === ViewerNames.bim && (!buildingId || buildingId === -1 || c.buildingId === buildingId)
|
|
297
93
|
).length;
|
|
298
|
-
return { addPendingComment, removePendingComment, commentCount };
|
|
94
|
+
return { addPendingComment: addPending, removePendingComment: removePending, commentCount };
|
|
299
95
|
}
|
|
300
96
|
export {
|
|
301
97
|
useCommentMarkers
|