@collabdt/core 0.0.55 → 0.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/dist/core/components/AppSidebarContent.d.ts +2 -1
  2. package/dist/core/components/AppSidebarContent.d.ts.map +1 -1
  3. package/dist/core/components/AppSidebarContent.js +8 -5
  4. package/dist/core/components/AppSidebarContent.js.map +1 -1
  5. package/dist/core/components/Toolbar.d.ts +7 -1
  6. package/dist/core/components/Toolbar.d.ts.map +1 -1
  7. package/dist/core/components/Toolbar.js +3 -3
  8. package/dist/core/components/Toolbar.js.map +1 -1
  9. package/dist/core/components/TopNavigationBar.d.ts +6 -1
  10. package/dist/core/components/TopNavigationBar.d.ts.map +1 -1
  11. package/dist/core/components/TopNavigationBar.js +2 -2
  12. package/dist/core/components/TopNavigationBar.js.map +1 -1
  13. package/dist/core/components/authentication/AuthPage.d.ts +2 -1
  14. package/dist/core/components/authentication/AuthPage.d.ts.map +1 -1
  15. package/dist/core/components/authentication/AuthPage.js +2 -3
  16. package/dist/core/components/authentication/AuthPage.js.map +1 -1
  17. package/dist/core/components/authentication/Signin.d.ts +6 -1
  18. package/dist/core/components/authentication/Signin.d.ts.map +1 -1
  19. package/dist/core/components/authentication/Signin.js +17 -6
  20. package/dist/core/components/authentication/Signin.js.map +1 -1
  21. package/dist/core/components/organizationConfig/src/organizationConfigContent.d.ts.map +1 -1
  22. package/dist/core/components/organizationConfig/src/organizationConfigContent.js +109 -36
  23. package/dist/core/components/organizationConfig/src/organizationConfigContent.js.map +1 -1
  24. package/dist/core/components/settings/index.d.ts +3 -1
  25. package/dist/core/components/settings/index.d.ts.map +1 -1
  26. package/dist/core/components/settings/index.js +2 -2
  27. package/dist/core/components/settings/index.js.map +1 -1
  28. package/dist/core/components/settings/src/AccountSettingsPanel.d.ts.map +1 -1
  29. package/dist/core/components/settings/src/AccountSettingsPanel.js +9 -2
  30. package/dist/core/components/settings/src/AccountSettingsPanel.js.map +1 -1
  31. package/dist/core/components/settings/src/OrganizationSettingsPanel.d.ts +5 -1
  32. package/dist/core/components/settings/src/OrganizationSettingsPanel.d.ts.map +1 -1
  33. package/dist/core/components/settings/src/OrganizationSettingsPanel.js +7 -3
  34. package/dist/core/components/settings/src/OrganizationSettingsPanel.js.map +1 -1
  35. package/dist/core/components/settings/src/SettingsContent.d.ts +2 -1
  36. package/dist/core/components/settings/src/SettingsContent.d.ts.map +1 -1
  37. package/dist/core/components/settings/src/SettingsContent.js +2 -2
  38. package/dist/core/components/settings/src/SettingsContent.js.map +1 -1
  39. package/dist/core/components/support/BugReportDialog.d.ts +3 -2
  40. package/dist/core/components/support/BugReportDialog.d.ts.map +1 -1
  41. package/dist/core/components/support/BugReportDialog.js +71 -25
  42. package/dist/core/components/support/BugReportDialog.js.map +1 -1
  43. package/dist/core/components/support/FeatureRequestDialog.d.ts +3 -1
  44. package/dist/core/components/support/FeatureRequestDialog.d.ts.map +1 -1
  45. package/dist/core/components/support/FeatureRequestDialog.js +7 -4
  46. package/dist/core/components/support/FeatureRequestDialog.js.map +1 -1
  47. package/dist/core/components/support/SupportMenu.d.ts.map +1 -1
  48. package/dist/core/components/support/SupportMenu.js +1 -4
  49. package/dist/core/components/support/SupportMenu.js.map +1 -1
  50. package/dist/core/components/ui/AnimatedBackground.d.ts +2 -1
  51. package/dist/core/components/ui/AnimatedBackground.d.ts.map +1 -1
  52. package/dist/core/components/ui/AnimatedBackground.js +2 -3
  53. package/dist/core/components/ui/AnimatedBackground.js.map +1 -1
  54. package/dist/core/components/ui/AppSidebar.d.ts.map +1 -1
  55. package/dist/core/components/ui/AppSidebar.js +11 -11
  56. package/dist/core/components/ui/AppSidebar.js.map +1 -1
  57. package/dist/core/components/ui/InfoSidebar/Container.d.ts +3 -1
  58. package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
  59. package/dist/core/components/ui/InfoSidebar/Container.js +4 -2
  60. package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
  61. package/dist/core/components/ui/InfoSidebar/Header.d.ts +3 -2
  62. package/dist/core/components/ui/InfoSidebar/Header.d.ts.map +1 -1
  63. package/dist/core/components/ui/InfoSidebar/Header.js +5 -6
  64. package/dist/core/components/ui/InfoSidebar/Header.js.map +1 -1
  65. package/dist/core/components/ui/InfoSidebar/index.d.ts +7 -1
  66. package/dist/core/components/ui/InfoSidebar/index.d.ts.map +1 -1
  67. package/dist/core/components/ui/InfoSidebar/index.js +4 -4
  68. package/dist/core/components/ui/InfoSidebar/index.js.map +1 -1
  69. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +2 -1
  70. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  71. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +3 -2
  72. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  73. package/dist/core/components/ui/Sensors/SensorsSection.d.ts +3 -1
  74. package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
  75. package/dist/core/components/ui/Sensors/SensorsSection.js +3 -1
  76. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  77. package/dist/core/components/ui/Sidebar.d.ts +8 -0
  78. package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
  79. package/dist/core/components/ui/Sidebar.js +21 -7
  80. package/dist/core/components/ui/Sidebar.js.map +1 -1
  81. package/dist/core/components/ui/ToolbarButton.js +18 -1
  82. package/dist/core/components/ui/ToolbarButton.js.map +1 -1
  83. package/dist/core/components/viewers/Data/DataMenu.d.ts +5 -1
  84. package/dist/core/components/viewers/Data/DataMenu.d.ts.map +1 -1
  85. package/dist/core/components/viewers/Data/DataMenu.js +6 -3
  86. package/dist/core/components/viewers/Data/DataMenu.js.map +1 -1
  87. package/dist/core/components/viewers/Data/HeaderButtons.d.ts +3 -1
  88. package/dist/core/components/viewers/Data/HeaderButtons.d.ts.map +1 -1
  89. package/dist/core/components/viewers/Data/HeaderButtons.js +6 -2
  90. package/dist/core/components/viewers/Data/HeaderButtons.js.map +1 -1
  91. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.d.ts +3 -1
  92. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.d.ts.map +1 -1
  93. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.js +4 -2
  94. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.js.map +1 -1
  95. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.d.ts +3 -1
  96. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.d.ts.map +1 -1
  97. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js +3 -1
  98. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js.map +1 -1
  99. package/dist/core/components/viewers/Data/details/DetailHeader.d.ts +2 -1
  100. package/dist/core/components/viewers/Data/details/DetailHeader.d.ts.map +1 -1
  101. package/dist/core/components/viewers/Data/details/DetailHeader.js +3 -5
  102. package/dist/core/components/viewers/Data/details/DetailHeader.js.map +1 -1
  103. package/dist/core/components/viewers/Viewer.d.ts +7 -1
  104. package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
  105. package/dist/core/components/viewers/Viewer.js +6 -6
  106. package/dist/core/components/viewers/Viewer.js.map +1 -1
  107. package/dist/core/components/viewers/bim/BimToolbar.d.ts +3 -1
  108. package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
  109. package/dist/core/components/viewers/bim/BimToolbar.js +2 -2
  110. package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
  111. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +3 -1
  112. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
  113. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
  114. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
  115. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.d.ts +5 -1
  116. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.d.ts.map +1 -1
  117. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +3 -2
  118. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
  119. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +3 -1
  120. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
  121. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +2 -2
  122. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
  123. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +1 -1
  124. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
  125. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +2 -2
  126. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
  127. package/dist/core/components/viewers/bim/src/tools/bimToolbar.d.ts +3 -1
  128. package/dist/core/components/viewers/bim/src/tools/bimToolbar.d.ts.map +1 -1
  129. package/dist/core/components/viewers/bim/src/tools/bimToolbar.js +4 -2
  130. package/dist/core/components/viewers/bim/src/tools/bimToolbar.js.map +1 -1
  131. package/dist/core/components/viewers/map/MapViewer.d.ts +3 -1
  132. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  133. package/dist/core/components/viewers/map/MapViewer.js +2 -2
  134. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  135. package/dist/core/components/viewers/map/datasets/RowActions.d.ts +2 -1
  136. package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
  137. package/dist/core/components/viewers/map/datasets/RowActions.js +5 -4
  138. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  139. package/dist/core/components/viewers/map/datasets/index.d.ts +5 -1
  140. package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
  141. package/dist/core/components/viewers/map/datasets/index.js +15 -16
  142. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  143. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
  144. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
  145. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +3 -5
  146. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
  147. package/dist/core/components/viewers/map/src/Geocoder.d.ts +3 -1
  148. package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
  149. package/dist/core/components/viewers/map/src/Geocoder.js +5 -1
  150. package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
  151. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +6 -1
  152. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
  153. package/dist/core/components/viewers/map/src/MapLayers/index.js +3 -3
  154. package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
  155. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts +5 -1
  156. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
  157. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +6 -10
  158. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
  159. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +3 -1
  160. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
  161. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +2 -2
  162. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
  163. package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts +6 -1
  164. package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts.map +1 -1
  165. package/dist/core/components/viewers/map/src/MapSidebar/index.js +5 -4
  166. package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
  167. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.d.ts +5 -1
  168. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.d.ts.map +1 -1
  169. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js +5 -8
  170. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js.map +1 -1
  171. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +3 -1
  172. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
  173. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
  174. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
  175. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.d.ts +3 -1
  176. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.d.ts.map +1 -1
  177. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.js +2 -2
  178. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.js.map +1 -1
  179. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.d.ts +3 -1
  180. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.d.ts.map +1 -1
  181. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.js +4 -7
  182. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.js.map +1 -1
  183. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
  184. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +8 -8
  185. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
  186. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.d.ts +8 -1
  187. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.d.ts.map +1 -1
  188. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.js +8 -3
  189. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.js.map +1 -1
  190. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.d.ts +11 -1
  191. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.d.ts.map +1 -1
  192. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.js +5 -3
  193. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.js.map +1 -1
  194. package/dist/core/components/viewers/map/src/tools/mapTools.d.ts +10 -1
  195. package/dist/core/components/viewers/map/src/tools/mapTools.d.ts.map +1 -1
  196. package/dist/core/components/viewers/map/src/tools/mapTools.js +5 -3
  197. package/dist/core/components/viewers/map/src/tools/mapTools.js.map +1 -1
  198. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +14 -5
  199. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -1
  200. package/dist/core/components/viewers/map/utils/geocoding/config.js +22 -11
  201. package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -1
  202. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -1
  203. package/dist/core/components/viewers/map/utils/geocoding/index.js +2 -2
  204. package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -1
  205. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -1
  206. package/dist/core/components/viewers/map/utils/geocoding/osm.js +5 -4
  207. package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -1
  208. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -1
  209. package/dist/core/components/viewers/map/utils/geocoding/pelias.js +7 -5
  210. package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -1
  211. package/dist/core/components/viewers/pointcloud/PointCloudViewer.d.ts +3 -1
  212. package/dist/core/components/viewers/pointcloud/PointCloudViewer.d.ts.map +1 -1
  213. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +11 -12
  214. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
  215. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts +3 -1
  216. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts.map +1 -1
  217. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js +37 -50
  218. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js.map +1 -1
  219. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.d.ts +3 -1
  220. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.d.ts.map +1 -1
  221. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.js +5 -3
  222. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.js.map +1 -1
  223. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.d.ts +2 -1
  224. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.d.ts.map +1 -1
  225. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js +8 -7
  226. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js.map +1 -1
  227. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.d.ts +2 -1
  228. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.d.ts.map +1 -1
  229. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js +22 -9
  230. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js.map +1 -1
  231. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.d.ts +5 -1
  232. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.d.ts.map +1 -1
  233. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.js +3 -2
  234. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.js.map +1 -1
  235. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts +3 -1
  236. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
  237. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -2
  238. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
  239. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts +2 -1
  240. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  241. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js +12 -22
  242. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  243. package/dist/core/hooks/useCaptureScreenshot.d.ts +2 -0
  244. package/dist/core/hooks/useCaptureScreenshot.d.ts.map +1 -0
  245. package/dist/core/hooks/useCaptureScreenshot.js +63 -0
  246. package/dist/core/hooks/useCaptureScreenshot.js.map +1 -0
  247. package/dist/core/hooks/useGeocodingRuntimeConfig.d.ts +3 -0
  248. package/dist/core/hooks/useGeocodingRuntimeConfig.d.ts.map +1 -0
  249. package/dist/core/hooks/useGeocodingRuntimeConfig.js +17 -0
  250. package/dist/core/hooks/useGeocodingRuntimeConfig.js.map +1 -0
  251. package/dist/core/store/AppConfig/context.d.ts +15 -1
  252. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  253. package/dist/core/store/AppConfig/context.js +26 -5
  254. package/dist/core/store/AppConfig/context.js.map +1 -1
  255. package/dist/core/store/CombineProviders.d.ts +6 -1
  256. package/dist/core/store/CombineProviders.d.ts.map +1 -1
  257. package/dist/core/store/CombineProviders.js +4 -3
  258. package/dist/core/store/CombineProviders.js.map +1 -1
  259. package/dist/core/types/tools.d.ts +2 -1
  260. package/dist/core/types/tools.d.ts.map +1 -1
  261. package/dist/core/utils/imageUtils.d.ts.map +1 -1
  262. package/dist/core/utils/imageUtils.js +2 -1
  263. package/dist/core/utils/imageUtils.js.map +1 -1
  264. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- var _a;
4
3
  import * as React from "react";
4
+ import { useSession } from "next-auth/react";
5
+ import { useOrganization } from "../../../../../hooks/organizations/organizations";
5
6
  import { ProgressBar } from "../../../map/src/tools/AddTools/AddFile/ProgressBar";
6
7
  import { Button, Input, ScrollArea } from "../../../../ui";
7
- const API_BASE = (_a = process.env.NEXT_PUBLIC_POINTCLOUD_API_URL) != null ? _a : "http://localhost:5101";
8
+ import { toast } from "sonner";
8
9
  const CONVERSION_STATUS = Object.freeze({
9
10
  STARTED: "conversion_started",
10
11
  DOWNLOAD: "download",
@@ -15,10 +16,17 @@ const CONVERSION_STATUS = Object.freeze({
15
16
  FINISHED: "finished"
16
17
  });
17
18
  function UploadPointCloudPage({
18
- onGoBackButtonClick
19
+ onGoBackButtonClick,
20
+ pointcloudApiUrl
19
21
  }) {
22
+ var _a, _b;
23
+ const API_BASE = pointcloudApiUrl != null ? pointcloudApiUrl : "http://localhost:5101";
24
+ const { data: session } = useSession();
25
+ const organizationId = (_b = (_a = session == null ? void 0 : session.user) == null ? void 0 : _a.organizationId) != null ? _b : null;
26
+ const { organization } = useOrganization(organizationId ? organizationId.toString() : null);
20
27
  const [name, setName] = React.useState("");
21
28
  const [file, setFile] = React.useState(null);
29
+ const [uploadSuccess, setUploadSuccess] = React.useState(false);
22
30
  const [progress, setProgress] = React.useState(0);
23
31
  const [status, setStatus] = React.useState("idle");
24
32
  const [pointCloudId, setPointCloudId] = React.useState(null);
@@ -40,7 +48,7 @@ function UploadPointCloudPage({
40
48
  const res = await fetch(`${API_BASE}/point-cloud`, {
41
49
  method: "POST",
42
50
  headers: { "Content-Type": "application/json" },
43
- body: JSON.stringify({ name: name2 })
51
+ body: JSON.stringify({ name: name2, organizationId, organizationName: organization == null ? void 0 : organization.name })
44
52
  });
45
53
  if (!res.ok) {
46
54
  const msg = await res.text();
@@ -104,14 +112,14 @@ function UploadPointCloudPage({
104
112
  );
105
113
  };
106
114
  es.addEventListener("progress", (event) => {
107
- var _a2, _b, _c;
115
+ var _a2, _b2, _c;
108
116
  try {
109
117
  const msgEvent = event;
110
118
  const data = JSON.parse(msgEvent.data);
111
119
  appendLog(
112
120
  "[progress]",
113
121
  (_a2 = data.status) != null ? _a2 : "",
114
- (_b = data.message) != null ? _b : "",
122
+ (_b2 = data.message) != null ? _b2 : "",
115
123
  (_c = data.progress) != null ? _c : ""
116
124
  );
117
125
  if (data.status && Object.values(CONVERSION_STATUS).includes(data.status)) {
@@ -128,6 +136,7 @@ function UploadPointCloudPage({
128
136
  appendLog("[finished] Conversion completed");
129
137
  setStatus(CONVERSION_STATUS.FINISHED);
130
138
  setProgress(100);
139
+ toast.success("Point cloud conversion completed");
131
140
  es.close();
132
141
  esRef.current = null;
133
142
  });
@@ -156,6 +165,7 @@ function UploadPointCloudPage({
156
165
  setPointCloudId(null);
157
166
  setJobId(null);
158
167
  setStatus("idle");
168
+ setUploadSuccess(false);
159
169
  try {
160
170
  appendLog("\u{1F7E6} 1) Creating point cloud...");
161
171
  setStatus("creating");
@@ -170,6 +180,8 @@ function UploadPointCloudPage({
170
180
  (pct) => setProgress(pct)
171
181
  );
172
182
  appendLog("\u2714 Upload finished");
183
+ setUploadSuccess(true);
184
+ toast.success("LAZ file uploaded successfully", { duration: 6e3 });
173
185
  appendLog("\u{1F7E6} 3) Starting conversion...");
174
186
  setStatus(CONVERSION_STATUS.STARTED);
175
187
  const conversion = await startConversion(pointCloud.id);
@@ -252,8 +264,8 @@ function UploadPointCloudPage({
252
264
  type: "file",
253
265
  accept: ".laz,.las",
254
266
  onChange: (e) => {
255
- var _a2, _b;
256
- const f = (_b = (_a2 = e.target.files) == null ? void 0 : _a2[0]) != null ? _b : null;
267
+ var _a2, _b2;
268
+ const f = (_b2 = (_a2 = e.target.files) == null ? void 0 : _a2[0]) != null ? _b2 : null;
257
269
  setFile(f);
258
270
  }
259
271
  }
@@ -294,7 +306,8 @@ function UploadPointCloudPage({
294
306
  ] })
295
307
  ] }),
296
308
  /* @__PURE__ */ jsx(ProgressBar, { value: progress })
297
- ] })
309
+ ] }),
310
+ uploadSuccess && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-green-50 border border-green-200 px-3 py-2 text-sm text-green-800 font-medium", children: "\u2714 LAZ file uploaded successfully \u2014 conversion in progress" })
298
311
  ] })
299
312
  ] }),
300
313
  /* @__PURE__ */ jsxs("div", { className: "rounded-md border bg-muted/20 p-3 flex flex-col gap-2", children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.tsx"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// app/point-clouds/upload/page.tsx\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport { ProgressBar } from \"../../../map/src/tools/AddTools/AddFile/ProgressBar\";\r\nimport { Button, Input, ScrollArea } from '../../../../ui';\r\n\r\nconst API_BASE =\r\n process.env.NEXT_PUBLIC_POINTCLOUD_API_URL ?? \"http://localhost:5101\";\r\n\r\nconst CONVERSION_STATUS = Object.freeze({\r\n STARTED: \"conversion_started\",\r\n DOWNLOAD: \"download\",\r\n CONVERT: \"convert\",\r\n UPLOAD: \"upload\",\r\n CLEAN_UP: \"clean_up\",\r\n FAILED: \"failed\",\r\n FINISHED: \"finished\",\r\n});\r\n\r\n// All possible status values:\r\n// - local client-only phases: \"idle\", \"creating\", \"uploading\"\r\n// - plus all statuses from the backend (CONVERSION_STATUS values)\r\ntype ConversionStatus =\r\n | \"idle\"\r\n | \"creating\"\r\n | \"uploading\"\r\n | (typeof CONVERSION_STATUS)[keyof typeof CONVERSION_STATUS];\r\n\r\ntype CreatePointCloudResponse = {\r\n pointCloud: {\r\n id: string;\r\n name: string;\r\n };\r\n upload: {\r\n uploadUrl: string;\r\n };\r\n};\r\n\r\ntype StartConversionResponse = {\r\n jobId: string;\r\n};\r\n\r\ntype UploadPointCloudPageProps = {\r\n onGoBackButtonClick?: () => void;\r\n};\r\n\r\nexport default function UploadPointCloudPage({\r\n onGoBackButtonClick,\r\n}: UploadPointCloudPageProps) {\r\n const [name, setName] = React.useState(\"\");\r\n const [file, setFile] = React.useState<File | null>(null);\r\n\r\n const [progress, setProgress] = React.useState(0);\r\n const [status, setStatus] = React.useState<ConversionStatus>(\"idle\");\r\n const [pointCloudId, setPointCloudId] = React.useState<string | null>(null);\r\n const [jobId, setJobId] = React.useState<string | null>(null);\r\n const [logLines, setLogLines] = React.useState<string[]>([]);\r\n\r\n const esRef = React.useRef<EventSource | null>(null);\r\n\r\n const appendLog = React.useCallback((...parts: unknown[]) => {\r\n const line = parts\r\n .map((p) => (typeof p === \"string\" ? p : JSON.stringify(p, null, 2)))\r\n .join(\" \");\r\n setLogLines((prev) => [...prev, line]);\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n return () => {\r\n if (esRef.current) {\r\n esRef.current.close();\r\n }\r\n };\r\n }, []);\r\n\r\n async function createPointCloud(\r\n name: string,\r\n ): Promise<CreatePointCloudResponse> {\r\n const res = await fetch(`${API_BASE}/point-cloud`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ name }),\r\n });\r\n\r\n if (!res.ok) {\r\n const msg = await res.text();\r\n throw new Error(`Create point-cloud failed: ${msg || res.status}`);\r\n }\r\n\r\n return res.json();\r\n }\r\n\r\n function uploadToPresignedUrl(\r\n url: string,\r\n file: File,\r\n onProgress: (pct: number) => void,\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const xhr = new XMLHttpRequest();\r\n xhr.open(\"PUT\", url, true);\r\n\r\n xhr.upload.onprogress = (evt) => {\r\n if (evt.lengthComputable) {\r\n const pct = Math.round((evt.loaded / evt.total) * 100);\r\n onProgress(pct);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status >= 200 && xhr.status < 300) resolve();\r\n else reject(new Error(`Upload failed with status ${xhr.status}`));\r\n };\r\n\r\n xhr.onerror = () => reject(new Error(\"Network error during upload\"));\r\n xhr.send(file);\r\n } catch (err) {\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n async function startConversion(\r\n pointCloudId: string,\r\n ): Promise<StartConversionResponse> {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(\r\n pointCloudId,\r\n )}/convert-to-potree`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ options: { sampling_method: \"poisson\" } }),\r\n },\r\n );\r\n\r\n if (!res.ok) {\r\n const msg = await res.text();\r\n throw new Error(`convert-to-potree failed: ${msg || res.status}`);\r\n }\r\n\r\n return res.json();\r\n }\r\n\r\n function subscribeToProgress(jobId: string) {\r\n if (!jobId) return;\r\n\r\n if (esRef.current) {\r\n esRef.current.close();\r\n }\r\n\r\n const es = new EventSource(\r\n `${API_BASE}/events/convert-progress/${encodeURIComponent(jobId)}`,\r\n );\r\n esRef.current = es;\r\n\r\n es.onopen = () => appendLog(\"🟢 SSE connection opened\");\r\n\r\n es.onerror = (event) => {\r\n appendLog(\"❌ SSE error:\", event);\r\n setStatus((prev) =>\r\n prev === CONVERSION_STATUS.FINISHED ? prev : CONVERSION_STATUS.FAILED,\r\n );\r\n };\r\n\r\n es.addEventListener(\"progress\", (event) => {\r\n try {\r\n const msgEvent = event as MessageEvent;\r\n const data = JSON.parse(msgEvent.data);\r\n\r\n appendLog(\r\n \"[progress]\",\r\n data.status ?? \"\",\r\n data.message ?? \"\",\r\n data.progress ?? \"\",\r\n );\r\n\r\n // If backend sends a status field matching our constants, use it\r\n if (\r\n data.status &&\r\n Object.values(CONVERSION_STATUS).includes(data.status)\r\n ) {\r\n setStatus(data.status as ConversionStatus);\r\n }\r\n\r\n if (typeof data.progress === \"number\") {\r\n setProgress(data.progress);\r\n }\r\n } catch (err) {\r\n appendLog(\"❌ Failed to parse progress event\", err);\r\n }\r\n });\r\n\r\n es.addEventListener(\"finished\", () => {\r\n appendLog(\"[finished] Conversion completed\");\r\n setStatus(CONVERSION_STATUS.FINISHED);\r\n setProgress(100);\r\n es.close();\r\n esRef.current = null;\r\n });\r\n\r\n es.addEventListener(\"failed\", () => {\r\n appendLog(\"[failed] Conversion failed\");\r\n setStatus(CONVERSION_STATUS.FAILED);\r\n es.close();\r\n esRef.current = null;\r\n });\r\n\r\n es.addEventListener(\"connected\", (event) => {\r\n const msgEvent = event as MessageEvent;\r\n appendLog(\"[connected]\", msgEvent.data);\r\n });\r\n\r\n es.onmessage = (event) => {\r\n appendLog(\"[message]\", event.data);\r\n };\r\n }\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!name.trim() || !file) {\r\n alert(\"Please provide a name and select a LAZ/LAS file.\");\r\n return;\r\n }\r\n\r\n setLogLines([]);\r\n setProgress(0);\r\n setPointCloudId(null);\r\n setJobId(null);\r\n setStatus(\"idle\");\r\n\r\n try {\r\n appendLog(\"🟦 1) Creating point cloud...\");\r\n setStatus(\"creating\");\r\n\r\n const { pointCloud, upload } = await createPointCloud(name.trim());\r\n appendLog(pointCloud);\r\n setPointCloudId(pointCloud.id);\r\n\r\n appendLog(\"🟦 2) Uploading to presigned URL...\");\r\n setStatus(\"uploading\");\r\n await uploadToPresignedUrl(upload.uploadUrl, file, (pct) =>\r\n setProgress(pct),\r\n );\r\n appendLog(\"✔ Upload finished\");\r\n\r\n appendLog(\"🟦 3) Starting conversion...\");\r\n // Mark that the conversion has started (using backend status constant)\r\n setStatus(CONVERSION_STATUS.STARTED);\r\n const conversion = await startConversion(pointCloud.id);\r\n appendLog(conversion);\r\n\r\n const jobId = conversion.jobId;\r\n setJobId(jobId);\r\n\r\n appendLog(\"🟦 4) Subscribing to SSE…\");\r\n subscribeToProgress(jobId);\r\n } catch (err) {\r\n const message =\r\n err instanceof Error ? err.message : \"Unknown upload error\";\r\n appendLog(\"🔥 ERROR:\", message);\r\n setStatus(CONVERSION_STATUS.FAILED);\r\n alert(message);\r\n }\r\n };\r\n\r\n const busy =\r\n status !== \"idle\" &&\r\n status !== CONVERSION_STATUS.FINISHED &&\r\n status !== CONVERSION_STATUS.FAILED;\r\n\r\n const statusLabel: string = (() => {\r\n switch (status) {\r\n case \"idle\":\r\n return \"Idle\";\r\n case \"creating\":\r\n return \"Creating point cloud…\";\r\n case \"uploading\":\r\n return \"Uploading LAZ…\";\r\n\r\n case CONVERSION_STATUS.STARTED:\r\n return \"Conversion started…\";\r\n case CONVERSION_STATUS.DOWNLOAD:\r\n return \"Downloading source file…\";\r\n case CONVERSION_STATUS.CONVERT:\r\n return \"Running Potree converter…\";\r\n case CONVERSION_STATUS.UPLOAD:\r\n return \"Uploading Potree output…\";\r\n case CONVERSION_STATUS.CLEAN_UP:\r\n return \"Cleaning up temporary files…\";\r\n case CONVERSION_STATUS.FINISHED:\r\n return \"Done 🎉\";\r\n case CONVERSION_STATUS.FAILED:\r\n return \"Error – see log\";\r\n default:\r\n return \"Unknown status\";\r\n }\r\n })();\r\n\r\n return (\r\n <div className=\"p-2 mt-16\">\r\n <div className=\"flex items-center justify-between gap-2 mb-4\">\r\n <div>\r\n <h1 className=\"text-2xl font-semibold tracking-tight\">\r\n Upload & Convert Point Cloud\r\n </h1>\r\n </div>\r\n\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n if (onGoBackButtonClick) onGoBackButtonClick();\r\n }}\r\n >\r\n ← Back to list\r\n </Button>\r\n </div>\r\n\r\n <div className=\"grid gap-4 md:grid-cols-[2fr,1.2fr]\">\r\n {/* Upload card */}\r\n <div className=\"rounded-md border bg-background p-4 space-y-4\">\r\n <div className=\"flex items-center justify-between gap-2 text-sm\">\r\n <span className=\"font-semibold\">Upload point cloud</span>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {statusLabel}\r\n </span>\r\n </div>\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-3 text-sm\">\r\n <div className=\"space-y-1\">\r\n <div className=\"text-xs font-medium\">Name</div>\r\n <Input\r\n placeholder=\"e.g. Campus north wing\"\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-1\">\r\n <div className=\"text-xs font-medium\">LAZ / LAS file</div>\r\n <Input\r\n type=\"file\"\r\n accept=\".laz,.las\"\r\n onChange={(e) => {\r\n const f = e.target.files?.[0] ?? null;\r\n setFile(f);\r\n }}\r\n />\r\n {file && (\r\n <div className=\"text-[11px] text-muted-foreground\">\r\n Selected: <span className=\"font-medium\">{file.name}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3\">\r\n <Button\r\n type=\"submit\"\r\n disabled={!name.trim() || !file || busy}\r\n size=\"sm\"\r\n >\r\n {busy ? \"Working...\" : \"Upload & Convert\"}\r\n </Button>\r\n\r\n <div className=\"flex flex-col text-[11px] text-muted-foreground\">\r\n <span>\r\n PointCloud ID:{\" \"}\r\n <code className=\"text-xs\">{pointCloudId ?? \"—\"}</code>\r\n </span>\r\n <span>\r\n Job ID: <code className=\"text-xs\">{jobId ?? \"—\"}</code>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-1\">\r\n <div className=\"flex items-center justify-between text-[11px] text-muted-foreground\">\r\n <span>Upload / conversion progress</span>\r\n <span>{progress}%</span>\r\n </div>\r\n <ProgressBar value={progress} />\r\n </div>\r\n </form>\r\n </div>\r\n\r\n {/* Log card */}\r\n <div className=\"rounded-md border bg-muted/20 p-3 flex flex-col gap-2\">\r\n <div className=\"flex items-center justify-between text-xs\">\r\n <h2 className=\"font-semibold uppercase tracking-wide\">\r\n Conversion log\r\n </h2>\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-6 px-2 text-[11px]\"\r\n onClick={() => setLogLines([])}\r\n >\r\n Clear\r\n </Button>\r\n </div>\r\n\r\n <ScrollArea className=\"h-[200px] rounded border bg-background\">\r\n <pre className=\"p-2 text-[11px] leading-snug whitespace-pre-wrap\">\r\n {logLines.length ? logLines.join(\"\\n\") : \"No activity yet.\"}\r\n </pre>\r\n </ScrollArea>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":["name","file","pointCloudId","jobId","_a"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.tsx"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// app/point-clouds/upload/page.tsx\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport { useSession } from \"next-auth/react\";\r\nimport { useOrganization } from \"../../../../../hooks/organizations/organizations\";\r\nimport { ProgressBar } from \"../../../map/src/tools/AddTools/AddFile/ProgressBar\";\r\nimport { Button, Input, ScrollArea } from '../../../../ui';\r\nimport { toast } from 'sonner'\r\n\r\nconst CONVERSION_STATUS = Object.freeze({\r\n STARTED: \"conversion_started\",\r\n DOWNLOAD: \"download\",\r\n CONVERT: \"convert\",\r\n UPLOAD: \"upload\",\r\n CLEAN_UP: \"clean_up\",\r\n FAILED: \"failed\",\r\n FINISHED: \"finished\",\r\n});\r\n\r\n// All possible status values:\r\n// - local client-only phases: \"idle\", \"creating\", \"uploading\"\r\n// - plus all statuses from the backend (CONVERSION_STATUS values)\r\ntype ConversionStatus =\r\n | \"idle\"\r\n | \"creating\"\r\n | \"uploading\"\r\n | (typeof CONVERSION_STATUS)[keyof typeof CONVERSION_STATUS];\r\n\r\ntype CreatePointCloudResponse = {\r\n pointCloud: {\r\n id: string;\r\n name: string;\r\n };\r\n upload: {\r\n uploadUrl: string;\r\n };\r\n};\r\n\r\ntype StartConversionResponse = {\r\n jobId: string;\r\n};\r\n\r\ntype UploadPointCloudPageProps = {\r\n onGoBackButtonClick?: () => void;\r\n pointcloudApiUrl?: string;\r\n};\r\n\r\nexport default function UploadPointCloudPage({\r\n onGoBackButtonClick,\r\n pointcloudApiUrl,\r\n}: UploadPointCloudPageProps) {\r\n const API_BASE = pointcloudApiUrl ?? 'http://localhost:5101'\r\n const { data: session } = useSession();\r\n const organizationId = session?.user?.organizationId ?? null;\r\n const { organization } = useOrganization(organizationId ? organizationId.toString() : null);\r\n\r\n const [name, setName] = React.useState(\"\");\r\n const [file, setFile] = React.useState<File | null>(null);\r\n const [uploadSuccess, setUploadSuccess] = React.useState(false);\r\n\r\n const [progress, setProgress] = React.useState(0);\r\n const [status, setStatus] = React.useState<ConversionStatus>(\"idle\");\r\n const [pointCloudId, setPointCloudId] = React.useState<string | null>(null);\r\n const [jobId, setJobId] = React.useState<string | null>(null);\r\n const [logLines, setLogLines] = React.useState<string[]>([]);\r\n\r\n const esRef = React.useRef<EventSource | null>(null);\r\n\r\n const appendLog = React.useCallback((...parts: unknown[]) => {\r\n const line = parts\r\n .map((p) => (typeof p === \"string\" ? p : JSON.stringify(p, null, 2)))\r\n .join(\" \");\r\n setLogLines((prev) => [...prev, line]);\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n return () => {\r\n if (esRef.current) {\r\n esRef.current.close();\r\n }\r\n };\r\n }, []);\r\n\r\n async function createPointCloud(\r\n name: string,\r\n ): Promise<CreatePointCloudResponse> {\r\n const res = await fetch(`${API_BASE}/point-cloud`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ name, organizationId, organizationName: organization?.name }),\r\n });\r\n\r\n if (!res.ok) {\r\n const msg = await res.text();\r\n throw new Error(`Create point-cloud failed: ${msg || res.status}`);\r\n }\r\n\r\n return res.json();\r\n }\r\n\r\n function uploadToPresignedUrl(\r\n url: string,\r\n file: File,\r\n onProgress: (pct: number) => void,\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const xhr = new XMLHttpRequest();\r\n xhr.open(\"PUT\", url, true);\r\n\r\n xhr.upload.onprogress = (evt) => {\r\n if (evt.lengthComputable) {\r\n const pct = Math.round((evt.loaded / evt.total) * 100);\r\n onProgress(pct);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status >= 200 && xhr.status < 300) resolve();\r\n else reject(new Error(`Upload failed with status ${xhr.status}`));\r\n };\r\n\r\n xhr.onerror = () => reject(new Error(\"Network error during upload\"));\r\n xhr.send(file);\r\n } catch (err) {\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n async function startConversion(\r\n pointCloudId: string,\r\n ): Promise<StartConversionResponse> {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(\r\n pointCloudId,\r\n )}/convert-to-potree`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ options: { sampling_method: \"poisson\" } }),\r\n },\r\n );\r\n\r\n if (!res.ok) {\r\n const msg = await res.text();\r\n throw new Error(`convert-to-potree failed: ${msg || res.status}`);\r\n }\r\n\r\n return res.json();\r\n }\r\n\r\n function subscribeToProgress(jobId: string) {\r\n if (!jobId) return;\r\n\r\n if (esRef.current) {\r\n esRef.current.close();\r\n }\r\n\r\n const es = new EventSource(\r\n `${API_BASE}/events/convert-progress/${encodeURIComponent(jobId)}`,\r\n );\r\n esRef.current = es;\r\n\r\n es.onopen = () => appendLog(\"🟢 SSE connection opened\");\r\n\r\n es.onerror = (event) => {\r\n appendLog(\"❌ SSE error:\", event);\r\n setStatus((prev) =>\r\n prev === CONVERSION_STATUS.FINISHED ? prev : CONVERSION_STATUS.FAILED,\r\n );\r\n };\r\n\r\n es.addEventListener(\"progress\", (event) => {\r\n try {\r\n const msgEvent = event as MessageEvent;\r\n const data = JSON.parse(msgEvent.data);\r\n\r\n appendLog(\r\n \"[progress]\",\r\n data.status ?? \"\",\r\n data.message ?? \"\",\r\n data.progress ?? \"\",\r\n );\r\n\r\n // If backend sends a status field matching our constants, use it\r\n if (\r\n data.status &&\r\n Object.values(CONVERSION_STATUS).includes(data.status)\r\n ) {\r\n setStatus(data.status as ConversionStatus);\r\n }\r\n\r\n if (typeof data.progress === \"number\") {\r\n setProgress(data.progress);\r\n }\r\n } catch (err) {\r\n appendLog(\"❌ Failed to parse progress event\", err);\r\n }\r\n });\r\n\r\n es.addEventListener(\"finished\", () => {\r\n appendLog(\"[finished] Conversion completed\");\r\n setStatus(CONVERSION_STATUS.FINISHED);\r\n setProgress(100);\r\n toast.success(\"Point cloud conversion completed\");\r\n es.close();\r\n esRef.current = null;\r\n });\r\n\r\n es.addEventListener(\"failed\", () => {\r\n appendLog(\"[failed] Conversion failed\");\r\n setStatus(CONVERSION_STATUS.FAILED);\r\n es.close();\r\n esRef.current = null;\r\n });\r\n\r\n es.addEventListener(\"connected\", (event) => {\r\n const msgEvent = event as MessageEvent;\r\n appendLog(\"[connected]\", msgEvent.data);\r\n });\r\n\r\n es.onmessage = (event) => {\r\n appendLog(\"[message]\", event.data);\r\n };\r\n }\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!name.trim() || !file) {\r\n alert(\"Please provide a name and select a LAZ/LAS file.\");\r\n return;\r\n }\r\n\r\n setLogLines([]);\r\n setProgress(0);\r\n setPointCloudId(null);\r\n setJobId(null);\r\n setStatus(\"idle\");\r\n setUploadSuccess(false);\r\n\r\n try {\r\n appendLog(\"🟦 1) Creating point cloud...\");\r\n setStatus(\"creating\");\r\n\r\n const { pointCloud, upload } = await createPointCloud(name.trim());\r\n appendLog(pointCloud);\r\n setPointCloudId(pointCloud.id);\r\n\r\n appendLog(\"🟦 2) Uploading to presigned URL...\");\r\n setStatus(\"uploading\");\r\n await uploadToPresignedUrl(upload.uploadUrl, file, (pct) =>\r\n setProgress(pct),\r\n );\r\n appendLog(\"✔ Upload finished\");\r\n setUploadSuccess(true);\r\n toast.success(\"LAZ file uploaded successfully\", { duration: 6000 });\r\n\r\n appendLog(\"🟦 3) Starting conversion...\");\r\n // Mark that the conversion has started (using backend status constant)\r\n setStatus(CONVERSION_STATUS.STARTED);\r\n const conversion = await startConversion(pointCloud.id);\r\n appendLog(conversion);\r\n\r\n const jobId = conversion.jobId;\r\n setJobId(jobId);\r\n\r\n appendLog(\"🟦 4) Subscribing to SSE…\");\r\n subscribeToProgress(jobId);\r\n } catch (err) {\r\n const message =\r\n err instanceof Error ? err.message : \"Unknown upload error\";\r\n appendLog(\"🔥 ERROR:\", message);\r\n setStatus(CONVERSION_STATUS.FAILED);\r\n alert(message);\r\n }\r\n };\r\n\r\n const busy =\r\n status !== \"idle\" &&\r\n status !== CONVERSION_STATUS.FINISHED &&\r\n status !== CONVERSION_STATUS.FAILED;\r\n\r\n const statusLabel: string = (() => {\r\n switch (status) {\r\n case \"idle\":\r\n return \"Idle\";\r\n case \"creating\":\r\n return \"Creating point cloud…\";\r\n case \"uploading\":\r\n return \"Uploading LAZ…\";\r\n\r\n case CONVERSION_STATUS.STARTED:\r\n return \"Conversion started…\";\r\n case CONVERSION_STATUS.DOWNLOAD:\r\n return \"Downloading source file…\";\r\n case CONVERSION_STATUS.CONVERT:\r\n return \"Running Potree converter…\";\r\n case CONVERSION_STATUS.UPLOAD:\r\n return \"Uploading Potree output…\";\r\n case CONVERSION_STATUS.CLEAN_UP:\r\n return \"Cleaning up temporary files…\";\r\n case CONVERSION_STATUS.FINISHED:\r\n return \"Done 🎉\";\r\n case CONVERSION_STATUS.FAILED:\r\n return \"Error – see log\";\r\n default:\r\n return \"Unknown status\";\r\n }\r\n })();\r\n\r\n return (\r\n <div className=\"p-2 mt-16\">\r\n <div className=\"flex items-center justify-between gap-2 mb-4\">\r\n <div>\r\n <h1 className=\"text-2xl font-semibold tracking-tight\">\r\n Upload & Convert Point Cloud\r\n </h1>\r\n </div>\r\n\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n if (onGoBackButtonClick) onGoBackButtonClick();\r\n }}\r\n >\r\n ← Back to list\r\n </Button>\r\n </div>\r\n\r\n <div className=\"grid gap-4 md:grid-cols-[2fr,1.2fr]\">\r\n {/* Upload card */}\r\n <div className=\"rounded-md border bg-background p-4 space-y-4\">\r\n <div className=\"flex items-center justify-between gap-2 text-sm\">\r\n <span className=\"font-semibold\">Upload point cloud</span>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {statusLabel}\r\n </span>\r\n </div>\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-3 text-sm\">\r\n <div className=\"space-y-1\">\r\n <div className=\"text-xs font-medium\">Name</div>\r\n <Input\r\n placeholder=\"e.g. Campus north wing\"\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-1\">\r\n <div className=\"text-xs font-medium\">LAZ / LAS file</div>\r\n <Input\r\n type=\"file\"\r\n accept=\".laz,.las\"\r\n onChange={(e) => {\r\n const f = e.target.files?.[0] ?? null;\r\n setFile(f);\r\n }}\r\n />\r\n {file && (\r\n <div className=\"text-[11px] text-muted-foreground\">\r\n Selected: <span className=\"font-medium\">{file.name}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3\">\r\n <Button\r\n type=\"submit\"\r\n disabled={!name.trim() || !file || busy}\r\n size=\"sm\"\r\n >\r\n {busy ? \"Working...\" : \"Upload & Convert\"}\r\n </Button>\r\n\r\n <div className=\"flex flex-col text-[11px] text-muted-foreground\">\r\n <span>\r\n PointCloud ID:{\" \"}\r\n <code className=\"text-xs\">{pointCloudId ?? \"—\"}</code>\r\n </span>\r\n <span>\r\n Job ID: <code className=\"text-xs\">{jobId ?? \"—\"}</code>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-1\">\r\n <div className=\"flex items-center justify-between text-[11px] text-muted-foreground\">\r\n <span>Upload / conversion progress</span>\r\n <span>{progress}%</span>\r\n </div>\r\n <ProgressBar value={progress} />\r\n </div>\r\n\r\n {uploadSuccess && (\r\n <div className=\"rounded-md bg-green-50 border border-green-200 px-3 py-2 text-sm text-green-800 font-medium\">\r\n ✔ LAZ file uploaded successfully — conversion in progress\r\n </div>\r\n )}\r\n </form>\r\n </div>\r\n\r\n {/* Log card */}\r\n <div className=\"rounded-md border bg-muted/20 p-3 flex flex-col gap-2\">\r\n <div className=\"flex items-center justify-between text-xs\">\r\n <h2 className=\"font-semibold uppercase tracking-wide\">\r\n Conversion log\r\n </h2>\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-6 px-2 text-[11px]\"\r\n onClick={() => setLogLines([])}\r\n >\r\n Clear\r\n </Button>\r\n </div>\r\n\r\n <ScrollArea className=\"h-[200px] rounded border bg-background\">\r\n <pre className=\"p-2 text-[11px] leading-snug whitespace-pre-wrap\">\r\n {logLines.length ? logLines.join(\"\\n\") : \"No activity yet.\"}\r\n </pre>\r\n </ScrollArea>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":["name","file","pointCloudId","jobId","_a","_b"]}
@@ -1,3 +1,7 @@
1
1
  import * as React from 'react';
2
- export declare function PointCloudSidebar(): React.JSX.Element;
2
+ import type { Organization } from '../../../../../types/dbTypes';
3
+ export declare function PointCloudSidebar({ pointcloudApiUrl, organization }: {
4
+ pointcloudApiUrl?: string;
5
+ organization?: Organization;
6
+ }): React.JSX.Element;
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,wBAAgB,iBAAiB,sBAuBhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAEhE,wBAAgB,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,YAAY,EAAE,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,qBAwB/H"}
@@ -6,7 +6,7 @@ import { PointCloudContext, MenusContext } from "../../../../../store";
6
6
  import { FileTab } from "./src/FileTab";
7
7
  import { SettingsTab } from "./src/SettingsTab";
8
8
  import { InfoSidebarContainer } from "../../../../../components/ui/InfoSidebar/Container";
9
- function PointCloudSidebar() {
9
+ function PointCloudSidebar({ pointcloudApiUrl, organization }) {
10
10
  const { state: pointCloudState } = React.useContext(PointCloudContext);
11
11
  const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext);
12
12
  const { selectedTab } = menusState.menus;
@@ -16,6 +16,7 @@ function PointCloudSidebar() {
16
16
  return /* @__PURE__ */ jsxs(
17
17
  InfoSidebarContainer,
18
18
  {
19
+ organization,
19
20
  tabSelector: /* @__PURE__ */ jsx(
20
21
  TabSelector,
21
22
  {
@@ -24,7 +25,7 @@ function PointCloudSidebar() {
24
25
  }
25
26
  ),
26
27
  children: [
27
- selectedTab === "file" && /* @__PURE__ */ jsx(FileTab, {}),
28
+ selectedTab === "file" && /* @__PURE__ */ jsx(FileTab, { pointcloudApiUrl }),
28
29
  selectedTab === "settings" && /* @__PURE__ */ jsx(SettingsTab, {})
29
30
  ]
30
31
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/index.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\nimport { InfoSidebar } from '../../../../../components/ui/InfoSidebar'\r\nimport { TabSelector } from './TabSelector'\r\nimport { PointCloudContext, MenusContext } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\n\r\nimport { SettingsTab } from './src/SettingsTab'\r\nimport { InfoSidebarContainer } from '../../../../../components/ui/InfoSidebar/Container'\r\n\r\nexport function PointCloudSidebar() {\r\n const { state: pointCloudState } = React.useContext(PointCloudContext)\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { selectedTab } = menusState.menus\r\n\r\n const handleTabChange = (selectedTab: SidebarTabType) => {\r\n menusDispatch({ type: 'SET_SIDEBAR_SELECTED_TAB', payload: { selectedTab } })\r\n }\r\n\r\n return (\r\n <InfoSidebarContainer\r\n tabSelector={\r\n <TabSelector\r\n activeTab={selectedTab}\r\n onTabChangeAction={handleTabChange}\r\n />\r\n }\r\n >\r\n {selectedTab === 'file' && <FileTab />}\r\n {/* {selectedTab === 'layers' && <PointCloudLayersTab />}*/}\r\n {selectedTab === 'settings' && <SettingsTab />} \r\n </InfoSidebarContainer>\r\n )\r\n}"],"mappings":";AAyBI,SAEI,KAFJ;AApBJ,YAAY,WAAW;AAEvB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,oBAAoB;AAEhD,SAAS,eAAe;AAExB,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AAE9B,SAAS,oBAAoB;AAClC,QAAM,EAAE,OAAO,gBAAgB,IAAI,MAAM,WAAW,iBAAiB;AACrE,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,YAAY,IAAI,WAAW;AAEnC,QAAM,kBAAkB,CAACA,iBAAgC;AACvD,kBAAc,EAAE,MAAM,4BAA4B,SAAS,EAAE,aAAAA,aAAY,EAAE,CAAC;AAAA,EAC9E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,mBAAmB;AAAA;AAAA,MACrB;AAAA,MAGD;AAAA,wBAAgB,UAAU,oBAAC,WAAQ;AAAA,QAEnC,gBAAgB,cAAc,oBAAC,eAAY;AAAA;AAAA;AAAA,EAC9C;AAEJ;","names":["selectedTab"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/index.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\nimport { InfoSidebar } from '../../../../../components/ui/InfoSidebar'\r\nimport { TabSelector } from './TabSelector'\r\nimport { PointCloudContext, MenusContext } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\n\r\nimport { SettingsTab } from './src/SettingsTab'\r\nimport { InfoSidebarContainer } from '../../../../../components/ui/InfoSidebar/Container'\r\nimport type { Organization } from '../../../../../types/dbTypes'\r\n\r\nexport function PointCloudSidebar({ pointcloudApiUrl, organization }: { pointcloudApiUrl?: string; organization?: Organization }) {\r\n const { state: pointCloudState } = React.useContext(PointCloudContext)\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { selectedTab } = menusState.menus\r\n\r\n const handleTabChange = (selectedTab: SidebarTabType) => {\r\n menusDispatch({ type: 'SET_SIDEBAR_SELECTED_TAB', payload: { selectedTab } })\r\n }\r\n\r\n return (\r\n <InfoSidebarContainer\r\n organization={organization}\r\n tabSelector={\r\n <TabSelector\r\n activeTab={selectedTab}\r\n onTabChangeAction={handleTabChange}\r\n />\r\n }\r\n >\r\n {selectedTab === 'file' && <FileTab pointcloudApiUrl={pointcloudApiUrl} />}\r\n {/* {selectedTab === 'layers' && <PointCloudLayersTab />}*/}\r\n {selectedTab === 'settings' && <SettingsTab />} \r\n </InfoSidebarContainer>\r\n )\r\n}"],"mappings":";AA0BI,SAGI,KAHJ;AArBJ,YAAY,WAAW;AAEvB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,oBAAoB;AAEhD,SAAS,eAAe;AAExB,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AAG9B,SAAS,kBAAkB,EAAE,kBAAkB,aAAa,GAA+D;AAChI,QAAM,EAAE,OAAO,gBAAgB,IAAI,MAAM,WAAW,iBAAiB;AACrE,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,YAAY,IAAI,WAAW;AAEnC,QAAM,kBAAkB,CAACA,iBAAgC;AACvD,kBAAc,EAAE,MAAM,4BAA4B,SAAS,EAAE,aAAAA,aAAY,EAAE,CAAC;AAAA,EAC9E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,mBAAmB;AAAA;AAAA,MACrB;AAAA,MAGD;AAAA,wBAAgB,UAAU,oBAAC,WAAQ,kBAAoC;AAAA,QAEvE,gBAAgB,cAAc,oBAAC,eAAY;AAAA;AAAA;AAAA,EAC9C;AAEJ;","names":["selectedTab"]}
@@ -1,3 +1,5 @@
1
1
  import * as React from 'react';
2
- export declare function FileTab(): React.JSX.Element;
2
+ export declare function FileTab({ pointcloudApiUrl }: {
3
+ pointcloudApiUrl?: string;
4
+ }): React.JSX.Element;
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,wBAAgB,OAAO,sBAiCtB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,wBAAgB,OAAO,CAAC,EAAE,gBAAgB,EAAE,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,qBAiC1E"}
@@ -6,7 +6,7 @@ import { PointCloudsSection } from "./src/PointCloudSection";
6
6
  import { BuildingsContext } from "../../../../../../../store";
7
7
  import { useSearchParams } from "next/navigation";
8
8
  import { useFilesByBuildingId } from "../../../../../../../hooks/files/files";
9
- function FileTab() {
9
+ function FileTab({ pointcloudApiUrl }) {
10
10
  var _a;
11
11
  const { state: buildingState } = React.useContext(BuildingsContext);
12
12
  const { building } = buildingState.buildings;
@@ -25,7 +25,7 @@ function FileTab() {
25
25
  }
26
26
  });
27
27
  return /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col space-y-6 h-full py-4 overflow-hidden", children: [
28
- /* @__PURE__ */ jsx(PointCloudsSection, { files: pointCloudFiles }),
28
+ /* @__PURE__ */ jsx(PointCloudsSection, { files: pointCloudFiles, pointcloudApiUrl }),
29
29
  /* @__PURE__ */ jsx(FilesSection, { files: nonPointCloudFiles })
30
30
  ] });
31
31
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.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\nimport { FilesSection } from './src/FilesSection'\r\nimport { PointCloudsSection } from './src/PointCloudSection'\r\nimport { BuildingsContext } from '../../../../../../../store'\r\nimport { useSearchParams } from 'next/navigation'\r\nimport { useFilesByBuildingId } from '../../../../../../../hooks/files/files'\r\nimport { DbFile } from '../../../../../../../types/dbTypes'\r\n\r\nexport function FileTab() {\r\n const { state: buildingState } = React.useContext(BuildingsContext)\r\n const { building } = buildingState.buildings\r\n\r\n const urlBuildingId = useSearchParams().get('buildingId')\r\n // Resolve from the store building, else the URL param; undefined if neither is\r\n // ready yet (e.g. mid viewer-switch) — the hook handles undefined → no files.\r\n const buildingId = building?.id ?? (urlBuildingId ? Number(urlBuildingId) : undefined)\r\n\r\n const filesData: DbFile[] = useFilesByBuildingId(buildingId).files || []\r\n\r\n const pointCloudFiles: DbFile[] = []\r\n const nonPointCloudFiles: DbFile[] = []\r\n\r\n // single .map pass to populate both arrays\r\n filesData.map((file) => {\r\n const {extension, type} = file\r\n // const isPointCloud = extension.toLowerCase() === 'laz' || extension.toLowerCase() === 'las'\r\n const isPointCloud = type?.toLowerCase() === 'point-cloud-file'\r\n\r\n if (isPointCloud) {\r\n pointCloudFiles.push(file)\r\n } else {\r\n nonPointCloudFiles.push(file)\r\n }\r\n })\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-6 h-full py-4 overflow-hidden\">\r\n <PointCloudsSection files={pointCloudFiles} />\r\n <FilesSection files={nonPointCloudFiles} />\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAyCI,SACE,KADF;AApCJ,YAAY,WAAW;AACvB,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AAG9B,SAAS,UAAU;AAb1B;AAcE,QAAM,EAAE,OAAO,cAAc,IAAI,MAAM,WAAW,gBAAgB;AAClE,QAAM,EAAE,SAAS,IAAI,cAAc;AAEnC,QAAM,gBAAgB,gBAAgB,EAAE,IAAI,YAAY;AAGxD,QAAM,cAAa,0CAAU,OAAV,YAAiB,gBAAgB,OAAO,aAAa,IAAI;AAE5E,QAAM,YAAsB,qBAAqB,UAAU,EAAE,SAAS,CAAC;AAEvE,QAAM,kBAA4B,CAAC;AACnC,QAAM,qBAA+B,CAAC;AAGtC,YAAU,IAAI,CAAC,SAAS;AACtB,UAAM,EAAC,WAAW,KAAI,IAAI;AAE1B,UAAM,gBAAe,6BAAM,mBAAkB;AAE7C,QAAI,cAAc;AAChB,sBAAgB,KAAK,IAAI;AAAA,IAC3B,OAAO;AACL,yBAAmB,KAAK,IAAI;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,SACE,qBAAC,SAAI,WAAU,8DACb;AAAA,wBAAC,sBAAmB,OAAO,iBAAiB;AAAA,IAC5C,oBAAC,gBAAa,OAAO,oBAAoB;AAAA,KAC3C;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.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\nimport { FilesSection } from './src/FilesSection'\r\nimport { PointCloudsSection } from './src/PointCloudSection'\r\nimport { BuildingsContext } from '../../../../../../../store'\r\nimport { useSearchParams } from 'next/navigation'\r\nimport { useFilesByBuildingId } from '../../../../../../../hooks/files/files'\r\nimport { DbFile } from '../../../../../../../types/dbTypes'\r\n\r\nexport function FileTab({ pointcloudApiUrl }: { pointcloudApiUrl?: string }) {\r\n const { state: buildingState } = React.useContext(BuildingsContext)\r\n const { building } = buildingState.buildings\r\n\r\n const urlBuildingId = useSearchParams().get('buildingId')\r\n // Resolve from the store building, else the URL param; undefined if neither is\r\n // ready yet (e.g. mid viewer-switch) — the hook handles undefined → no files.\r\n const buildingId = building?.id ?? (urlBuildingId ? Number(urlBuildingId) : undefined)\r\n\r\n const filesData: DbFile[] = useFilesByBuildingId(buildingId).files || []\r\n\r\n const pointCloudFiles: DbFile[] = []\r\n const nonPointCloudFiles: DbFile[] = []\r\n\r\n // single .map pass to populate both arrays\r\n filesData.map((file) => {\r\n const {extension, type} = file\r\n // const isPointCloud = extension.toLowerCase() === 'laz' || extension.toLowerCase() === 'las'\r\n const isPointCloud = type?.toLowerCase() === 'point-cloud-file'\r\n\r\n if (isPointCloud) {\r\n pointCloudFiles.push(file)\r\n } else {\r\n nonPointCloudFiles.push(file)\r\n }\r\n })\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-6 h-full py-4 overflow-hidden\">\r\n <PointCloudsSection files={pointCloudFiles} pointcloudApiUrl={pointcloudApiUrl} />\r\n <FilesSection files={nonPointCloudFiles} />\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAyCI,SACE,KADF;AApCJ,YAAY,WAAW;AACvB,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AAG9B,SAAS,QAAQ,EAAE,iBAAiB,GAAkC;AAb7E;AAcE,QAAM,EAAE,OAAO,cAAc,IAAI,MAAM,WAAW,gBAAgB;AAClE,QAAM,EAAE,SAAS,IAAI,cAAc;AAEnC,QAAM,gBAAgB,gBAAgB,EAAE,IAAI,YAAY;AAGxD,QAAM,cAAa,0CAAU,OAAV,YAAiB,gBAAgB,OAAO,aAAa,IAAI;AAE5E,QAAM,YAAsB,qBAAqB,UAAU,EAAE,SAAS,CAAC;AAEvE,QAAM,kBAA4B,CAAC;AACnC,QAAM,qBAA+B,CAAC;AAGtC,YAAU,IAAI,CAAC,SAAS;AACtB,UAAM,EAAC,WAAW,KAAI,IAAI;AAE1B,UAAM,gBAAe,6BAAM,mBAAkB;AAE7C,QAAI,cAAc;AAChB,sBAAgB,KAAK,IAAI;AAAA,IAC3B,OAAO;AACL,yBAAmB,KAAK,IAAI;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,SACE,qBAAC,SAAI,WAAU,8DACb;AAAA,wBAAC,sBAAmB,OAAO,iBAAiB,kBAAoC;AAAA,IAChF,oBAAC,gBAAa,OAAO,oBAAoB;AAAA,KAC3C;AAEJ;","names":[]}
@@ -2,7 +2,8 @@ import * as React from 'react';
2
2
  import { DbFile } from '../../../../../../../../types/dbTypes';
3
3
  interface PointCloudsSectionProps {
4
4
  files: DbFile[];
5
+ pointcloudApiUrl?: string;
5
6
  }
6
- export declare function PointCloudsSection({ files }: PointCloudsSectionProps): React.JSX.Element;
7
+ export declare function PointCloudsSection({ files, pointcloudApiUrl }: PointCloudsSectionProps): React.JSX.Element;
7
8
  export {};
8
9
  //# sourceMappingURL=PointCloudSection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointCloudSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAA;AAqB9D,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA0YpE"}
1
+ {"version":3,"file":"PointCloudSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAA;AAoB9D,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,uBAAuB,qBAqYtF"}
@@ -19,7 +19,6 @@ var __spreadValues = (a, b) => {
19
19
  };
20
20
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
21
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
- var _a;
23
22
  import * as React from "react";
24
23
  import * as LR from "lucide-react";
25
24
  import { useTranslations } from "next-intl";
@@ -29,16 +28,12 @@ import { FileItemComponent } from "../../../../../../../ui/FilesManager/src/File
29
28
  import { useFileActions } from "../../../../../../../ui/FilesManager/src/useFileActions";
30
29
  import ConfirmDialog from "../../../../../../../ConfirmDialog";
31
30
  import { Button } from "../../../../../../../ui/Button";
32
- import { useOrganization } from "../../../../../../../../hooks/organizations/organizations";
33
31
  import { PointCloudContext } from "../../../../../../../../store";
34
- const API_BASE = (_a = process.env.NEXT_PUBLIC_POINTCLOUD_API_URL) != null ? _a : "http://localhost:5101";
35
32
  const POINT_CLOUD_OPTIONS = ["view", "delete", "info"];
36
- function PointCloudsSection({ files }) {
37
- var _a2, _b;
33
+ function PointCloudsSection({ files, pointcloudApiUrl }) {
38
34
  const t = useTranslations("PointCloudManagement");
35
+ const API_BASE = pointcloudApiUrl != null ? pointcloudApiUrl : "http://localhost:5101";
39
36
  const { data: session } = useSession();
40
- const organizationId = (_b = (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.organizationId) != null ? _b : null;
41
- const { organization } = useOrganization(organizationId ? organizationId.toString() : null);
42
37
  const { dispatch: pointCloudDispatch } = React.useContext(PointCloudContext);
43
38
  const [pointcloudsFiles, setPointcloudsFiles] = React.useState(
44
39
  () => files.map((f) => __spreadProps(__spreadValues({}, f), { isVisible: false }))
@@ -47,17 +42,17 @@ function PointCloudsSection({ files }) {
47
42
  const autoLoadedRef = React.useRef(false);
48
43
  const fileSyncKey = files.map(
49
44
  (file) => {
50
- var _a3;
51
- return `${file.id}:${file.name}:${Boolean(file.pointCloudUploaded)}:${Boolean(file.pointCloudPotreeConverted)}:${file.uploadedAt}:${(_a3 = file.potreeMetadataFileKey) != null ? _a3 : ""}`;
45
+ var _a;
46
+ return `${file.id}:${file.name}:${Boolean(file.pointCloudUploaded)}:${Boolean(file.pointCloudPotreeConverted)}:${file.uploadedAt}:${(_a = file.potreeMetadataFileKey) != null ? _a : ""}`;
52
47
  }
53
48
  ).join("|");
54
49
  React.useEffect(() => {
55
50
  setPointcloudsFiles((prev) => {
56
51
  const prevMap = new Map(prev.map((f) => [String(f.id), f]));
57
52
  return files.map((f) => {
58
- var _a3, _b2;
53
+ var _a, _b;
59
54
  return __spreadProps(__spreadValues({}, f), {
60
- isVisible: (_b2 = (_a3 = prevMap.get(String(f.id))) == null ? void 0 : _a3.isVisible) != null ? _b2 : false
55
+ isVisible: (_b = (_a = prevMap.get(String(f.id))) == null ? void 0 : _a.isVisible) != null ? _b : false
61
56
  });
62
57
  });
63
58
  });
@@ -134,15 +129,10 @@ function PointCloudsSection({ files }) {
134
129
  });
135
130
  }, [pointcloudsFiles]);
136
131
  async function createPointCloud(name, uploadedBy) {
137
- const res = await fetch(`${API_BASE}/point-cloud`, {
132
+ const res = await fetch("/api/point-cloud", {
138
133
  method: "POST",
139
134
  headers: { "Content-Type": "application/json" },
140
- body: JSON.stringify({
141
- name,
142
- uploadedBy,
143
- organizationName: organization == null ? void 0 : organization.name,
144
- organizationId
145
- })
135
+ body: JSON.stringify({ name, uploadedBy })
146
136
  });
147
137
  if (!res.ok) {
148
138
  const msg = await res.text();
@@ -245,7 +235,7 @@ function PointCloudsSection({ files }) {
245
235
  });
246
236
  }
247
237
  const handleFileUpload = async (file) => {
248
- var _a3;
238
+ var _a;
249
239
  if (!file) return;
250
240
  const originalFileName = file.name;
251
241
  const fileExt = originalFileName.toLowerCase();
@@ -263,7 +253,7 @@ function PointCloudsSection({ files }) {
263
253
  }
264
254
  try {
265
255
  console.log("Creating point cloud entry...");
266
- const userEmail = ((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.email) || null;
256
+ const userEmail = ((_a = session == null ? void 0 : session.user) == null ? void 0 : _a.email) || null;
267
257
  const { pointCloud, upload } = await createPointCloud(fileName, userEmail);
268
258
  console.log("Point cloud created:", pointCloud.id);
269
259
  console.log("Uploading file...");
@@ -287,8 +277,8 @@ function PointCloudsSection({ files }) {
287
277
  input.type = "file";
288
278
  input.accept = ".laz,.las";
289
279
  input.onchange = (e) => {
290
- var _a3;
291
- const file = (_a3 = e.target.files) == null ? void 0 : _a3[0];
280
+ var _a;
281
+ const file = (_a = e.target.files) == null ? void 0 : _a[0];
292
282
  if (file) {
293
283
  handleFileUpload(file);
294
284
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.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\nimport * as LR from 'lucide-react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { CollapsibleSection } from '../../../../../../../ui/CollapsibleSection'\r\nimport { FileItemComponent } from '../../../../../../../ui/FilesManager/src/FileItemComponent'\r\nimport { useFileActions } from '../../../../../../../ui/FilesManager/src/useFileActions'\r\nimport ConfirmDialog from '../../../../../../../ConfirmDialog'\r\nimport { Button } from '../../../../../../../ui/Button'\r\nimport { useOrganization } from '../../../../../../../../hooks/organizations/organizations'\r\nimport { DbFile } from '../../../../../../../../types/dbTypes'\r\nimport { PointCloudContext } from '../../../../../../../../store'\r\n\r\nconst API_BASE = process.env.NEXT_PUBLIC_POINTCLOUD_API_URL ?? 'http://localhost:5101'\r\n\r\ntype CreatePointCloudResponse = {\r\n pointCloud: {\r\n id: string\r\n name: string\r\n }\r\n upload: {\r\n uploadUrl: string\r\n }\r\n}\r\n\r\ntype StartConversionResponse = {\r\n jobId: string\r\n}\r\n\r\nconst POINT_CLOUD_OPTIONS: import('../../../../../../../../types/global').FileAction[] = ['view', 'delete', 'info']\r\n\r\ninterface PointCloudsSectionProps {\r\n files: DbFile[]\r\n}\r\n\r\nexport function PointCloudsSection({ files }: PointCloudsSectionProps) {\r\n // Translation\r\n const t = useTranslations('PointCloudManagement')\r\n\r\n // Get current user session\r\n const { data: session } = useSession()\r\n const organizationId = session?.user?.organizationId ?? null;\r\n const { organization } = useOrganization(organizationId ? organizationId.toString() : null);\r\n\r\n // Point cloud context for loading/unloading clouds in the viewer\r\n const { dispatch: pointCloudDispatch } = React.useContext(PointCloudContext)\r\n\r\n // State for point clouds — includes isVisible to track which are loaded in viewer\r\n const [pointcloudsFiles, setPointcloudsFiles] = React.useState<(DbFile & { isVisible?: boolean })[]>(\r\n () => files.map(f => ({ ...f, isVisible: false }))\r\n )\r\n const esRef = React.useRef<EventSource | null>(null)\r\n const autoLoadedRef = React.useRef(false)\r\n\r\n const fileSyncKey = files\r\n .map(\r\n (file) =>\r\n `${file.id}:${file.name}:${Boolean(file.pointCloudUploaded)}:${Boolean(file.pointCloudPotreeConverted)}:${file.uploadedAt}:${file.potreeMetadataFileKey ?? ''}`\r\n )\r\n .join('|')\r\n\r\n // Sync incoming files from props while preserving isVisible state for known files\r\n React.useEffect(() => {\r\n setPointcloudsFiles(prev => {\r\n const prevMap = new Map(prev.map(f => [String(f.id), f]))\r\n return files.map(f => ({\r\n ...f,\r\n isVisible: prevMap.get(String(f.id))?.isVisible ?? false,\r\n }))\r\n })\r\n }, [fileSyncKey])\r\n\r\n // Auto-load the most recently uploaded converted file on first access\r\n React.useEffect(() => {\r\n if (autoLoadedRef.current || files.length === 0) return\r\n\r\n const readyFiles = files.filter(f => Boolean(f.pointCloudPotreeConverted))\r\n if (readyFiles.length === 0) return\r\n\r\n const lastFile = readyFiles.reduce((latest, f) =>\r\n new Date(f.uploadedAt) > new Date(latest.uploadedAt) ? f : latest\r\n )\r\n\r\n autoLoadedRef.current = true\r\n pointCloudDispatch({ type: 'LOAD_POINT_CLOUD', payload: { id: String(lastFile.id) } })\r\n setPointcloudsFiles(prev =>\r\n prev.map(f => ({ ...f, isVisible: String(f.id) === String(lastFile.id) }))\r\n )\r\n }, [fileSyncKey, files, pointCloudDispatch])\r\n\r\n React.useEffect(() => {\r\n // Cleanup SSE on unmount\r\n return () => {\r\n if (esRef.current) {\r\n esRef.current.close()\r\n }\r\n }\r\n }, [])\r\n\r\n // Toggle a point cloud on/off in the viewer via context\r\n const handleView = React.useCallback((file: DbFile, newVisibility: boolean) => {\r\n const id = String(file.id)\r\n if (newVisibility) {\r\n pointCloudDispatch({ type: 'LOAD_POINT_CLOUD', payload: { id } })\r\n } else {\r\n pointCloudDispatch({ type: 'UNLOAD_POINT_CLOUD', payload: { id } })\r\n }\r\n }, [pointCloudDispatch])\r\n\r\n const handleDeleteFile = React.useCallback(async (file: DbFile) => {\r\n const res = await fetch(`${API_BASE}/point-cloud/${encodeURIComponent(String(file.id))}`, {\r\n method: 'DELETE',\r\n })\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(msg || `Delete failed (${res.status})`)\r\n }\r\n }, [])\r\n\r\n const handleConvert = React.useCallback(async (file: DbFile) => {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(String(file.id))}/convert-to-potree`,\r\n {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ options: { sampling_method: 'poisson' } }),\r\n }\r\n )\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(msg || `Conversion failed (${res.status})`)\r\n }\r\n\r\n const { jobId } = await res.json() as StartConversionResponse\r\n subscribeToProgress(jobId, file.id)\r\n }, [])\r\n\r\n const handleDeletePointCloud = React.useCallback((file: DbFile) => {\r\n pointCloudDispatch({ type: 'UNLOAD_POINT_CLOUD', payload: { id: String(file.id) } })\r\n }, [pointCloudDispatch])\r\n\r\n // Use the generic file actions hook\r\n const { handleAction, deleteDialog } = useFileActions({\r\n files: pointcloudsFiles,\r\n setFiles: setPointcloudsFiles as React.Dispatch<React.SetStateAction<(DbFile & { isVisible?: boolean })[]>>,\r\n buildingId: 0,\r\n handleDeleteFile,\r\n onView: handleView,\r\n onDelete: handleDeletePointCloud,\r\n })\r\n\r\n // Sort: visible (loaded) files at the top, preserving relative order within each group\r\n const sortedFiles = React.useMemo(() => {\r\n return [...pointcloudsFiles].sort((a, b) => {\r\n const aLoaded = a.isVisible !== false ? 1 : 0\r\n const bLoaded = b.isVisible !== false ? 1 : 0\r\n return bLoaded - aLoaded\r\n })\r\n }, [pointcloudsFiles])\r\n\r\n // Create point cloud entry\r\n async function createPointCloud(name: string, uploadedBy: string | null): Promise<CreatePointCloudResponse> {\r\n const res = await fetch(`${API_BASE}/point-cloud`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ \r\n name, \r\n uploadedBy,\r\n organizationName: organization?.name,\r\n organizationId: organizationId\r\n }),\r\n })\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(`Create point-cloud failed: ${msg || res.status}`)\r\n }\r\n\r\n return res.json()\r\n }\r\n\r\n // Upload to presigned URL\r\n function uploadToPresignedUrl(\r\n url: string,\r\n file: File,\r\n onProgress?: (pct: number) => void\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const xhr = new XMLHttpRequest()\r\n xhr.open('PUT', url, true)\r\n\r\n if (onProgress) {\r\n xhr.upload.onprogress = (evt) => {\r\n if (evt.lengthComputable) {\r\n const pct = Math.round((evt.loaded / evt.total) * 100)\r\n onProgress(pct)\r\n }\r\n }\r\n }\r\n\r\n xhr.onload = () => {\r\n if (xhr.status >= 200 && xhr.status < 300) resolve()\r\n else reject(new Error(`Upload failed with status ${xhr.status}`))\r\n }\r\n\r\n xhr.onerror = () => reject(new Error('Network error during upload'))\r\n xhr.send(file)\r\n } catch (err) {\r\n reject(err)\r\n }\r\n })\r\n }\r\n\r\n // Start conversion\r\n async function startConversion(pointCloudId: string): Promise<StartConversionResponse> {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(pointCloudId)}/convert-to-potree`,\r\n {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ options: { sampling_method: 'poisson' } }),\r\n }\r\n )\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(`convert-to-potree failed: ${msg || res.status}`)\r\n }\r\n\r\n return res.json()\r\n }\r\n\r\n // Subscribe to conversion progress\r\n function subscribeToProgress(jobId: string, pointCloudId: number) {\r\n if (!jobId) return\r\n\r\n if (esRef.current) {\r\n esRef.current.close()\r\n }\r\n\r\n const es = new EventSource(\r\n `${API_BASE}/events/convert-progress/${encodeURIComponent(jobId)}`\r\n )\r\n esRef.current = es\r\n\r\n es.onopen = () => console.log('SSE connection opened')\r\n\r\n es.onerror = (event) => {\r\n console.error('SSE error:', event)\r\n // Update to failed state\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 0 }\r\n : pc\r\n )\r\n )\r\n }\r\n\r\n es.addEventListener('progress', (event) => {\r\n try {\r\n const msgEvent = event as MessageEvent\r\n const data = JSON.parse(msgEvent.data)\r\n\r\n console.log('[progress]', data.status, data.message, data.progress)\r\n\r\n if (typeof data.progress === 'number') {\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, conversionProgress: data.progress }\r\n : pc\r\n )\r\n )\r\n }\r\n } catch (err) {\r\n console.error('Failed to parse progress event', err)\r\n }\r\n })\r\n\r\n es.addEventListener('finished', () => {\r\n console.log('[finished] Conversion completed')\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 100 }\r\n : pc\r\n )\r\n )\r\n es.close()\r\n esRef.current = null\r\n })\r\n\r\n es.addEventListener('failed', () => {\r\n console.log('[failed] Conversion failed')\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 0 }\r\n : pc\r\n )\r\n )\r\n es.close()\r\n esRef.current = null\r\n })\r\n }\r\n\r\n // Handle file upload\r\n const handleFileUpload = async (file: File) => {\r\n if (!file) return\r\n\r\n const originalFileName = file.name\r\n const fileExt = originalFileName.toLowerCase()\r\n const baseFileName = originalFileName.replace(/\\.(laz|las)$/i, '')\r\n\r\n // Validate file extension\r\n if (!fileExt.endsWith('.laz') && !fileExt.endsWith('.las')) {\r\n alert('Please select a LAZ or LAS file.')\r\n return\r\n }\r\n\r\n // Check for duplicate names and append (1), (2), etc.\r\n let fileName = baseFileName\r\n let counter = 1\r\n const existingNames = pointcloudsFiles.map((pc) => pc.name)\r\n \r\n while (existingNames.includes(fileName)) {\r\n fileName = `${baseFileName} (${counter})`\r\n counter++\r\n }\r\n\r\n try {\r\n console.log('Creating point cloud entry...')\r\n const userEmail = session?.user?.email || null\r\n const { pointCloud, upload } = await createPointCloud(fileName, userEmail)\r\n console.log('Point cloud created:', pointCloud.id)\r\n\r\n console.log('Uploading file...')\r\n await uploadToPresignedUrl(upload.uploadUrl, file, (pct) => {\r\n console.log(`Upload progress: ${pct}%`)\r\n })\r\n console.log('Upload complete!')\r\n\r\n console.log('Starting conversion...')\r\n const conversion = await startConversion(pointCloud.id)\r\n console.log('Conversion started:', conversion.jobId)\r\n\r\n // Subscribe to progress\r\n subscribeToProgress(conversion.jobId, Number(pointCloud.id))\r\n } catch (error) {\r\n console.error('Error uploading point cloud:', error)\r\n \r\n alert(\r\n error instanceof Error\r\n ? `Failed to upload: ${error.message}`\r\n : 'Failed to upload point cloud'\r\n )\r\n }\r\n }\r\n\r\n // Handle upload button click\r\n const handleUpload = () => {\r\n const input = document.createElement('input')\r\n input.type = 'file'\r\n input.accept = '.laz,.las'\r\n input.onchange = (e) => {\r\n const file = (e.target as HTMLInputElement).files?.[0]\r\n if (file) {\r\n handleFileUpload(file)\r\n }\r\n }\r\n input.click()\r\n }\r\n\r\n return (\r\n <>\r\n <CollapsibleSection\r\n title={t('title')}\r\n icon={LR.Grip}\r\n className=\"h-1/2 overflow-y-auto\"\r\n itemCount={pointcloudsFiles.length}\r\n onAddItem={handleUpload}\r\n addItemTitle={t('uploadTitle')}\r\n >\r\n <div className=\"space-y-1\">\r\n {sortedFiles.length === 0 ? (\r\n <div className=\"px-2 py-3 text-sm text-muted-foreground text-center\">\r\n {t('noPointClouds')}\r\n </div>\r\n ) : (\r\n sortedFiles.map((file) => (\r\n <div key={file.id} className=\"flex items-center gap-1\">\r\n <div className=\"flex-1 min-w-0\">\r\n <FileItemComponent\r\n file={file}\r\n onAction={handleAction}\r\n options={POINT_CLOUD_OPTIONS}\r\n />\r\n </div>\r\n {Boolean(file.pointCloudUploaded) && !Boolean(file.pointCloudPotreeConverted) && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-6 w-6 p-0\"\r\n onClick={() => void handleConvert(file)}\r\n title={t('convertTitle')}\r\n >\r\n <LR.RefreshCw className=\"h-3 w-3\" />\r\n </Button>\r\n )}\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n </CollapsibleSection>\r\n\r\n <ConfirmDialog\r\n isOpen={deleteDialog.isOpen}\r\n isDeleting={deleteDialog.isDeleting}\r\n onOpenChange={deleteDialog.onOpenChange}\r\n handleConfirm={deleteDialog.onConfirm}\r\n itemName={deleteDialog.itemName}\r\n dataType=\"file\"\r\n />\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b"]}
1
+ {"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.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\nimport * as LR from 'lucide-react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { CollapsibleSection } from '../../../../../../../ui/CollapsibleSection'\r\nimport { FileItemComponent } from '../../../../../../../ui/FilesManager/src/FileItemComponent'\r\nimport { useFileActions } from '../../../../../../../ui/FilesManager/src/useFileActions'\r\nimport ConfirmDialog from '../../../../../../../ConfirmDialog'\r\nimport { Button } from '../../../../../../../ui/Button'\r\nimport { DbFile } from '../../../../../../../../types/dbTypes'\r\nimport { PointCloudContext } from '../../../../../../../../store'\r\n// import { useAppConfigContext } from '../../../../../../../../store/AppConfig/context'\r\n\r\ntype CreatePointCloudResponse = {\r\n pointCloud: {\r\n id: string\r\n name: string\r\n }\r\n upload: {\r\n uploadUrl: string\r\n }\r\n}\r\n\r\ntype StartConversionResponse = {\r\n jobId: string\r\n}\r\n\r\nconst POINT_CLOUD_OPTIONS: import('../../../../../../../../types/global').FileAction[] = ['view', 'delete', 'info']\r\n\r\ninterface PointCloudsSectionProps {\r\n files: DbFile[]\r\n pointcloudApiUrl?: string\r\n}\r\n\r\nexport function PointCloudsSection({ files, pointcloudApiUrl }: PointCloudsSectionProps) {\r\n // Translation\r\n const t = useTranslations('PointCloudManagement')\r\n const API_BASE = pointcloudApiUrl ?? 'http://localhost:5101'\r\n\r\n // Get current user session (needed for uploadedBy)\r\n const { data: session } = useSession()\r\n\r\n // Point cloud context for loading/unloading clouds in the viewer\r\n const { dispatch: pointCloudDispatch } = React.useContext(PointCloudContext)\r\n\r\n // State for point clouds — includes isVisible to track which are loaded in viewer\r\n const [pointcloudsFiles, setPointcloudsFiles] = React.useState<(DbFile & { isVisible?: boolean })[]>(\r\n () => files.map(f => ({ ...f, isVisible: false }))\r\n )\r\n const esRef = React.useRef<EventSource | null>(null)\r\n const autoLoadedRef = React.useRef(false)\r\n\r\n const fileSyncKey = files\r\n .map(\r\n (file) =>\r\n `${file.id}:${file.name}:${Boolean(file.pointCloudUploaded)}:${Boolean(file.pointCloudPotreeConverted)}:${file.uploadedAt}:${file.potreeMetadataFileKey ?? ''}`\r\n )\r\n .join('|')\r\n\r\n // Sync incoming files from props while preserving isVisible state for known files\r\n React.useEffect(() => {\r\n setPointcloudsFiles(prev => {\r\n const prevMap = new Map(prev.map(f => [String(f.id), f]))\r\n return files.map(f => ({\r\n ...f,\r\n isVisible: prevMap.get(String(f.id))?.isVisible ?? false,\r\n }))\r\n })\r\n }, [fileSyncKey])\r\n\r\n // Auto-load the most recently uploaded converted file on first access\r\n React.useEffect(() => {\r\n if (autoLoadedRef.current || files.length === 0) return\r\n\r\n const readyFiles = files.filter(f => Boolean(f.pointCloudPotreeConverted))\r\n if (readyFiles.length === 0) return\r\n\r\n const lastFile = readyFiles.reduce((latest, f) =>\r\n new Date(f.uploadedAt) > new Date(latest.uploadedAt) ? f : latest\r\n )\r\n\r\n autoLoadedRef.current = true\r\n pointCloudDispatch({ type: 'LOAD_POINT_CLOUD', payload: { id: String(lastFile.id) } })\r\n setPointcloudsFiles(prev =>\r\n prev.map(f => ({ ...f, isVisible: String(f.id) === String(lastFile.id) }))\r\n )\r\n }, [fileSyncKey, files, pointCloudDispatch])\r\n\r\n React.useEffect(() => {\r\n // Cleanup SSE on unmount\r\n return () => {\r\n if (esRef.current) {\r\n esRef.current.close()\r\n }\r\n }\r\n }, [])\r\n\r\n // Toggle a point cloud on/off in the viewer via context\r\n const handleView = React.useCallback((file: DbFile, newVisibility: boolean) => {\r\n const id = String(file.id)\r\n if (newVisibility) {\r\n pointCloudDispatch({ type: 'LOAD_POINT_CLOUD', payload: { id } })\r\n } else {\r\n pointCloudDispatch({ type: 'UNLOAD_POINT_CLOUD', payload: { id } })\r\n }\r\n }, [pointCloudDispatch])\r\n\r\n const handleDeleteFile = React.useCallback(async (file: DbFile) => {\r\n const res = await fetch(`${API_BASE}/point-cloud/${encodeURIComponent(String(file.id))}`, {\r\n method: 'DELETE',\r\n })\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(msg || `Delete failed (${res.status})`)\r\n }\r\n }, [])\r\n\r\n const handleConvert = React.useCallback(async (file: DbFile) => {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(String(file.id))}/convert-to-potree`,\r\n {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ options: { sampling_method: 'poisson' } }),\r\n }\r\n )\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(msg || `Conversion failed (${res.status})`)\r\n }\r\n\r\n const { jobId } = await res.json() as StartConversionResponse\r\n subscribeToProgress(jobId, file.id)\r\n }, [])\r\n\r\n const handleDeletePointCloud = React.useCallback((file: DbFile) => {\r\n pointCloudDispatch({ type: 'UNLOAD_POINT_CLOUD', payload: { id: String(file.id) } })\r\n }, [pointCloudDispatch])\r\n\r\n // Use the generic file actions hook\r\n const { handleAction, deleteDialog } = useFileActions({\r\n files: pointcloudsFiles,\r\n setFiles: setPointcloudsFiles as React.Dispatch<React.SetStateAction<(DbFile & { isVisible?: boolean })[]>>,\r\n buildingId: 0,\r\n handleDeleteFile,\r\n onView: handleView,\r\n onDelete: handleDeletePointCloud,\r\n })\r\n\r\n // Sort: visible (loaded) files at the top, preserving relative order within each group\r\n const sortedFiles = React.useMemo(() => {\r\n return [...pointcloudsFiles].sort((a, b) => {\r\n const aLoaded = a.isVisible !== false ? 1 : 0\r\n const bLoaded = b.isVisible !== false ? 1 : 0\r\n return bLoaded - aLoaded\r\n })\r\n }, [pointcloudsFiles])\r\n\r\n // Create point cloud entry — routed through the CDT proxy so that\r\n // organizationId is injected server-side from the authenticated session.\r\n async function createPointCloud(name: string, uploadedBy: string | null): Promise<CreatePointCloudResponse> {\r\n const res = await fetch('/api/point-cloud', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ name, uploadedBy }),\r\n })\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(`Create point-cloud failed: ${msg || res.status}`)\r\n }\r\n\r\n return res.json()\r\n }\r\n\r\n // Upload to presigned URL\r\n function uploadToPresignedUrl(\r\n url: string,\r\n file: File,\r\n onProgress?: (pct: number) => void\r\n ): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const xhr = new XMLHttpRequest()\r\n xhr.open('PUT', url, true)\r\n\r\n if (onProgress) {\r\n xhr.upload.onprogress = (evt) => {\r\n if (evt.lengthComputable) {\r\n const pct = Math.round((evt.loaded / evt.total) * 100)\r\n onProgress(pct)\r\n }\r\n }\r\n }\r\n\r\n xhr.onload = () => {\r\n if (xhr.status >= 200 && xhr.status < 300) resolve()\r\n else reject(new Error(`Upload failed with status ${xhr.status}`))\r\n }\r\n\r\n xhr.onerror = () => reject(new Error('Network error during upload'))\r\n xhr.send(file)\r\n } catch (err) {\r\n reject(err)\r\n }\r\n })\r\n }\r\n\r\n // Start conversion\r\n async function startConversion(pointCloudId: string): Promise<StartConversionResponse> {\r\n const res = await fetch(\r\n `${API_BASE}/point-cloud/${encodeURIComponent(pointCloudId)}/convert-to-potree`,\r\n {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ options: { sampling_method: 'poisson' } }),\r\n }\r\n )\r\n\r\n if (!res.ok) {\r\n const msg = await res.text()\r\n throw new Error(`convert-to-potree failed: ${msg || res.status}`)\r\n }\r\n\r\n return res.json()\r\n }\r\n\r\n // Subscribe to conversion progress\r\n function subscribeToProgress(jobId: string, pointCloudId: number) {\r\n if (!jobId) return\r\n\r\n if (esRef.current) {\r\n esRef.current.close()\r\n }\r\n\r\n const es = new EventSource(\r\n `${API_BASE}/events/convert-progress/${encodeURIComponent(jobId)}`\r\n )\r\n esRef.current = es\r\n\r\n es.onopen = () => console.log('SSE connection opened')\r\n\r\n es.onerror = (event) => {\r\n console.error('SSE error:', event)\r\n // Update to failed state\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 0 }\r\n : pc\r\n )\r\n )\r\n }\r\n\r\n es.addEventListener('progress', (event) => {\r\n try {\r\n const msgEvent = event as MessageEvent\r\n const data = JSON.parse(msgEvent.data)\r\n\r\n console.log('[progress]', data.status, data.message, data.progress)\r\n\r\n if (typeof data.progress === 'number') {\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, conversionProgress: data.progress }\r\n : pc\r\n )\r\n )\r\n }\r\n } catch (err) {\r\n console.error('Failed to parse progress event', err)\r\n }\r\n })\r\n\r\n es.addEventListener('finished', () => {\r\n console.log('[finished] Conversion completed')\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 100 }\r\n : pc\r\n )\r\n )\r\n es.close()\r\n esRef.current = null\r\n })\r\n\r\n es.addEventListener('failed', () => {\r\n console.log('[failed] Conversion failed')\r\n setPointcloudsFiles((prev) =>\r\n prev.map((pc) =>\r\n Number(pc.id) === pointCloudId\r\n ? { ...pc, status: 'idle', conversionProgress: 0 }\r\n : pc\r\n )\r\n )\r\n es.close()\r\n esRef.current = null\r\n })\r\n }\r\n\r\n // Handle file upload\r\n const handleFileUpload = async (file: File) => {\r\n if (!file) return\r\n\r\n const originalFileName = file.name\r\n const fileExt = originalFileName.toLowerCase()\r\n const baseFileName = originalFileName.replace(/\\.(laz|las)$/i, '')\r\n\r\n // Validate file extension\r\n if (!fileExt.endsWith('.laz') && !fileExt.endsWith('.las')) {\r\n alert('Please select a LAZ or LAS file.')\r\n return\r\n }\r\n\r\n // Check for duplicate names and append (1), (2), etc.\r\n let fileName = baseFileName\r\n let counter = 1\r\n const existingNames = pointcloudsFiles.map((pc) => pc.name)\r\n \r\n while (existingNames.includes(fileName)) {\r\n fileName = `${baseFileName} (${counter})`\r\n counter++\r\n }\r\n\r\n try {\r\n console.log('Creating point cloud entry...')\r\n const userEmail = session?.user?.email || null\r\n const { pointCloud, upload } = await createPointCloud(fileName, userEmail)\r\n console.log('Point cloud created:', pointCloud.id)\r\n\r\n console.log('Uploading file...')\r\n await uploadToPresignedUrl(upload.uploadUrl, file, (pct) => {\r\n console.log(`Upload progress: ${pct}%`)\r\n })\r\n console.log('Upload complete!')\r\n\r\n console.log('Starting conversion...')\r\n const conversion = await startConversion(pointCloud.id)\r\n console.log('Conversion started:', conversion.jobId)\r\n\r\n // Subscribe to progress\r\n subscribeToProgress(conversion.jobId, Number(pointCloud.id))\r\n } catch (error) {\r\n console.error('Error uploading point cloud:', error)\r\n \r\n alert(\r\n error instanceof Error\r\n ? `Failed to upload: ${error.message}`\r\n : 'Failed to upload point cloud'\r\n )\r\n }\r\n }\r\n\r\n // Handle upload button click\r\n const handleUpload = () => {\r\n const input = document.createElement('input')\r\n input.type = 'file'\r\n input.accept = '.laz,.las'\r\n input.onchange = (e) => {\r\n const file = (e.target as HTMLInputElement).files?.[0]\r\n if (file) {\r\n handleFileUpload(file)\r\n }\r\n }\r\n input.click()\r\n }\r\n\r\n return (\r\n <>\r\n <CollapsibleSection\r\n title={t('title')}\r\n icon={LR.Grip}\r\n className=\"h-1/2 overflow-y-auto\"\r\n itemCount={pointcloudsFiles.length}\r\n onAddItem={handleUpload}\r\n addItemTitle={t('uploadTitle')}\r\n >\r\n <div className=\"space-y-1\">\r\n {sortedFiles.length === 0 ? (\r\n <div className=\"px-2 py-3 text-sm text-muted-foreground text-center\">\r\n {t('noPointClouds')}\r\n </div>\r\n ) : (\r\n sortedFiles.map((file) => (\r\n <div key={file.id} className=\"flex items-center gap-1\">\r\n <div className=\"flex-1 min-w-0\">\r\n <FileItemComponent\r\n file={file}\r\n onAction={handleAction}\r\n options={POINT_CLOUD_OPTIONS}\r\n />\r\n </div>\r\n {Boolean(file.pointCloudUploaded) && !Boolean(file.pointCloudPotreeConverted) && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-6 w-6 p-0\"\r\n onClick={() => void handleConvert(file)}\r\n title={t('convertTitle')}\r\n >\r\n <LR.RefreshCw className=\"h-3 w-3\" />\r\n </Button>\r\n )}\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n </CollapsibleSection>\r\n\r\n <ConfirmDialog\r\n isOpen={deleteDialog.isOpen}\r\n isDeleting={deleteDialog.isDeleting}\r\n onOpenChange={deleteDialog.onOpenChange}\r\n handleConfirm={deleteDialog.onConfirm}\r\n itemName={deleteDialog.itemName}\r\n dataType=\"file\"\r\n />\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+ export declare function useCaptureScreenshot(): () => Promise<string | null>;
2
+ //# sourceMappingURL=useCaptureScreenshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCaptureScreenshot.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/useCaptureScreenshot.ts"],"names":[],"mappings":"AAcA,wBAAgB,oBAAoB,IAAI,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkDnE"}