@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
@@ -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 React from "react";
24
23
  import { Button } from "../../../../ui/Button";
25
24
  import { Card, CardContent, CardHeader } from "../../../../ui/Card";
@@ -32,9 +31,10 @@ import { useFilesByBuildingId } from "../../../../../hooks/files/files";
32
31
  import { cn } from "../../../../../utils/utils";
33
32
  import { useSearchParams, useRouter } from "next/navigation";
34
33
  import { useBuilding, useBuildings } from "../../../../../hooks/buildings/buildings";
35
- const API_BASE = (_a = process.env.NEXT_PUBLIC_POINTCLOUD_API_URL) != null ? _a : "http://localhost:5101";
36
- function PointCloudLoadingState() {
34
+ import { toast } from "sonner";
35
+ function PointCloudLoadingState({ pointcloudApiUrl }) {
37
36
  const t = useTranslations("PointCloudLoadingState");
37
+ const API_BASE = pointcloudApiUrl != null ? pointcloudApiUrl : "http://localhost:5101";
38
38
  const { ability } = usePermissions();
39
39
  const { state: buildingState, dispatch: buildingDispatch } = React.useContext(BuildingsContext);
40
40
  const { building: storeBuilding } = buildingState.buildings;
@@ -57,8 +57,8 @@ function PointCloudLoadingState() {
57
57
  const [selectedBuilding, setSelectedBuilding] = React.useState(null);
58
58
  const { files, isLoading: filesLoading } = useFilesByBuildingId(building == null ? void 0 : building.id);
59
59
  const pointCloudFiles = React.useMemo(() => files.filter((file) => {
60
- var _a2;
61
- const ext = (_a2 = file.extension) == null ? void 0 : _a2.toLowerCase();
60
+ var _a;
61
+ const ext = (_a = file.extension) == null ? void 0 : _a.toLowerCase();
62
62
  if (!ext) return false;
63
63
  return ext === "laz" || ext === "las";
64
64
  }), [files]);
@@ -124,42 +124,6 @@ function PointCloudLoadingState() {
124
124
  setSearchResults([]);
125
125
  router.push(url.toString());
126
126
  };
127
- async function createPointCloud(name) {
128
- const res = await fetch(`${API_BASE}/point-cloud`, {
129
- method: "POST",
130
- headers: { "Content-Type": "application/json" },
131
- body: JSON.stringify({ name })
132
- });
133
- if (!res.ok) {
134
- const msg = await res.text();
135
- throw new Error(`Create point-cloud failed: ${msg || res.status}`);
136
- }
137
- return res.json();
138
- }
139
- function uploadToPresignedUrl(url, file, onProgress) {
140
- return new Promise((resolve, reject) => {
141
- try {
142
- const xhr = new XMLHttpRequest();
143
- xhr.open("PUT", url, true);
144
- if (onProgress) {
145
- xhr.upload.onprogress = (evt) => {
146
- if (evt.lengthComputable) {
147
- const pct = Math.round(evt.loaded / evt.total * 100);
148
- onProgress(pct);
149
- }
150
- };
151
- }
152
- xhr.onload = () => {
153
- if (xhr.status >= 200 && xhr.status < 300) resolve();
154
- else reject(new Error(`Upload failed with status ${xhr.status}`));
155
- };
156
- xhr.onerror = () => reject(new Error("Network error during upload"));
157
- xhr.send(file);
158
- } catch (err) {
159
- reject(err);
160
- }
161
- });
162
- }
163
127
  const handleFileChange = async (event) => {
164
128
  const files2 = event.target.files;
165
129
  if (!files2 || files2.length === 0) return;
@@ -170,16 +134,39 @@ function PointCloudLoadingState() {
170
134
  alert("Please select a LAZ or LAS file.");
171
135
  return;
172
136
  }
137
+ if (!(building == null ? void 0 : building.id)) {
138
+ alert("No building selected.");
139
+ return;
140
+ }
173
141
  setUploading(true);
174
142
  try {
175
- console.log("Creating point cloud entry...");
176
- const { pointCloud, upload } = await createPointCloud(fileName);
177
- console.log("Point cloud created:", pointCloud.id);
178
- console.log("Uploading file...");
179
- await uploadToPresignedUrl(upload.uploadUrl, file, (pct) => {
180
- console.log(`Upload progress: ${pct}%`);
143
+ const assetId = crypto.randomUUID();
144
+ const assetName = `${assetId}.laz`;
145
+ const presignedRes = await fetch(
146
+ `/api/presigned-url-upload?asset=${encodeURIComponent(assetName)}&bucket=pointclouds-demo`
147
+ );
148
+ if (!presignedRes.ok) throw new Error("Failed to get upload URL");
149
+ const { presignedUrl, key } = await presignedRes.json();
150
+ const uploadRes = await fetch(presignedUrl, {
151
+ method: "PUT",
152
+ body: file,
153
+ headers: { "Content-Type": "application/octet-stream" }
154
+ });
155
+ if (!uploadRes.ok) throw new Error(`Upload failed: ${uploadRes.status}`);
156
+ const fileRes = await fetch(`/api/files/building/${building.id}`, {
157
+ method: "POST",
158
+ headers: { "Content-Type": "application/json" },
159
+ body: JSON.stringify({
160
+ type: "point-cloud-file",
161
+ name: fileName,
162
+ assetId,
163
+ lazFileKey: key,
164
+ bucket: "pointclouds-demo",
165
+ extension: fileExt.endsWith(".las") ? "las" : "laz"
166
+ })
181
167
  });
182
- console.log("Upload complete!");
168
+ if (!fileRes.ok) throw new Error("Failed to create file record");
169
+ toast.success("LAZ file uploaded successfully", { duration: 6e3 });
183
170
  window.location.reload();
184
171
  } catch (error) {
185
172
  console.error("Error uploading point cloud:", error);
@@ -190,8 +177,8 @@ function PointCloudLoadingState() {
190
177
  }
191
178
  };
192
179
  const handleUploadClick = () => {
193
- var _a2;
194
- (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
180
+ var _a;
181
+ (_a = fileInputRef.current) == null ? void 0 : _a.click();
195
182
  };
196
183
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "absolute z-10 inset-0 bg-background/50 backdrop-blur-[1px] flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs(Card, { className: cn("w-[536px] pointer-events-auto flex flex-col justify-start items-center gap-2"), children: [
197
184
  /* @__PURE__ */ jsx(CardHeader, { className: "flex justify-center items-center", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 p-2 bg-card rounded-md shadow-sm border border-border flex justify-center items-center", children: currentState === "noBuilding" ? /* @__PURE__ */ jsx(LR.Building2, { className: cn("w-4 h-5 text-foreground", buildingsLoading && "animate-pulse"), strokeWidth: 2 }) : /* @__PURE__ */ jsx(LR.Grip, { className: cn("w-4 h-5 text-foreground", currentState === "opening" && "animate-pulse"), strokeWidth: 2 }) }) }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudLoadingState/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 React from 'react'\r\nimport { Button } from '../../../../ui/Button'\r\nimport { Card, CardContent, CardHeader } from '../../../../ui/Card'\r\nimport { Input } from '../../../../ui/Input'\r\nimport { LoadingSpinner } from '../../../../ui/LoadingSpinner'\r\nimport * as LR from 'lucide-react'\r\nimport { BuildingsContext, usePermissions } from '../../../../../store'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useFilesByBuildingId } from '../../../../../hooks/files/files'\r\nimport type { DbFile } from '../../../../../types/dbTypes'\r\nimport { cn } from '../../../../../utils/utils'\r\nimport { useSearchParams, useRouter } from 'next/navigation'\r\nimport { useBuilding, useBuildings } from '../../../../../hooks/buildings/buildings'\r\nimport { SquareArrowOutUpRight } from 'lucide-react'\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\nexport type pointCloudViewerState = 'opening' | 'loading' | 'ready' | 'error' | 'noPointCloudFiles' | 'noBuilding'\r\n\r\nexport function PointCloudLoadingState() {\r\n const t = useTranslations('PointCloudLoadingState')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: buildingState, dispatch: buildingDispatch } = React.useContext(BuildingsContext)\r\n const { building: storeBuilding } = buildingState.buildings\r\n\r\n const searchParams = useSearchParams()\r\n const buildingId = searchParams.get(\"buildingId\")\r\n const { building: urlBuilding, isLoading: buildingLoading, isError: buildingError } = useBuilding(buildingId ? Number(buildingId) : 0)\r\n const { buildings, isLoading: buildingsLoading } = useBuildings()\r\n\r\n // Determine the current building to use\r\n const building = storeBuilding || urlBuilding\r\n\r\n React.useEffect(() => {\r\n if (!storeBuilding && urlBuilding) {\r\n buildingDispatch({ type: \"SET-CURRENT-BUILDING\", payload: { building: urlBuilding } })\r\n }\r\n }, [urlBuilding, storeBuilding, buildingDispatch])\r\n\r\n const router = useRouter()\r\n const fileInputRef = React.useRef<HTMLInputElement>(null)\r\n\r\n const [currentState, setCurrentState] = React.useState<pointCloudViewerState>('opening')\r\n const [uploading, setUploading] = React.useState(false)\r\n const [searchTerm, setSearchTerm] = React.useState('')\r\n const [searchResults, setSearchResults] = React.useState<any[]>([])\r\n const [selectedBuilding, setSelectedBuilding] = React.useState<any>(null)\r\n \r\n const { files, isLoading: filesLoading } = useFilesByBuildingId(building?.id)\r\n const pointCloudFiles: DbFile[] = React.useMemo(() => (\r\n files.filter(file => {\r\n const ext = file.extension?.toLowerCase()\r\n if (!ext) return false\r\n return ext === \"laz\" || ext === \"las\"\r\n })\r\n ), [files])\r\n\r\n // Fuzzy search function for buildings\r\n const fuzzySearchBuildings = React.useCallback((buildings: any[], searchTerm: string) => {\r\n if (!searchTerm.trim()) return buildings.slice(0, 10)\r\n \r\n const fuzzySearchScore = (search: string, text: string): number => {\r\n if (!search || !text) return 0\r\n const searchLower = search.toLowerCase()\r\n const textLower = text.toLowerCase()\r\n \r\n if (textLower === searchLower) return 1000\r\n if (textLower.startsWith(searchLower)) return 800\r\n if (textLower.includes(searchLower)) return 600\r\n \r\n return 0\r\n }\r\n\r\n return buildings\r\n .map((building) => {\r\n const address = building.buildingAddress || ''\r\n const name = building.buildingName || ''\r\n const id = building.id.toString()\r\n \r\n const addressScore = fuzzySearchScore(searchTerm, address)\r\n const nameScore = fuzzySearchScore(searchTerm, name)\r\n const idScore = fuzzySearchScore(searchTerm, id)\r\n \r\n const maxScore = Math.max(addressScore, nameScore, idScore)\r\n return { ...building, searchScore: maxScore }\r\n })\r\n .filter(building => building.searchScore > 0)\r\n .sort((a, b) => b.searchScore - a.searchScore)\r\n .slice(0, 10)\r\n }, [])\r\n\r\n // Handle search\r\n const handleSearch = React.useCallback((term: string) => {\r\n setSearchTerm(term)\r\n if (buildings) {\r\n setSearchResults(fuzzySearchBuildings(buildings, term))\r\n }\r\n }, [buildings, fuzzySearchBuildings])\r\n\r\n const shouldShow = (currentState === 'opening' || currentState === 'noPointCloudFiles' || currentState === 'noBuilding')\r\n\r\n // Handle initial state transitions\r\n React.useEffect(() => {\r\n // If building is loading, stay in opening state\r\n if (buildingLoading) {\r\n setCurrentState('opening')\r\n return\r\n }\r\n\r\n // If building failed to load or no buildingId provided, show noBuilding state\r\n if (buildingError || (!buildingId && !building)) {\r\n setCurrentState('noBuilding')\r\n return\r\n }\r\n\r\n // If we have a building but files are still loading, stay in opening state\r\n if (building && filesLoading) {\r\n setCurrentState('opening')\r\n return\r\n }\r\n\r\n // If we have a building but no point cloud files, show noPointCloudFiles state\r\n if (building && pointCloudFiles.length === 0) {\r\n setCurrentState('noPointCloudFiles')\r\n return\r\n }\r\n\r\n // We have point cloud files, hide the loading state\r\n if (building && pointCloudFiles.length > 0) {\r\n setCurrentState('ready')\r\n }\r\n }, [building, buildingLoading, buildingError, buildingId, filesLoading, pointCloudFiles.length])\r\n\r\n // Don't render if not visible\r\n if (!shouldShow) {\r\n return null\r\n }\r\n\r\n const handleBuildingSelect = (building: any) => {\r\n const url = new URL(window.location.href)\r\n url.searchParams.set('buildingId', building.id.toString())\r\n buildingDispatch({ type: 'SET-CURRENT-BUILDING', payload: { building } })\r\n setSelectedBuilding(building)\r\n setSearchTerm('')\r\n setSearchResults([])\r\n router.push(url.toString())\r\n }\r\n\r\n // Create point cloud entry\r\n async function createPointCloud(name: string): 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 // 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 const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files\r\n if (!files || files.length === 0) return\r\n\r\n const file = files[0]\r\n const fileName = file.name\r\n const fileExt = fileName.toLowerCase()\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 setUploading(true)\r\n\r\n try {\r\n console.log('Creating point cloud entry...')\r\n const { pointCloud, upload } = await createPointCloud(fileName)\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 // Trigger a refresh of the files - the state will update automatically\r\n window.location.reload()\r\n }\r\n catch (error) {\r\n console.error('Error uploading point cloud:', error)\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 setUploading(false)\r\n }\r\n }\r\n\r\n const handleUploadClick = () => {\r\n fileInputRef.current?.click()\r\n }\r\n\r\n return (\r\n <>\r\n <div className=\"absolute z-10 inset-0 bg-background/50 backdrop-blur-[1px] flex items-center justify-center pointer-events-none\">\r\n <Card className={cn(\"w-[536px] pointer-events-auto flex flex-col justify-start items-center gap-2\")}>\r\n <CardHeader className=\"flex justify-center items-center\">\r\n <div className=\"w-12 h-12 p-2 bg-card rounded-md shadow-sm border border-border flex justify-center items-center\">\r\n {currentState === 'noBuilding' ? (\r\n <LR.Building2 className={cn(\"w-4 h-5 text-foreground\", buildingsLoading && \"animate-pulse\")} strokeWidth={2} />\r\n ) : (\r\n <LR.Grip className={cn(\"w-4 h-5 text-foreground\", currentState === 'opening' && \"animate-pulse\")} strokeWidth={2} />\r\n )}\r\n </div>\r\n </CardHeader>\r\n\r\n <CardContent className=\"self-stretch flex flex-col justify-start items-center gap-6 pt-0\">\r\n <div className=\"self-stretch flex flex-col justify-start items-center gap-2\">\r\n <div className=\"self-stretch text-center text-foreground text-xl font-semibold font-['Inter'] leading-7 flex items-center justify-center gap-2\">\r\n {currentState === 'opening' ? (\r\n <>\r\n {t('openingText')}\r\n <LoadingSpinner size={20} />\r\n </>\r\n ) : currentState === 'noBuilding' ? (\r\n <>\r\n {t('noBuilding')}\r\n </>\r\n ) : uploading ? (\r\n <>\r\n {t('uploading')}\r\n <LoadingSpinner size={20} />\r\n </>\r\n ) : (\r\n t('noPointCloudLoaded')\r\n )}\r\n </div>\r\n {(currentState === 'noPointCloudFiles' || currentState === 'noBuilding') && !uploading && (\r\n <div className=\"self-stretch text-center text-muted-foreground text-sm font-normal font-['Inter'] leading-tight\">\r\n {currentState === 'noBuilding' ? t('selectBuildingHelpText') : t('helpText')}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {currentState === 'noBuilding' && (\r\n <div className=\"self-stretch flex flex-col gap-3 justify-centre items-center\">\r\n {buildingsLoading ? (\r\n <div className=\"flex items-center justify-center gap-2 text-muted-foreground\">\r\n <LoadingSpinner size={16} />\r\n <span>{t('loadingBuildings') || 'Loading buildings...'}</span>\r\n </div>\r\n ) : buildings && buildings.length > 0 ? (\r\n <div className=\"w-full relative\">\r\n {selectedBuilding ? (\r\n <div className=\"relative flex justify-end items-center\">\r\n <Input\r\n type=\"text\"\r\n value={\r\n 'Building: '\r\n + (selectedBuilding.buildingName && selectedBuilding.buildingAddress\r\n ? `${selectedBuilding.buildingName}, ${selectedBuilding.buildingAddress}`\r\n : selectedBuilding.buildingName || selectedBuilding.buildingAddress || `Building ${selectedBuilding.id}`)\r\n }\r\n readOnly\r\n className=\"w-full\"\r\n />\r\n <LR.X \r\n className=\"absolute right-2 cursor-pointer w-4 h-4 text-muted-foreground hover:text-foreground\" \r\n onClick={() => {\r\n setSelectedBuilding(null)\r\n setSearchTerm('')\r\n setSearchResults([])\r\n }} \r\n />\r\n </div>\r\n ) : (\r\n <div className=\"relative\">\r\n <LR.Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4\" />\r\n <Input\r\n placeholder={t('searchBuildings') || 'Search buildings...'}\r\n value={searchTerm}\r\n onChange={(e) => handleSearch(e.target.value)}\r\n className=\"w-full pl-10\"\r\n disabled={!ability.can('read', 'File')}\r\n />\r\n </div>\r\n )}\r\n \r\n {/* Search results dropdown */}\r\n {searchResults.length > 0 && searchTerm !== '' && !selectedBuilding && (\r\n <div className=\"absolute top-full left-0 right-0 mt-1 bg-background border border-border rounded-md shadow-lg max-h-60 overflow-y-auto z-20\">\r\n {searchResults.map(building => (\r\n <div\r\n key={building.id}\r\n className=\"px-3 py-2 text-sm cursor-pointer hover:bg-muted transition-colors flex gap-2 items-center\"\r\n onClick={() => handleBuildingSelect(building)}\r\n >\r\n <LR.SquareArrowOutUpRight className=\"w-3 h-3\" />\r\n {building.buildingName\r\n ? `${building.buildingName}, ${building.buildingAddress}`\r\n : building.buildingAddress || `Building ${building.id}`}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"text-muted-foreground text-center\">\r\n {t('noBuildings') || 'No buildings available'}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {currentState === 'noPointCloudFiles' && (\r\n <div className=\"self-stretch flex justify-center items-center gap-3\">\r\n <Input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\".laz,.las\"\r\n onChange={handleFileChange}\r\n className=\"hidden\"\r\n />\r\n <Button\r\n onClick={handleUploadClick}\r\n size=\"sm\"\r\n className=\"gap-2\"\r\n disabled={uploading || !ability.can('create', 'File')}\r\n >\r\n <LR.Upload className=\"w-4 h-4\" />\r\n {uploading ? t('uploading') : t('uploadButton')}\r\n </Button>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </>\r\n )\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0QgB,SAWE,UAXF,KAWE,YAXF;AA1QhB;AAKA,OAAO,WAAW;AAClB,SAAS,cAAc;AACvB,SAAS,MAAM,aAAa,kBAAkB;AAC9C,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAC/B,YAAY,QAAQ;AACpB,SAAS,kBAAkB,sBAAsB;AACjD,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AAErC,SAAS,UAAU;AACnB,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,aAAa,oBAAoB;AAG1C,MAAM,YAAW,aAAQ,IAAI,mCAAZ,YAA8C;AAcxD,SAAS,yBAAyB;AACvC,QAAM,IAAI,gBAAgB,wBAAwB;AAElD,QAAM,EAAE,QAAQ,IAAI,eAAe;AAEnC,QAAM,EAAE,OAAO,eAAe,UAAU,iBAAiB,IAAI,MAAM,WAAW,gBAAgB;AAC9F,QAAM,EAAE,UAAU,cAAc,IAAI,cAAc;AAElD,QAAM,eAAe,gBAAgB;AACrC,QAAM,aAAa,aAAa,IAAI,YAAY;AAChD,QAAM,EAAE,UAAU,aAAa,WAAW,iBAAiB,SAAS,cAAc,IAAI,YAAY,aAAa,OAAO,UAAU,IAAI,CAAC;AACrI,QAAM,EAAE,WAAW,WAAW,iBAAiB,IAAI,aAAa;AAGhE,QAAM,WAAW,iBAAiB;AAElC,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,iBAAiB,aAAa;AACjC,uBAAiB,EAAE,MAAM,wBAAwB,SAAS,EAAE,UAAU,YAAY,EAAE,CAAC;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,aAAa,eAAe,gBAAgB,CAAC;AAEjD,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,MAAM,OAAyB,IAAI;AAExD,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAgC,SAAS;AACvF,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,EAAE;AACrD,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAgB,CAAC,CAAC;AAClE,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAc,IAAI;AAExE,QAAM,EAAE,OAAO,WAAW,aAAa,IAAI,qBAAqB,qCAAU,EAAE;AAC5E,QAAM,kBAA4B,MAAM,QAAQ,MAC9C,MAAM,OAAO,UAAQ;AAnEzB,QAAAA;AAoEM,UAAM,OAAMA,MAAA,KAAK,cAAL,gBAAAA,IAAgB;AAC5B,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,QAAQ,SAAS,QAAQ;AAAA,EAClC,CAAC,GACA,CAAC,KAAK,CAAC;AAGV,QAAM,uBAAuB,MAAM,YAAY,CAACC,YAAkBC,gBAAuB;AACvF,QAAI,CAACA,YAAW,KAAK,EAAG,QAAOD,WAAU,MAAM,GAAG,EAAE;AAEpD,UAAM,mBAAmB,CAAC,QAAgB,SAAyB;AACjE,UAAI,CAAC,UAAU,CAAC,KAAM,QAAO;AAC7B,YAAM,cAAc,OAAO,YAAY;AACvC,YAAM,YAAY,KAAK,YAAY;AAEnC,UAAI,cAAc,YAAa,QAAO;AACtC,UAAI,UAAU,WAAW,WAAW,EAAG,QAAO;AAC9C,UAAI,UAAU,SAAS,WAAW,EAAG,QAAO;AAE5C,aAAO;AAAA,IACT;AAEA,WAAOA,WACJ,IAAI,CAACE,cAAa;AACjB,YAAM,UAAUA,UAAS,mBAAmB;AAC5C,YAAM,OAAOA,UAAS,gBAAgB;AACtC,YAAM,KAAKA,UAAS,GAAG,SAAS;AAEhC,YAAM,eAAe,iBAAiBD,aAAY,OAAO;AACzD,YAAM,YAAY,iBAAiBA,aAAY,IAAI;AACnD,YAAM,UAAU,iBAAiBA,aAAY,EAAE;AAE/C,YAAM,WAAW,KAAK,IAAI,cAAc,WAAW,OAAO;AAC1D,aAAO,iCAAKC,YAAL,EAAe,aAAa,SAAS;AAAA,IAC9C,CAAC,EACA,OAAO,CAAAA,cAAYA,UAAS,cAAc,CAAC,EAC3C,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE,WAAW,EAC5C,MAAM,GAAG,EAAE;AAAA,EAChB,GAAG,CAAC,CAAC;AAGL,QAAM,eAAe,MAAM,YAAY,CAAC,SAAiB;AACvD,kBAAc,IAAI;AAClB,QAAI,WAAW;AACb,uBAAiB,qBAAqB,WAAW,IAAI,CAAC;AAAA,IACxD;AAAA,EACF,GAAG,CAAC,WAAW,oBAAoB,CAAC;AAEpC,QAAM,aAAc,iBAAiB,aAAa,iBAAiB,uBAAuB,iBAAiB;AAG3G,QAAM,UAAU,MAAM;AAEpB,QAAI,iBAAiB;AACnB,sBAAgB,SAAS;AACzB;AAAA,IACF;AAGA,QAAI,iBAAkB,CAAC,cAAc,CAAC,UAAW;AAC/C,sBAAgB,YAAY;AAC5B;AAAA,IACF;AAGA,QAAI,YAAY,cAAc;AAC5B,sBAAgB,SAAS;AACzB;AAAA,IACF;AAGA,QAAI,YAAY,gBAAgB,WAAW,GAAG;AAC5C,sBAAgB,mBAAmB;AACnC;AAAA,IACF;AAGA,QAAI,YAAY,gBAAgB,SAAS,GAAG;AAC1C,sBAAgB,OAAO;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,UAAU,iBAAiB,eAAe,YAAY,cAAc,gBAAgB,MAAM,CAAC;AAG/F,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,uBAAuB,CAACA,cAAkB;AAC9C,UAAM,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI;AACxC,QAAI,aAAa,IAAI,cAAcA,UAAS,GAAG,SAAS,CAAC;AACzD,qBAAiB,EAAE,MAAM,wBAAwB,SAAS,EAAE,UAAAA,UAAS,EAAE,CAAC;AACxE,wBAAoBA,SAAQ;AAC5B,kBAAc,EAAE;AAChB,qBAAiB,CAAC,CAAC;AACnB,WAAO,KAAK,IAAI,SAAS,CAAC;AAAA,EAC5B;AAGA,iBAAe,iBAAiB,MAAiD;AAC/E,UAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,gBAAgB;AAAA,MACjD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,IAC/B,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,YAAM,IAAI,MAAM,8BAA8B,OAAO,IAAI,MAAM,EAAE;AAAA,IACnE;AAEA,WAAO,IAAI,KAAK;AAAA,EAClB;AAGA,WAAS,qBACP,KACA,MACA,YACe;AACf,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI;AACF,cAAM,MAAM,IAAI,eAAe;AAC/B,YAAI,KAAK,OAAO,KAAK,IAAI;AAEzB,YAAI,YAAY;AACd,cAAI,OAAO,aAAa,CAAC,QAAQ;AAC/B,gBAAI,IAAI,kBAAkB;AACxB,oBAAM,MAAM,KAAK,MAAO,IAAI,SAAS,IAAI,QAAS,GAAG;AACrD,yBAAW,GAAG;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAEA,YAAI,SAAS,MAAM;AACjB,cAAI,IAAI,UAAU,OAAO,IAAI,SAAS,IAAK,SAAQ;AAAA,cAC9C,QAAO,IAAI,MAAM,6BAA6B,IAAI,MAAM,EAAE,CAAC;AAAA,QAClE;AAEA,YAAI,UAAU,MAAM,OAAO,IAAI,MAAM,6BAA6B,CAAC;AACnE,YAAI,KAAK,IAAI;AAAA,MACf,SAAS,KAAK;AACZ,eAAO,GAAG;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,OAAO,UAA+C;AAC7E,UAAMC,SAAQ,MAAM,OAAO;AAC3B,QAAI,CAACA,UAASA,OAAM,WAAW,EAAG;AAElC,UAAM,OAAOA,OAAM,CAAC;AACpB,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS,YAAY;AAGrC,QAAI,CAAC,QAAQ,SAAS,MAAM,KAAK,CAAC,QAAQ,SAAS,MAAM,GAAG;AAC1D,YAAM,kCAAkC;AACxC;AAAA,IACF;AAEA,iBAAa,IAAI;AAEjB,QAAI;AACF,cAAQ,IAAI,+BAA+B;AAC3C,YAAM,EAAE,YAAY,OAAO,IAAI,MAAM,iBAAiB,QAAQ;AAC9D,cAAQ,IAAI,wBAAwB,WAAW,EAAE;AAEjD,cAAQ,IAAI,mBAAmB;AAC/B,YAAM,qBAAqB,OAAO,WAAW,MAAM,CAAC,QAAQ;AAC1D,gBAAQ,IAAI,oBAAoB,GAAG,GAAG;AAAA,MACxC,CAAC;AACD,cAAQ,IAAI,kBAAkB;AAG9B,aAAO,SAAS,OAAO;AAAA,IACzB,SACO,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD;AAAA,QACE,iBAAiB,QACb,qBAAqB,MAAM,OAAO,KAClC;AAAA,MACN;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,oBAAoB,MAAM;AA/PlC,QAAAJ;AAgQI,KAAAA,MAAA,aAAa,YAAb,gBAAAA,IAAsB;AAAA,EACxB;AAEA,SACE,gCACE,8BAAC,SAAI,WAAU,mHACb,+BAAC,QAAK,WAAW,GAAG,8EAA8E,GAChG;AAAA,wBAAC,cAAW,WAAU,oCACpB,8BAAC,SAAI,WAAU,oGACZ,2BAAiB,eAChB,oBAAC,GAAG,WAAH,EAAa,WAAW,GAAG,2BAA2B,oBAAoB,eAAe,GAAG,aAAa,GAAG,IAE7G,oBAAC,GAAG,MAAH,EAAQ,WAAW,GAAG,2BAA2B,iBAAiB,aAAa,eAAe,GAAG,aAAa,GAAG,GAEtH,GACF;AAAA,IAEA,qBAAC,eAAY,WAAU,oEACrB;AAAA,2BAAC,SAAI,WAAU,+DACb;AAAA,4BAAC,SAAI,WAAU,kIACZ,2BAAiB,YAChB,iCACG;AAAA,YAAE,aAAa;AAAA,UAChB,oBAAC,kBAAe,MAAM,IAAI;AAAA,WAC5B,IACE,iBAAiB,eACnB,gCACG,YAAE,YAAY,GACjB,IACE,YACF,iCACG;AAAA,YAAE,WAAW;AAAA,UACd,oBAAC,kBAAe,MAAM,IAAI;AAAA,WAC5B,IAEA,EAAE,oBAAoB,GAE1B;AAAA,SACE,iBAAiB,uBAAuB,iBAAiB,iBAAiB,CAAC,aAC3E,oBAAC,SAAI,WAAU,mGACZ,2BAAiB,eAAe,EAAE,wBAAwB,IAAI,EAAE,UAAU,GAC7E;AAAA,SAEJ;AAAA,MAEC,iBAAiB,gBAChB,oBAAC,SAAI,WAAU,gEACZ,6BACC,qBAAC,SAAI,WAAU,gEACb;AAAA,4BAAC,kBAAe,MAAM,IAAI;AAAA,QAC1B,oBAAC,UAAM,YAAE,kBAAkB,KAAK,wBAAuB;AAAA,SACzD,IACE,aAAa,UAAU,SAAS,IAClC,qBAAC,SAAI,WAAU,mBACZ;AAAA,2BACC,qBAAC,SAAI,WAAU,0CACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OACE,gBACG,iBAAiB,gBAAgB,iBAAiB,kBACjD,GAAG,iBAAiB,YAAY,KAAK,iBAAiB,eAAe,KACrE,iBAAiB,gBAAgB,iBAAiB,mBAAmB,YAAY,iBAAiB,EAAE;AAAA,cAE1G,UAAQ;AAAA,cACR,WAAU;AAAA;AAAA,UACZ;AAAA,UACA;AAAA,YAAC,GAAG;AAAA,YAAH;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAM;AACb,oCAAoB,IAAI;AACxB,8BAAc,EAAE;AAChB,iCAAiB,CAAC,CAAC;AAAA,cACrB;AAAA;AAAA,UACF;AAAA,WACF,IAEA,qBAAC,SAAI,WAAU,YACb;AAAA,8BAAC,GAAG,QAAH,EAAU,WAAU,oFAAmF;AAAA,UACxG;AAAA,YAAC;AAAA;AAAA,cACC,aAAa,EAAE,iBAAiB,KAAK;AAAA,cACrC,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK;AAAA,cAC5C,WAAU;AAAA,cACV,UAAU,CAAC,QAAQ,IAAI,QAAQ,MAAM;AAAA;AAAA,UACvC;AAAA,WACF;AAAA,QAID,cAAc,SAAS,KAAK,eAAe,MAAM,CAAC,oBACjD,oBAAC,SAAI,WAAU,+HACZ,wBAAc,IAAI,CAAAG,cACjB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YACV,SAAS,MAAM,qBAAqBA,SAAQ;AAAA,YAE5C;AAAA,kCAAC,GAAG,uBAAH,EAAyB,WAAU,WAAU;AAAA,cAC7CA,UAAS,eACN,GAAGA,UAAS,YAAY,KAAKA,UAAS,eAAe,KACrDA,UAAS,mBAAmB,YAAYA,UAAS,EAAE;AAAA;AAAA;AAAA,UAPlDA,UAAS;AAAA,QAQhB,CACD,GACH;AAAA,SAEJ,IAEA,oBAAC,SAAI,WAAU,qCACZ,YAAE,aAAa,KAAK,0BACvB,GAEJ;AAAA,MAGD,iBAAiB,uBAChB,qBAAC,SAAI,WAAU,uDACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,QAAO;AAAA,YACP,UAAU;AAAA,YACV,WAAU;AAAA;AAAA,QACZ;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,MAAK;AAAA,YACL,WAAU;AAAA,YACV,UAAU,aAAa,CAAC,QAAQ,IAAI,UAAU,MAAM;AAAA,YAEpD;AAAA,kCAAC,GAAG,QAAH,EAAU,WAAU,WAAU;AAAA,cAC9B,YAAY,EAAE,WAAW,IAAI,EAAE,cAAc;AAAA;AAAA;AAAA,QAChD;AAAA,SACF;AAAA,OAEJ;AAAA,KACF,GACF,GACF;AAEJ;","names":["_a","buildings","searchTerm","building","files"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudLoadingState/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 React from 'react'\r\nimport { Button } from '../../../../ui/Button'\r\nimport { Card, CardContent, CardHeader } from '../../../../ui/Card'\r\nimport { Input } from '../../../../ui/Input'\r\nimport { LoadingSpinner } from '../../../../ui/LoadingSpinner'\r\nimport * as LR from 'lucide-react'\r\nimport { BuildingsContext, usePermissions } from '../../../../../store'\r\n// import { useAppConfigContext } from '../../../../../store/AppConfig/context'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useFilesByBuildingId } from '../../../../../hooks/files/files'\r\nimport type { DbFile } from '../../../../../types/dbTypes'\r\nimport { cn } from '../../../../../utils/utils'\r\nimport { useSearchParams, useRouter } from 'next/navigation'\r\nimport { useBuilding, useBuildings } from '../../../../../hooks/buildings/buildings'\r\nimport { SquareArrowOutUpRight } from 'lucide-react'\r\nimport { toast } from 'sonner'\r\n\r\ntype PresignedUploadResponse = {\r\n presignedUrl: string\r\n key: string\r\n}\r\n\r\nexport type pointCloudViewerState = 'opening' | 'loading' | 'ready' | 'error' | 'noPointCloudFiles' | 'noBuilding'\r\n\r\nexport function PointCloudLoadingState({ pointcloudApiUrl }: { pointcloudApiUrl?: string }) {\r\n const t = useTranslations('PointCloudLoadingState')\r\n const API_BASE = pointcloudApiUrl ?? 'http://localhost:5101'\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: buildingState, dispatch: buildingDispatch } = React.useContext(BuildingsContext)\r\n const { building: storeBuilding } = buildingState.buildings\r\n\r\n const searchParams = useSearchParams()\r\n const buildingId = searchParams.get(\"buildingId\")\r\n const { building: urlBuilding, isLoading: buildingLoading, isError: buildingError } = useBuilding(buildingId ? Number(buildingId) : 0)\r\n const { buildings, isLoading: buildingsLoading } = useBuildings()\r\n\r\n // Determine the current building to use\r\n const building = storeBuilding || urlBuilding\r\n\r\n React.useEffect(() => {\r\n if (!storeBuilding && urlBuilding) {\r\n buildingDispatch({ type: \"SET-CURRENT-BUILDING\", payload: { building: urlBuilding } })\r\n }\r\n }, [urlBuilding, storeBuilding, buildingDispatch])\r\n\r\n const router = useRouter()\r\n const fileInputRef = React.useRef<HTMLInputElement>(null)\r\n\r\n const [currentState, setCurrentState] = React.useState<pointCloudViewerState>('opening')\r\n const [uploading, setUploading] = React.useState(false)\r\n const [searchTerm, setSearchTerm] = React.useState('')\r\n const [searchResults, setSearchResults] = React.useState<any[]>([])\r\n const [selectedBuilding, setSelectedBuilding] = React.useState<any>(null)\r\n \r\n const { files, isLoading: filesLoading } = useFilesByBuildingId(building?.id)\r\n const pointCloudFiles: DbFile[] = React.useMemo(() => (\r\n files.filter(file => {\r\n const ext = file.extension?.toLowerCase()\r\n if (!ext) return false\r\n return ext === \"laz\" || ext === \"las\"\r\n })\r\n ), [files])\r\n\r\n // Fuzzy search function for buildings\r\n const fuzzySearchBuildings = React.useCallback((buildings: any[], searchTerm: string) => {\r\n if (!searchTerm.trim()) return buildings.slice(0, 10)\r\n \r\n const fuzzySearchScore = (search: string, text: string): number => {\r\n if (!search || !text) return 0\r\n const searchLower = search.toLowerCase()\r\n const textLower = text.toLowerCase()\r\n \r\n if (textLower === searchLower) return 1000\r\n if (textLower.startsWith(searchLower)) return 800\r\n if (textLower.includes(searchLower)) return 600\r\n \r\n return 0\r\n }\r\n\r\n return buildings\r\n .map((building) => {\r\n const address = building.buildingAddress || ''\r\n const name = building.buildingName || ''\r\n const id = building.id.toString()\r\n \r\n const addressScore = fuzzySearchScore(searchTerm, address)\r\n const nameScore = fuzzySearchScore(searchTerm, name)\r\n const idScore = fuzzySearchScore(searchTerm, id)\r\n \r\n const maxScore = Math.max(addressScore, nameScore, idScore)\r\n return { ...building, searchScore: maxScore }\r\n })\r\n .filter(building => building.searchScore > 0)\r\n .sort((a, b) => b.searchScore - a.searchScore)\r\n .slice(0, 10)\r\n }, [])\r\n\r\n // Handle search\r\n const handleSearch = React.useCallback((term: string) => {\r\n setSearchTerm(term)\r\n if (buildings) {\r\n setSearchResults(fuzzySearchBuildings(buildings, term))\r\n }\r\n }, [buildings, fuzzySearchBuildings])\r\n\r\n const shouldShow = (currentState === 'opening' || currentState === 'noPointCloudFiles' || currentState === 'noBuilding')\r\n\r\n // Handle initial state transitions\r\n React.useEffect(() => {\r\n // If building is loading, stay in opening state\r\n if (buildingLoading) {\r\n setCurrentState('opening')\r\n return\r\n }\r\n\r\n // If building failed to load or no buildingId provided, show noBuilding state\r\n if (buildingError || (!buildingId && !building)) {\r\n setCurrentState('noBuilding')\r\n return\r\n }\r\n\r\n // If we have a building but files are still loading, stay in opening state\r\n if (building && filesLoading) {\r\n setCurrentState('opening')\r\n return\r\n }\r\n\r\n // If we have a building but no point cloud files, show noPointCloudFiles state\r\n if (building && pointCloudFiles.length === 0) {\r\n setCurrentState('noPointCloudFiles')\r\n return\r\n }\r\n\r\n // We have point cloud files, hide the loading state\r\n if (building && pointCloudFiles.length > 0) {\r\n setCurrentState('ready')\r\n }\r\n }, [building, buildingLoading, buildingError, buildingId, filesLoading, pointCloudFiles.length])\r\n\r\n // Don't render if not visible\r\n if (!shouldShow) {\r\n return null\r\n }\r\n\r\n const handleBuildingSelect = (building: any) => {\r\n const url = new URL(window.location.href)\r\n url.searchParams.set('buildingId', building.id.toString())\r\n buildingDispatch({ type: 'SET-CURRENT-BUILDING', payload: { building } })\r\n setSelectedBuilding(building)\r\n setSearchTerm('')\r\n setSearchResults([])\r\n router.push(url.toString())\r\n }\r\n\r\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files\r\n if (!files || files.length === 0) return\r\n\r\n const file = files[0]\r\n const fileName = file.name\r\n const fileExt = fileName.toLowerCase()\r\n\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 if (!building?.id) {\r\n alert('No building selected.')\r\n return\r\n }\r\n\r\n setUploading(true)\r\n\r\n try {\r\n const assetId = crypto.randomUUID()\r\n const assetName = `${assetId}.laz`\r\n\r\n // 1. Get presigned upload URL\r\n const presignedRes = await fetch(\r\n `/api/presigned-url-upload?asset=${encodeURIComponent(assetName)}&bucket=pointclouds-demo`\r\n )\r\n if (!presignedRes.ok) throw new Error('Failed to get upload URL')\r\n const { presignedUrl, key }: PresignedUploadResponse = await presignedRes.json()\r\n\r\n // 2. Upload LAZ directly to MinIO\r\n const uploadRes = await fetch(presignedUrl, {\r\n method: 'PUT',\r\n body: file,\r\n headers: { 'Content-Type': 'application/octet-stream' },\r\n })\r\n if (!uploadRes.ok) throw new Error(`Upload failed: ${uploadRes.status}`)\r\n\r\n // 3. Create file record attached to the building\r\n const fileRes = await fetch(`/api/files/building/${building.id}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n type: 'point-cloud-file',\r\n name: fileName,\r\n assetId,\r\n lazFileKey: key,\r\n bucket: 'pointclouds-demo',\r\n extension: fileExt.endsWith('.las') ? 'las' : 'laz',\r\n }),\r\n })\r\n if (!fileRes.ok) throw new Error('Failed to create file record')\r\n\r\n toast.success('LAZ file uploaded successfully', { duration: 6000 })\r\n window.location.reload()\r\n }\r\n catch (error) {\r\n console.error('Error uploading point cloud:', error)\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 setUploading(false)\r\n }\r\n }\r\n\r\n const handleUploadClick = () => {\r\n fileInputRef.current?.click()\r\n }\r\n\r\n return (\r\n <>\r\n <div className=\"absolute z-10 inset-0 bg-background/50 backdrop-blur-[1px] flex items-center justify-center pointer-events-none\">\r\n <Card className={cn(\"w-[536px] pointer-events-auto flex flex-col justify-start items-center gap-2\")}>\r\n <CardHeader className=\"flex justify-center items-center\">\r\n <div className=\"w-12 h-12 p-2 bg-card rounded-md shadow-sm border border-border flex justify-center items-center\">\r\n {currentState === 'noBuilding' ? (\r\n <LR.Building2 className={cn(\"w-4 h-5 text-foreground\", buildingsLoading && \"animate-pulse\")} strokeWidth={2} />\r\n ) : (\r\n <LR.Grip className={cn(\"w-4 h-5 text-foreground\", currentState === 'opening' && \"animate-pulse\")} strokeWidth={2} />\r\n )}\r\n </div>\r\n </CardHeader>\r\n\r\n <CardContent className=\"self-stretch flex flex-col justify-start items-center gap-6 pt-0\">\r\n <div className=\"self-stretch flex flex-col justify-start items-center gap-2\">\r\n <div className=\"self-stretch text-center text-foreground text-xl font-semibold font-['Inter'] leading-7 flex items-center justify-center gap-2\">\r\n {currentState === 'opening' ? (\r\n <>\r\n {t('openingText')}\r\n <LoadingSpinner size={20} />\r\n </>\r\n ) : currentState === 'noBuilding' ? (\r\n <>\r\n {t('noBuilding')}\r\n </>\r\n ) : uploading ? (\r\n <>\r\n {t('uploading')}\r\n <LoadingSpinner size={20} />\r\n </>\r\n ) : (\r\n t('noPointCloudLoaded')\r\n )}\r\n </div>\r\n {(currentState === 'noPointCloudFiles' || currentState === 'noBuilding') && !uploading && (\r\n <div className=\"self-stretch text-center text-muted-foreground text-sm font-normal font-['Inter'] leading-tight\">\r\n {currentState === 'noBuilding' ? t('selectBuildingHelpText') : t('helpText')}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {currentState === 'noBuilding' && (\r\n <div className=\"self-stretch flex flex-col gap-3 justify-centre items-center\">\r\n {buildingsLoading ? (\r\n <div className=\"flex items-center justify-center gap-2 text-muted-foreground\">\r\n <LoadingSpinner size={16} />\r\n <span>{t('loadingBuildings') || 'Loading buildings...'}</span>\r\n </div>\r\n ) : buildings && buildings.length > 0 ? (\r\n <div className=\"w-full relative\">\r\n {selectedBuilding ? (\r\n <div className=\"relative flex justify-end items-center\">\r\n <Input\r\n type=\"text\"\r\n value={\r\n 'Building: '\r\n + (selectedBuilding.buildingName && selectedBuilding.buildingAddress\r\n ? `${selectedBuilding.buildingName}, ${selectedBuilding.buildingAddress}`\r\n : selectedBuilding.buildingName || selectedBuilding.buildingAddress || `Building ${selectedBuilding.id}`)\r\n }\r\n readOnly\r\n className=\"w-full\"\r\n />\r\n <LR.X \r\n className=\"absolute right-2 cursor-pointer w-4 h-4 text-muted-foreground hover:text-foreground\" \r\n onClick={() => {\r\n setSelectedBuilding(null)\r\n setSearchTerm('')\r\n setSearchResults([])\r\n }} \r\n />\r\n </div>\r\n ) : (\r\n <div className=\"relative\">\r\n <LR.Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4\" />\r\n <Input\r\n placeholder={t('searchBuildings') || 'Search buildings...'}\r\n value={searchTerm}\r\n onChange={(e) => handleSearch(e.target.value)}\r\n className=\"w-full pl-10\"\r\n disabled={!ability.can('read', 'File')}\r\n />\r\n </div>\r\n )}\r\n \r\n {/* Search results dropdown */}\r\n {searchResults.length > 0 && searchTerm !== '' && !selectedBuilding && (\r\n <div className=\"absolute top-full left-0 right-0 mt-1 bg-background border border-border rounded-md shadow-lg max-h-60 overflow-y-auto z-20\">\r\n {searchResults.map(building => (\r\n <div\r\n key={building.id}\r\n className=\"px-3 py-2 text-sm cursor-pointer hover:bg-muted transition-colors flex gap-2 items-center\"\r\n onClick={() => handleBuildingSelect(building)}\r\n >\r\n <LR.SquareArrowOutUpRight className=\"w-3 h-3\" />\r\n {building.buildingName\r\n ? `${building.buildingName}, ${building.buildingAddress}`\r\n : building.buildingAddress || `Building ${building.id}`}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"text-muted-foreground text-center\">\r\n {t('noBuildings') || 'No buildings available'}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {currentState === 'noPointCloudFiles' && (\r\n <div className=\"self-stretch flex justify-center items-center gap-3\">\r\n <Input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\".laz,.las\"\r\n onChange={handleFileChange}\r\n className=\"hidden\"\r\n />\r\n <Button\r\n onClick={handleUploadClick}\r\n size=\"sm\"\r\n className=\"gap-2\"\r\n disabled={uploading || !ability.can('create', 'File')}\r\n >\r\n <LR.Upload className=\"w-4 h-4\" />\r\n {uploading ? t('uploading') : t('uploadButton')}\r\n </Button>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["buildings","searchTerm","building","files"]}
@@ -1,3 +1,5 @@
1
1
  import * as React from "react";
2
- export declare function PointCloudManagementTable(): React.JSX.Element;
2
+ export declare function PointCloudManagementTable({ pointcloudApiUrl }: {
3
+ pointcloudApiUrl?: string;
4
+ }): React.JSX.Element;
3
5
  //# sourceMappingURL=PointCloudManagementTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointCloudManagementTable.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,wBAAgB,yBAAyB,sBAgBxC"}
1
+ {"version":3,"file":"PointCloudManagementTable.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,wBAAgB,yBAAyB,CAAC,EAAE,gBAAgB,EAAE,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,qBAkB5F"}
@@ -8,17 +8,19 @@ var PAGE = /* @__PURE__ */ ((PAGE2) => {
8
8
  PAGE2["UPLOAD"] = "upload";
9
9
  return PAGE2;
10
10
  })(PAGE || {});
11
- function PointCloudManagementTable() {
11
+ function PointCloudManagementTable({ pointcloudApiUrl }) {
12
12
  const [currentPage, setCurrentPage] = React.useState("table" /* TABLE */);
13
13
  return /* @__PURE__ */ jsx("div", { children: currentPage == "table" /* TABLE */ ? /* @__PURE__ */ jsx(
14
14
  PointCloudTable,
15
15
  {
16
- onUploadButtonClick: () => setCurrentPage("upload" /* UPLOAD */)
16
+ onUploadButtonClick: () => setCurrentPage("upload" /* UPLOAD */),
17
+ pointcloudApiUrl
17
18
  }
18
19
  ) : /* @__PURE__ */ jsx(
19
20
  UploadPointCloudPage,
20
21
  {
21
- onGoBackButtonClick: () => setCurrentPage("table" /* TABLE */)
22
+ onGoBackButtonClick: () => setCurrentPage("table" /* TABLE */),
23
+ pointcloudApiUrl
22
24
  }
23
25
  ) });
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.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 { PointCloudTable } from \"./PointCloudTable\";\r\nimport UploadPointCloudPage from \"./PointCloudUploadPanel\";\r\n\r\ntype StatusFilter = \"all\" | \"uploaded\" | \"converted\" | \"not-converted\";\r\n\r\nenum PAGE {\r\n TABLE = \"table\",\r\n UPLOAD = \"upload\",\r\n}\r\n\r\nexport function PointCloudManagementTable() {\r\n const [currentPage, setCurrentPage] = React.useState<PAGE>(PAGE.TABLE)\r\n\r\n return(\r\n <div>\r\n {currentPage == PAGE.TABLE ? \r\n <PointCloudTable\r\n onUploadButtonClick = {() => setCurrentPage(PAGE.UPLOAD)}\r\n />\r\n :\r\n <UploadPointCloudPage\r\n onGoBackButtonClick = {() => setCurrentPage(PAGE.TABLE)}\r\n />\r\n }\r\n </div>\r\n )\r\n}\r\n\r\n"],"mappings":";AAsBQ;AAjBR,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,OAAO,0BAA0B;AAIjC,IAAK,OAAL,kBAAKA,UAAL;AACE,EAAAA,MAAA,WAAQ;AACR,EAAAA,MAAA,YAAS;AAFN,SAAAA;AAAA,GAAA;AAKE,SAAS,4BAA4B;AAC1C,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAe,mBAAU;AAErE,SACE,oBAAC,SACE,yBAAe,sBACd;AAAA,IAAC;AAAA;AAAA,MACC,qBAAuB,MAAM,eAAe,qBAAW;AAAA;AAAA,EACzD,IAEA;AAAA,IAAC;AAAA;AAAA,MACC,qBAAuB,MAAM,eAAe,mBAAU;AAAA;AAAA,EACxD,GAEJ;AAEJ;","names":["PAGE"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.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 { PointCloudTable } from \"./PointCloudTable\";\r\nimport UploadPointCloudPage from \"./PointCloudUploadPanel\";\r\n\r\ntype StatusFilter = \"all\" | \"uploaded\" | \"converted\" | \"not-converted\";\r\n\r\nenum PAGE {\r\n TABLE = \"table\",\r\n UPLOAD = \"upload\",\r\n}\r\n\r\nexport function PointCloudManagementTable({ pointcloudApiUrl }: { pointcloudApiUrl?: string }) {\r\n const [currentPage, setCurrentPage] = React.useState<PAGE>(PAGE.TABLE)\r\n\r\n return(\r\n <div>\r\n {currentPage == PAGE.TABLE ?\r\n <PointCloudTable\r\n onUploadButtonClick = {() => setCurrentPage(PAGE.UPLOAD)}\r\n pointcloudApiUrl={pointcloudApiUrl}\r\n />\r\n :\r\n <UploadPointCloudPage\r\n onGoBackButtonClick = {() => setCurrentPage(PAGE.TABLE)}\r\n pointcloudApiUrl={pointcloudApiUrl}\r\n />\r\n }\r\n </div>\r\n )\r\n}\r\n\r\n"],"mappings":";AAsBQ;AAjBR,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,OAAO,0BAA0B;AAIjC,IAAK,OAAL,kBAAKA,UAAL;AACE,EAAAA,MAAA,WAAQ;AACR,EAAAA,MAAA,YAAS;AAFN,SAAAA;AAAA,GAAA;AAKE,SAAS,0BAA0B,EAAE,iBAAiB,GAAkC;AAC7F,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAe,mBAAU;AAErE,SACE,oBAAC,SACE,yBAAe,sBACd;AAAA,IAAC;AAAA;AAAA,MACC,qBAAuB,MAAM,eAAe,qBAAW;AAAA,MACvD;AAAA;AAAA,EACF,IAEA;AAAA,IAAC;AAAA;AAAA,MACC,qBAAuB,MAAM,eAAe,mBAAU;AAAA,MACtD;AAAA;AAAA,EACF,GAEJ;AAEJ;","names":["PAGE"]}
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
2
  type PointCloudTableProps = React.HTMLAttributes<HTMLDivElement> & {
3
3
  onUploadButtonClick: () => void;
4
+ pointcloudApiUrl?: string;
4
5
  };
5
- export declare function PointCloudTable({ onUploadButtonClick, ...divProps }: PointCloudTableProps): React.JSX.Element;
6
+ export declare function PointCloudTable({ onUploadButtonClick, pointcloudApiUrl, ...divProps }: PointCloudTableProps): React.JSX.Element;
6
7
  export {};
7
8
  //# sourceMappingURL=PointCloudTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointCloudTable.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkD/B,KAAK,oBAAoB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAC/D,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAC5B,mBAAmB,EACnB,GAAG,QAAQ,EACd,EAAE,oBAAoB,qBAkZtB"}
1
+ {"version":3,"file":"PointCloudTable.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAgD/B,KAAK,oBAAoB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAC/D,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,GAAG,QAAQ,EACd,EAAE,oBAAoB,qBAmZtB"}
@@ -15,7 +15,6 @@ var __objRest = (source, exclude) => {
15
15
  return target;
16
16
  };
17
17
  import { jsx, jsxs } from "react/jsx-runtime";
18
- var _a;
19
18
  import * as React from "react";
20
19
  import {
21
20
  Table,
@@ -41,18 +40,20 @@ import {
41
40
  ChevronLeft,
42
41
  ChevronRight
43
42
  } from "lucide-react";
44
- const API_BASE = (_a = process.env.NEXT_PUBLIC_POINTCLOUD_API_URL) != null ? _a : "http://localhost:5101";
45
43
  var PAGE = /* @__PURE__ */ ((PAGE2) => {
46
44
  PAGE2["TABLE"] = "table";
47
45
  PAGE2["UPLOAD"] = "upload";
48
46
  return PAGE2;
49
47
  })(PAGE || {});
50
- function PointCloudTable(_b) {
51
- var _c = _b, {
52
- onUploadButtonClick
53
- } = _c, divProps = __objRest(_c, [
54
- "onUploadButtonClick"
48
+ function PointCloudTable(_a) {
49
+ var _b = _a, {
50
+ onUploadButtonClick,
51
+ pointcloudApiUrl
52
+ } = _b, divProps = __objRest(_b, [
53
+ "onUploadButtonClick",
54
+ "pointcloudApiUrl"
55
55
  ]);
56
+ const API_BASE = pointcloudApiUrl != null ? pointcloudApiUrl : "http://localhost:5101";
56
57
  const [pointClouds, setPointClouds] = React.useState([]);
57
58
  const [loading, setLoading] = React.useState(false);
58
59
  const [error, setError] = React.useState(null);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.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 {\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableHead,\r\n TableHeader,\r\n TableRow,\r\n} from \"../../../../ui/Table\";\r\n\r\nimport { Badge, Button, Checkbox, Input, ScrollArea } from '../../../../ui';\r\n\r\nimport { Tabs, TabsList, TabsTrigger } from \"../../../../ui/Tabs\";\r\n\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { useTranslations } from 'next-intl'\r\nimport { toast } from 'sonner'\r\nimport ConfirmDialog from '../../../../ConfirmDialog'\r\n\r\nimport {\r\n Star,\r\n StarOff,\r\n Eye,\r\n Trash2,\r\n Filter,\r\n RotateCcw,\r\n ChevronLeft,\r\n ChevronRight,\r\n} from \"lucide-react\";\r\n\r\nconst API_BASE =\r\n process.env.NEXT_PUBLIC_POINTCLOUD_API_URL ?? \"http://localhost:5101\";\r\n\r\ntype PointCloud = {\r\n id: string;\r\n name: string;\r\n point_cloud_uploaded: boolean;\r\n point_cloud_potree_converted: boolean;\r\n createdAt: string;\r\n potree_metadata_presigned_url?: string | null;\r\n potree_metadata_file_key?: string | null;\r\n};\r\n\r\ntype StatusFilter = \"all\" | \"uploaded\" | \"converted\" | \"not-converted\";\r\n\r\nenum PAGE {\r\n TABLE = \"table\",\r\n UPLOAD = \"upload\",\r\n}\r\n\r\ntype PointCloudTableProps = React.HTMLAttributes<HTMLDivElement> & {\r\n onUploadButtonClick: () => void;\r\n};\r\n\r\nexport function PointCloudTable({\r\n onUploadButtonClick, \r\n ...divProps\r\n}: PointCloudTableProps) {\r\n const [pointClouds, setPointClouds] = React.useState<PointCloud[]>([]);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<string | null>(null);\r\n const [search, setSearch] = React.useState(\"\");\r\n const [statusFilter, setStatusFilter] = React.useState<StatusFilter>(\"all\");\r\n const [favorites, setFavorites] = React.useState<Set<string>>(new Set());\r\n const [currentUrl, setCurrentUrl] = React.useState<URL | null>(null);\r\n const [deleteTarget, setDeleteTarget] = React.useState<PointCloud | null>(null)\r\n const [isDeleting, setIsDeleting] = React.useState(false)\r\n const t = useTranslations('PointCloudManagement')\r\n\r\n React.useEffect(() => {\r\n // This only runs in the browser\r\n const url = new URL(window.location.href);\r\n setCurrentUrl(url);\r\n }, []);\r\n\r\n const [currentPage, setCurrentPage] = React.useState<PAGE>(PAGE.TABLE)\r\n\r\n // route and navigation\r\n const router = useRouter()\r\n const pathname = usePathname()\r\n\r\n const loadPointClouds = React.useCallback(async () => {\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const res = await fetch(`${API_BASE}/point-cloud`, {\r\n headers: { \"Accept\": \"application/json\" },\r\n });\r\n\r\n if (!res.ok) {\r\n throw new Error(`Failed to fetch point clouds (${res.status})`);\r\n }\r\n\r\n const data: PointCloud[] = await res.json();\r\n setPointClouds(Array.isArray(data) ? data : []);\r\n } catch (err) {\r\n console.error(err);\r\n setError(\r\n err instanceof Error ? err.message : \"Unknown error while loading data\",\r\n );\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n loadPointClouds();\r\n }, [loadPointClouds]);\r\n\r\n const openViewer = (pointCloudId) => {\r\n if (!pointCloudId) return;\r\n const origin = window.location.origin\r\n const pathname = window.location.pathname\r\n const params = new URLSearchParams(currentUrl.search)\r\n params.set('viewer', 'pointcloud')\r\n params.set('pointCloudId', pointCloudId)\r\n const newurl = `${origin}${pathname}?${params.toString()}`\r\n router.push(newurl, { scroll: false }) // push but do not refresh\r\n };\r\n\r\n const handleDelete = async () => {\r\n if (!deleteTarget) return\r\n\r\n setIsDeleting(true)\r\n\r\n try {\r\n const res = await fetch(`${API_BASE}/point-cloud/${deleteTarget.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 setPointClouds((prev) => prev.filter((pc) => pc.id !== deleteTarget.id));\r\n setFavorites((prev) => {\r\n const next = new Set(prev);\r\n next.delete(deleteTarget.id);\r\n return next;\r\n });\r\n toast.success(t('deleteSuccess', { name: deleteTarget.name }))\r\n } catch (err) {\r\n console.error(err);\r\n toast.error(\r\n err instanceof Error\r\n ? t('deleteFailedWithReason', { error: err.message })\r\n : t('deleteFailed'),\r\n );\r\n } finally {\r\n setIsDeleting(false)\r\n setDeleteTarget(null)\r\n }\r\n };\r\n\r\n const toggleFavorite = (id: string) => {\r\n setFavorites((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(id)) next.delete(id);\r\n else next.add(id);\r\n return next;\r\n });\r\n };\r\n\r\n const filtered = React.useMemo(() => {\r\n return pointClouds.filter((pc) => {\r\n const matchesSearch =\r\n !search ||\r\n pc.name.toLowerCase().includes(search.toLowerCase()) ||\r\n pc.id.toLowerCase().includes(search.toLowerCase());\r\n\r\n let matchesStatus = true;\r\n if (statusFilter === \"uploaded\") {\r\n matchesStatus = pc.point_cloud_uploaded;\r\n } else if (statusFilter === \"converted\") {\r\n matchesStatus = pc.point_cloud_potree_converted;\r\n } else if (statusFilter === \"not-converted\") {\r\n matchesStatus =\r\n pc.point_cloud_uploaded && !pc.point_cloud_potree_converted;\r\n }\r\n\r\n return matchesSearch && matchesStatus;\r\n });\r\n }, [pointClouds, search, statusFilter]);\r\n\r\n return (\r\n <div className={`p-2 mt-20 ${divProps}`}>\r\n {/* Header */}\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"space-y-1\">\r\n <h1 className=\"text-2xl font-semibold tracking-tight\">\r\n Point Clouds\r\n </h1>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <Input\r\n placeholder=\"Search point clouds...\"\r\n className=\"w-[240px]\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n />\r\n <Button variant=\"outline\" size=\"icon\" title=\"Filters (not wired)\">\r\n <Filter className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"icon\"\r\n onClick={loadPointClouds}\r\n disabled={loading}\r\n title=\"Refresh\"\r\n >\r\n <RotateCcw className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Tabs row */}\r\n <Tabs\r\n value={statusFilter}\r\n onValueChange={(val) => setStatusFilter(val as StatusFilter)}\r\n className=\"w-full mb-2\"\r\n >\r\n <TabsList className=\"h-8\">\r\n <TabsTrigger value=\"all\" className=\"px-3\">\r\n All\r\n </TabsTrigger>\r\n <TabsTrigger value=\"uploaded\" className=\"px-3\">\r\n Uploaded\r\n </TabsTrigger>\r\n <TabsTrigger value=\"converted\" className=\"px-3\">\r\n Converted\r\n </TabsTrigger>\r\n <TabsTrigger value=\"not-converted\" className=\"px-3\">\r\n Needs conversion\r\n </TabsTrigger>\r\n </TabsList>\r\n </Tabs>\r\n\r\n {/* Table card */}\r\n <div className=\"rounded-md border bg-background\">\r\n <ScrollArea className=\"max-h-[520px]\">\r\n <Table>\r\n <TableHeader className=\"sticky top-0 z-10 bg-background/95 backdrop-blur\">\r\n <TableRow>\r\n <TableHead className=\"w-[40px] pl-4\">\r\n <Checkbox aria-label=\"Select all\" />\r\n </TableHead>\r\n <TableHead className=\"w-[48px]\"></TableHead>\r\n <TableHead className=\"min-w-[220px]\">Name</TableHead>\r\n <TableHead className=\"w-[200px]\">Status</TableHead>\r\n <TableHead className=\"w-[220px]\">Created</TableHead>\r\n <TableHead className=\"w-[160px]\">Metadata</TableHead>\r\n <TableHead className=\"w-[140px] text-right pr-4\">\r\n Actions\r\n </TableHead>\r\n </TableRow>\r\n </TableHeader>\r\n\r\n <TableBody>\r\n {loading && pointClouds.length === 0 && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n Loading point clouds…\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {!loading && error && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n <span className=\"text-sm text-destructive\">\r\n {error}\r\n </span>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {!loading && !error && filtered.length === 0 && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n No point clouds found.\r\n </span>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {filtered.map((pc) => {\r\n const isFavorite = favorites.has(pc.id);\r\n return (\r\n <TableRow\r\n key={pc.id}\r\n className=\"hover:bg-muted/50 transition-colors\"\r\n >\r\n <TableCell className=\"pl-4\">\r\n <Checkbox aria-label={`Select ${pc.name}`} />\r\n </TableCell>\r\n\r\n {/* Favorite star */}\r\n <TableCell className=\"text-center\">\r\n <button\r\n type=\"button\"\r\n onClick={() => toggleFavorite(pc.id)}\r\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-full text-muted-foreground hover:text-yellow-500\"\r\n aria-label={\r\n isFavorite\r\n ? `Remove ${pc.name} from favourites`\r\n : `Add ${pc.name} to favourites`\r\n }\r\n >\r\n {isFavorite ? (\r\n <Star className=\"h-4 w-4 fill-yellow-400\" />\r\n ) : (\r\n <StarOff className=\"h-4 w-4\" />\r\n )}\r\n </button>\r\n </TableCell>\r\n\r\n {/* Name & ID */}\r\n <TableCell>\r\n <div className=\"font-medium\">{pc.name}</div>\r\n <div className=\"text-xs text-muted-foreground\">\r\n {pc.id}\r\n </div>\r\n </TableCell>\r\n\r\n {/* Status badges */}\r\n <TableCell>\r\n <div className=\"flex flex-wrap gap-1\">\r\n <Badge\r\n className={`text-xs border ${\r\n pc.point_cloud_uploaded\r\n ? \"bg-emerald-50 text-emerald-700 border-emerald-200\"\r\n : \"bg-rose-50 text-rose-700 border-rose-200\"\r\n }`}\r\n >\r\n {pc.point_cloud_uploaded ? \"Uploaded\" : \"Not uploaded\"}\r\n </Badge>\r\n\r\n <Badge\r\n className={`text-xs border ${\r\n pc.point_cloud_potree_converted\r\n ? \"bg-sky-50 text-sky-700 border-sky-200\"\r\n : \"bg-amber-50 text-amber-700 border-amber-200\"\r\n }`}\r\n >\r\n {pc.point_cloud_potree_converted\r\n ? \"Ready to view\"\r\n : \"Needs conversion\"}\r\n </Badge>\r\n </div>\r\n </TableCell>\r\n\r\n {/* Created date */}\r\n <TableCell className=\"whitespace-nowrap text-sm text-muted-foreground\">\r\n {new Date(pc.createdAt).toLocaleString()}\r\n </TableCell>\r\n\r\n {/* Metadata link */}\r\n <TableCell>\r\n {pc.potree_metadata_presigned_url ? (\r\n <Button\r\n asChild\r\n variant=\"link\"\r\n size=\"sm\"\r\n className=\"px-0\"\r\n >\r\n <a\r\n href={pc.potree_metadata_presigned_url}\r\n target=\"_blank\"\r\n rel=\"noreferrer\"\r\n >\r\n metadata.json\r\n </a>\r\n </Button>\r\n ) : (\r\n <span className=\"text-xs text-muted-foreground\">—</span>\r\n )}\r\n </TableCell>\r\n\r\n {/* Actions */}\r\n <TableCell className=\"pr-4 text-right\">\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"icon\"\r\n disabled={!pc.potree_metadata_file_key}\r\n onClick={() =>\r\n openViewer(pc.id)\r\n }\r\n title=\"Open Potree viewer\"\r\n >\r\n <Eye className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"text-destructive hover:text-destructive\"\r\n onClick={() => setDeleteTarget(pc)}\r\n title={t('deleteTitle')}\r\n >\r\n <Trash2 className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </TableCell>\r\n </TableRow>\r\n );\r\n })}\r\n </TableBody>\r\n </Table>\r\n </ScrollArea>\r\n\r\n {/* Faux pagination / footer */}\r\n <div className=\"flex items-center justify-between border-t px-4 py-2 text-xs text-muted-foreground\">\r\n <div>\r\n Showing <span className=\"font-medium\">{filtered.length}</span> of{\" \"}\r\n <span className=\"font-medium\">{pointClouds.length}</span> point\r\n clouds\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <Button variant=\"ghost\" size=\"icon\" disabled>\r\n <ChevronLeft className=\"h-4 w-4\" />\r\n </Button>\r\n <Button variant=\"ghost\" size=\"icon\" disabled>\r\n <ChevronRight className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <Button\r\n onClick={() => {\r\n if (onUploadButtonClick != undefined){\r\n onUploadButtonClick()\r\n }\r\n }}\r\n className=\"mt-1 flex gap-2\"\r\n >\r\n Upload point cloud →\r\n </Button>\r\n\r\n <ConfirmDialog\r\n isOpen={deleteTarget != null}\r\n isDeleting={isDeleting}\r\n onOpenChange={(open) => {\r\n if (!open) setDeleteTarget(null)\r\n }}\r\n handleConfirm={async (e) => {\r\n e.preventDefault()\r\n await handleDelete()\r\n }}\r\n itemName={deleteTarget?.name}\r\n dataType={t('pointCloudItem')}\r\n />\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":["PAGE","pathname"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.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 {\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableHead,\r\n TableHeader,\r\n TableRow,\r\n} from \"../../../../ui/Table\";\r\n\r\nimport { Badge, Button, Checkbox, Input, ScrollArea } from '../../../../ui';\r\n\r\nimport { Tabs, TabsList, TabsTrigger } from \"../../../../ui/Tabs\";\r\n\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { useTranslations } from 'next-intl'\r\nimport { toast } from 'sonner'\r\nimport ConfirmDialog from '../../../../ConfirmDialog'\r\n// import { useAppConfigContext } from '../../../../../store/AppConfig/context'\r\n\r\nimport {\r\n Star,\r\n StarOff,\r\n Eye,\r\n Trash2,\r\n Filter,\r\n RotateCcw,\r\n ChevronLeft,\r\n ChevronRight,\r\n} from \"lucide-react\";\r\n\r\ntype PointCloud = {\r\n id: string;\r\n name: string;\r\n point_cloud_uploaded: boolean;\r\n point_cloud_potree_converted: boolean;\r\n createdAt: string;\r\n potree_metadata_presigned_url?: string | null;\r\n potree_metadata_file_key?: string | null;\r\n};\r\n\r\ntype StatusFilter = \"all\" | \"uploaded\" | \"converted\" | \"not-converted\";\r\n\r\nenum PAGE {\r\n TABLE = \"table\",\r\n UPLOAD = \"upload\",\r\n}\r\n\r\ntype PointCloudTableProps = React.HTMLAttributes<HTMLDivElement> & {\r\n onUploadButtonClick: () => void;\r\n pointcloudApiUrl?: string;\r\n};\r\n\r\nexport function PointCloudTable({\r\n onUploadButtonClick,\r\n pointcloudApiUrl,\r\n ...divProps\r\n}: PointCloudTableProps) {\r\n const API_BASE = pointcloudApiUrl ?? 'http://localhost:5101'\r\n const [pointClouds, setPointClouds] = React.useState<PointCloud[]>([]);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<string | null>(null);\r\n const [search, setSearch] = React.useState(\"\");\r\n const [statusFilter, setStatusFilter] = React.useState<StatusFilter>(\"all\");\r\n const [favorites, setFavorites] = React.useState<Set<string>>(new Set());\r\n const [currentUrl, setCurrentUrl] = React.useState<URL | null>(null);\r\n const [deleteTarget, setDeleteTarget] = React.useState<PointCloud | null>(null)\r\n const [isDeleting, setIsDeleting] = React.useState(false)\r\n const t = useTranslations('PointCloudManagement')\r\n\r\n React.useEffect(() => {\r\n // This only runs in the browser\r\n const url = new URL(window.location.href);\r\n setCurrentUrl(url);\r\n }, []);\r\n\r\n const [currentPage, setCurrentPage] = React.useState<PAGE>(PAGE.TABLE)\r\n\r\n // route and navigation\r\n const router = useRouter()\r\n const pathname = usePathname()\r\n\r\n const loadPointClouds = React.useCallback(async () => {\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const res = await fetch(`${API_BASE}/point-cloud`, {\r\n headers: { \"Accept\": \"application/json\" },\r\n });\r\n\r\n if (!res.ok) {\r\n throw new Error(`Failed to fetch point clouds (${res.status})`);\r\n }\r\n\r\n const data: PointCloud[] = await res.json();\r\n setPointClouds(Array.isArray(data) ? data : []);\r\n } catch (err) {\r\n console.error(err);\r\n setError(\r\n err instanceof Error ? err.message : \"Unknown error while loading data\",\r\n );\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n loadPointClouds();\r\n }, [loadPointClouds]);\r\n\r\n const openViewer = (pointCloudId) => {\r\n if (!pointCloudId) return;\r\n const origin = window.location.origin\r\n const pathname = window.location.pathname\r\n const params = new URLSearchParams(currentUrl.search)\r\n params.set('viewer', 'pointcloud')\r\n params.set('pointCloudId', pointCloudId)\r\n const newurl = `${origin}${pathname}?${params.toString()}`\r\n router.push(newurl, { scroll: false }) // push but do not refresh\r\n };\r\n\r\n const handleDelete = async () => {\r\n if (!deleteTarget) return\r\n\r\n setIsDeleting(true)\r\n\r\n try {\r\n const res = await fetch(`${API_BASE}/point-cloud/${deleteTarget.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 setPointClouds((prev) => prev.filter((pc) => pc.id !== deleteTarget.id));\r\n setFavorites((prev) => {\r\n const next = new Set(prev);\r\n next.delete(deleteTarget.id);\r\n return next;\r\n });\r\n toast.success(t('deleteSuccess', { name: deleteTarget.name }))\r\n } catch (err) {\r\n console.error(err);\r\n toast.error(\r\n err instanceof Error\r\n ? t('deleteFailedWithReason', { error: err.message })\r\n : t('deleteFailed'),\r\n );\r\n } finally {\r\n setIsDeleting(false)\r\n setDeleteTarget(null)\r\n }\r\n };\r\n\r\n const toggleFavorite = (id: string) => {\r\n setFavorites((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(id)) next.delete(id);\r\n else next.add(id);\r\n return next;\r\n });\r\n };\r\n\r\n const filtered = React.useMemo(() => {\r\n return pointClouds.filter((pc) => {\r\n const matchesSearch =\r\n !search ||\r\n pc.name.toLowerCase().includes(search.toLowerCase()) ||\r\n pc.id.toLowerCase().includes(search.toLowerCase());\r\n\r\n let matchesStatus = true;\r\n if (statusFilter === \"uploaded\") {\r\n matchesStatus = pc.point_cloud_uploaded;\r\n } else if (statusFilter === \"converted\") {\r\n matchesStatus = pc.point_cloud_potree_converted;\r\n } else if (statusFilter === \"not-converted\") {\r\n matchesStatus =\r\n pc.point_cloud_uploaded && !pc.point_cloud_potree_converted;\r\n }\r\n\r\n return matchesSearch && matchesStatus;\r\n });\r\n }, [pointClouds, search, statusFilter]);\r\n\r\n return (\r\n <div className={`p-2 mt-20 ${divProps}`}>\r\n {/* Header */}\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"space-y-1\">\r\n <h1 className=\"text-2xl font-semibold tracking-tight\">\r\n Point Clouds\r\n </h1>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <Input\r\n placeholder=\"Search point clouds...\"\r\n className=\"w-[240px]\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n />\r\n <Button variant=\"outline\" size=\"icon\" title=\"Filters (not wired)\">\r\n <Filter className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"icon\"\r\n onClick={loadPointClouds}\r\n disabled={loading}\r\n title=\"Refresh\"\r\n >\r\n <RotateCcw className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Tabs row */}\r\n <Tabs\r\n value={statusFilter}\r\n onValueChange={(val) => setStatusFilter(val as StatusFilter)}\r\n className=\"w-full mb-2\"\r\n >\r\n <TabsList className=\"h-8\">\r\n <TabsTrigger value=\"all\" className=\"px-3\">\r\n All\r\n </TabsTrigger>\r\n <TabsTrigger value=\"uploaded\" className=\"px-3\">\r\n Uploaded\r\n </TabsTrigger>\r\n <TabsTrigger value=\"converted\" className=\"px-3\">\r\n Converted\r\n </TabsTrigger>\r\n <TabsTrigger value=\"not-converted\" className=\"px-3\">\r\n Needs conversion\r\n </TabsTrigger>\r\n </TabsList>\r\n </Tabs>\r\n\r\n {/* Table card */}\r\n <div className=\"rounded-md border bg-background\">\r\n <ScrollArea className=\"max-h-[520px]\">\r\n <Table>\r\n <TableHeader className=\"sticky top-0 z-10 bg-background/95 backdrop-blur\">\r\n <TableRow>\r\n <TableHead className=\"w-[40px] pl-4\">\r\n <Checkbox aria-label=\"Select all\" />\r\n </TableHead>\r\n <TableHead className=\"w-[48px]\"></TableHead>\r\n <TableHead className=\"min-w-[220px]\">Name</TableHead>\r\n <TableHead className=\"w-[200px]\">Status</TableHead>\r\n <TableHead className=\"w-[220px]\">Created</TableHead>\r\n <TableHead className=\"w-[160px]\">Metadata</TableHead>\r\n <TableHead className=\"w-[140px] text-right pr-4\">\r\n Actions\r\n </TableHead>\r\n </TableRow>\r\n </TableHeader>\r\n\r\n <TableBody>\r\n {loading && pointClouds.length === 0 && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n Loading point clouds…\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {!loading && error && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n <span className=\"text-sm text-destructive\">\r\n {error}\r\n </span>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {!loading && !error && filtered.length === 0 && (\r\n <TableRow>\r\n <TableCell colSpan={7} className=\"h-24 text-center\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n No point clouds found.\r\n </span>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n\r\n {filtered.map((pc) => {\r\n const isFavorite = favorites.has(pc.id);\r\n return (\r\n <TableRow\r\n key={pc.id}\r\n className=\"hover:bg-muted/50 transition-colors\"\r\n >\r\n <TableCell className=\"pl-4\">\r\n <Checkbox aria-label={`Select ${pc.name}`} />\r\n </TableCell>\r\n\r\n {/* Favorite star */}\r\n <TableCell className=\"text-center\">\r\n <button\r\n type=\"button\"\r\n onClick={() => toggleFavorite(pc.id)}\r\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-full text-muted-foreground hover:text-yellow-500\"\r\n aria-label={\r\n isFavorite\r\n ? `Remove ${pc.name} from favourites`\r\n : `Add ${pc.name} to favourites`\r\n }\r\n >\r\n {isFavorite ? (\r\n <Star className=\"h-4 w-4 fill-yellow-400\" />\r\n ) : (\r\n <StarOff className=\"h-4 w-4\" />\r\n )}\r\n </button>\r\n </TableCell>\r\n\r\n {/* Name & ID */}\r\n <TableCell>\r\n <div className=\"font-medium\">{pc.name}</div>\r\n <div className=\"text-xs text-muted-foreground\">\r\n {pc.id}\r\n </div>\r\n </TableCell>\r\n\r\n {/* Status badges */}\r\n <TableCell>\r\n <div className=\"flex flex-wrap gap-1\">\r\n <Badge\r\n className={`text-xs border ${\r\n pc.point_cloud_uploaded\r\n ? \"bg-emerald-50 text-emerald-700 border-emerald-200\"\r\n : \"bg-rose-50 text-rose-700 border-rose-200\"\r\n }`}\r\n >\r\n {pc.point_cloud_uploaded ? \"Uploaded\" : \"Not uploaded\"}\r\n </Badge>\r\n\r\n <Badge\r\n className={`text-xs border ${\r\n pc.point_cloud_potree_converted\r\n ? \"bg-sky-50 text-sky-700 border-sky-200\"\r\n : \"bg-amber-50 text-amber-700 border-amber-200\"\r\n }`}\r\n >\r\n {pc.point_cloud_potree_converted\r\n ? \"Ready to view\"\r\n : \"Needs conversion\"}\r\n </Badge>\r\n </div>\r\n </TableCell>\r\n\r\n {/* Created date */}\r\n <TableCell className=\"whitespace-nowrap text-sm text-muted-foreground\">\r\n {new Date(pc.createdAt).toLocaleString()}\r\n </TableCell>\r\n\r\n {/* Metadata link */}\r\n <TableCell>\r\n {pc.potree_metadata_presigned_url ? (\r\n <Button\r\n asChild\r\n variant=\"link\"\r\n size=\"sm\"\r\n className=\"px-0\"\r\n >\r\n <a\r\n href={pc.potree_metadata_presigned_url}\r\n target=\"_blank\"\r\n rel=\"noreferrer\"\r\n >\r\n metadata.json\r\n </a>\r\n </Button>\r\n ) : (\r\n <span className=\"text-xs text-muted-foreground\">—</span>\r\n )}\r\n </TableCell>\r\n\r\n {/* Actions */}\r\n <TableCell className=\"pr-4 text-right\">\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"icon\"\r\n disabled={!pc.potree_metadata_file_key}\r\n onClick={() =>\r\n openViewer(pc.id)\r\n }\r\n title=\"Open Potree viewer\"\r\n >\r\n <Eye className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"text-destructive hover:text-destructive\"\r\n onClick={() => setDeleteTarget(pc)}\r\n title={t('deleteTitle')}\r\n >\r\n <Trash2 className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </TableCell>\r\n </TableRow>\r\n );\r\n })}\r\n </TableBody>\r\n </Table>\r\n </ScrollArea>\r\n\r\n {/* Faux pagination / footer */}\r\n <div className=\"flex items-center justify-between border-t px-4 py-2 text-xs text-muted-foreground\">\r\n <div>\r\n Showing <span className=\"font-medium\">{filtered.length}</span> of{\" \"}\r\n <span className=\"font-medium\">{pointClouds.length}</span> point\r\n clouds\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <Button variant=\"ghost\" size=\"icon\" disabled>\r\n <ChevronLeft className=\"h-4 w-4\" />\r\n </Button>\r\n <Button variant=\"ghost\" size=\"icon\" disabled>\r\n <ChevronRight className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <Button\r\n onClick={() => {\r\n if (onUploadButtonClick != undefined){\r\n onUploadButtonClick()\r\n }\r\n }}\r\n className=\"mt-1 flex gap-2\"\r\n >\r\n Upload point cloud →\r\n </Button>\r\n\r\n <ConfirmDialog\r\n isOpen={deleteTarget != null}\r\n isDeleting={isDeleting}\r\n onOpenChange={(open) => {\r\n if (!open) setDeleteTarget(null)\r\n }}\r\n handleConfirm={async (e) => {\r\n e.preventDefault()\r\n await handleDelete()\r\n }}\r\n itemName={deleteTarget?.name}\r\n dataType={t('pointCloudItem')}\r\n />\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":["PAGE","pathname"]}
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
2
  type UploadPointCloudPageProps = {
3
3
  onGoBackButtonClick?: () => void;
4
+ pointcloudApiUrl?: string;
4
5
  };
5
- export default function UploadPointCloudPage({ onGoBackButtonClick, }: UploadPointCloudPageProps): React.JSX.Element;
6
+ export default function UploadPointCloudPage({ onGoBackButtonClick, pointcloudApiUrl, }: UploadPointCloudPageProps): React.JSX.Element;
6
7
  export {};
7
8
  //# sourceMappingURL=PointCloudUploadPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointCloudUploadPanel.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAyC/B,KAAK,yBAAyB,GAAG;IAC/B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,mBAAmB,GACpB,EAAE,yBAAyB,qBA2W3B"}
1
+ {"version":3,"file":"PointCloudUploadPanel.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAyC/B,KAAK,yBAAyB,GAAG;IAC/B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,mBAAmB,EACnB,gBAAgB,GACjB,EAAE,yBAAyB,qBA2X3B"}