@collabdt/core 0.0.56 → 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 (256) 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 +10 -7
  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 +3 -5
  16. package/dist/core/components/authentication/AuthPage.js.map +1 -1
  17. package/dist/core/components/authentication/Signin.d.ts +2 -1
  18. package/dist/core/components/authentication/Signin.d.ts.map +1 -1
  19. package/dist/core/components/authentication/Signin.js +2 -2
  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 -5
  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 -5
  53. package/dist/core/components/ui/AnimatedBackground.js.map +1 -1
  54. package/dist/core/components/ui/InfoSidebar/Container.d.ts +3 -1
  55. package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
  56. package/dist/core/components/ui/InfoSidebar/Container.js +4 -2
  57. package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
  58. package/dist/core/components/ui/InfoSidebar/Header.d.ts +3 -2
  59. package/dist/core/components/ui/InfoSidebar/Header.d.ts.map +1 -1
  60. package/dist/core/components/ui/InfoSidebar/Header.js +5 -6
  61. package/dist/core/components/ui/InfoSidebar/Header.js.map +1 -1
  62. package/dist/core/components/ui/InfoSidebar/index.d.ts +7 -1
  63. package/dist/core/components/ui/InfoSidebar/index.d.ts.map +1 -1
  64. package/dist/core/components/ui/InfoSidebar/index.js +4 -4
  65. package/dist/core/components/ui/InfoSidebar/index.js.map +1 -1
  66. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +2 -1
  67. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  68. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +3 -4
  69. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  70. package/dist/core/components/ui/Sensors/SensorsSection.d.ts +3 -1
  71. package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
  72. package/dist/core/components/ui/Sensors/SensorsSection.js +3 -1
  73. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  74. package/dist/core/components/ui/Sidebar.d.ts +8 -0
  75. package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
  76. package/dist/core/components/ui/Sidebar.js +21 -7
  77. package/dist/core/components/ui/Sidebar.js.map +1 -1
  78. package/dist/core/components/ui/ToolbarButton.js +18 -1
  79. package/dist/core/components/ui/ToolbarButton.js.map +1 -1
  80. package/dist/core/components/viewers/Data/DataMenu.d.ts +5 -1
  81. package/dist/core/components/viewers/Data/DataMenu.d.ts.map +1 -1
  82. package/dist/core/components/viewers/Data/DataMenu.js +6 -3
  83. package/dist/core/components/viewers/Data/DataMenu.js.map +1 -1
  84. package/dist/core/components/viewers/Data/HeaderButtons.d.ts +3 -1
  85. package/dist/core/components/viewers/Data/HeaderButtons.d.ts.map +1 -1
  86. package/dist/core/components/viewers/Data/HeaderButtons.js +6 -2
  87. package/dist/core/components/viewers/Data/HeaderButtons.js.map +1 -1
  88. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.d.ts +3 -1
  89. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.d.ts.map +1 -1
  90. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.js +4 -2
  91. package/dist/core/components/viewers/Data/buildingDetails/AddBuilding.js.map +1 -1
  92. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.d.ts +3 -1
  93. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.d.ts.map +1 -1
  94. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js +3 -1
  95. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js.map +1 -1
  96. package/dist/core/components/viewers/Data/details/DetailHeader.d.ts +2 -1
  97. package/dist/core/components/viewers/Data/details/DetailHeader.d.ts.map +1 -1
  98. package/dist/core/components/viewers/Data/details/DetailHeader.js +3 -5
  99. package/dist/core/components/viewers/Data/details/DetailHeader.js.map +1 -1
  100. package/dist/core/components/viewers/Viewer.d.ts +7 -1
  101. package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
  102. package/dist/core/components/viewers/Viewer.js +6 -6
  103. package/dist/core/components/viewers/Viewer.js.map +1 -1
  104. package/dist/core/components/viewers/bim/BimToolbar.d.ts +3 -1
  105. package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
  106. package/dist/core/components/viewers/bim/BimToolbar.js +2 -2
  107. package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
  108. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +3 -1
  109. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
  110. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
  111. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
  112. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.d.ts +5 -1
  113. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.d.ts.map +1 -1
  114. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +3 -2
  115. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
  116. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +3 -1
  117. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
  118. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +2 -2
  119. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
  120. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +1 -1
  121. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
  122. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +3 -5
  123. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
  124. package/dist/core/components/viewers/bim/src/tools/bimToolbar.d.ts +3 -1
  125. package/dist/core/components/viewers/bim/src/tools/bimToolbar.d.ts.map +1 -1
  126. package/dist/core/components/viewers/bim/src/tools/bimToolbar.js +4 -2
  127. package/dist/core/components/viewers/bim/src/tools/bimToolbar.js.map +1 -1
  128. package/dist/core/components/viewers/map/MapViewer.d.ts +3 -1
  129. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  130. package/dist/core/components/viewers/map/MapViewer.js +2 -2
  131. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  132. package/dist/core/components/viewers/map/datasets/RowActions.d.ts +2 -1
  133. package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
  134. package/dist/core/components/viewers/map/datasets/RowActions.js +5 -6
  135. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  136. package/dist/core/components/viewers/map/datasets/index.d.ts +5 -1
  137. package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
  138. package/dist/core/components/viewers/map/datasets/index.js +15 -16
  139. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  140. package/dist/core/components/viewers/map/src/Geocoder.d.ts +3 -1
  141. package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
  142. package/dist/core/components/viewers/map/src/Geocoder.js +5 -1
  143. package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
  144. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +6 -1
  145. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
  146. package/dist/core/components/viewers/map/src/MapLayers/index.js +3 -3
  147. package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
  148. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts +5 -1
  149. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
  150. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +6 -10
  151. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
  152. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +3 -1
  153. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
  154. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +4 -6
  155. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
  156. package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts +6 -1
  157. package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts.map +1 -1
  158. package/dist/core/components/viewers/map/src/MapSidebar/index.js +5 -4
  159. package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
  160. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.d.ts +5 -1
  161. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.d.ts.map +1 -1
  162. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js +5 -8
  163. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js.map +1 -1
  164. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +3 -1
  165. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
  166. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
  167. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
  168. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.d.ts +3 -1
  169. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.d.ts.map +1 -1
  170. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.js +2 -2
  171. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.js.map +1 -1
  172. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.d.ts +3 -1
  173. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.d.ts.map +1 -1
  174. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.js +4 -7
  175. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.js.map +1 -1
  176. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
  177. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +8 -8
  178. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
  179. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.d.ts +8 -1
  180. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.d.ts.map +1 -1
  181. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.js +8 -3
  182. package/dist/core/components/viewers/map/src/tools/AddTools/AddToMap.js.map +1 -1
  183. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.d.ts +11 -1
  184. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.d.ts.map +1 -1
  185. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.js +5 -3
  186. package/dist/core/components/viewers/map/src/tools/DatasetMapTool.js.map +1 -1
  187. package/dist/core/components/viewers/map/src/tools/mapTools.d.ts +10 -1
  188. package/dist/core/components/viewers/map/src/tools/mapTools.d.ts.map +1 -1
  189. package/dist/core/components/viewers/map/src/tools/mapTools.js +5 -3
  190. package/dist/core/components/viewers/map/src/tools/mapTools.js.map +1 -1
  191. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +14 -5
  192. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -1
  193. package/dist/core/components/viewers/map/utils/geocoding/config.js +22 -11
  194. package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -1
  195. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -1
  196. package/dist/core/components/viewers/map/utils/geocoding/index.js +2 -2
  197. package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -1
  198. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -1
  199. package/dist/core/components/viewers/map/utils/geocoding/osm.js +5 -4
  200. package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -1
  201. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -1
  202. package/dist/core/components/viewers/map/utils/geocoding/pelias.js +7 -5
  203. package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -1
  204. package/dist/core/components/viewers/pointcloud/PointCloudViewer.d.ts +3 -1
  205. package/dist/core/components/viewers/pointcloud/PointCloudViewer.d.ts.map +1 -1
  206. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +11 -14
  207. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
  208. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts +3 -1
  209. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts.map +1 -1
  210. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js +37 -52
  211. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js.map +1 -1
  212. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.d.ts +3 -1
  213. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.d.ts.map +1 -1
  214. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.js +5 -3
  215. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudManagementTable.js.map +1 -1
  216. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.d.ts +2 -1
  217. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.d.ts.map +1 -1
  218. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js +5 -6
  219. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js.map +1 -1
  220. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.d.ts +2 -1
  221. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.d.ts.map +1 -1
  222. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js +15 -9
  223. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js.map +1 -1
  224. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.d.ts +5 -1
  225. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.d.ts.map +1 -1
  226. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.js +3 -2
  227. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/index.js.map +1 -1
  228. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts +3 -1
  229. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
  230. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -2
  231. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
  232. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts +2 -1
  233. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  234. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js +12 -23
  235. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  236. package/dist/core/hooks/useCaptureScreenshot.d.ts +2 -0
  237. package/dist/core/hooks/useCaptureScreenshot.d.ts.map +1 -0
  238. package/dist/core/hooks/useCaptureScreenshot.js +63 -0
  239. package/dist/core/hooks/useCaptureScreenshot.js.map +1 -0
  240. package/dist/core/hooks/useGeocodingRuntimeConfig.d.ts +3 -0
  241. package/dist/core/hooks/useGeocodingRuntimeConfig.d.ts.map +1 -0
  242. package/dist/core/hooks/useGeocodingRuntimeConfig.js +17 -0
  243. package/dist/core/hooks/useGeocodingRuntimeConfig.js.map +1 -0
  244. package/dist/core/store/AppConfig/context.d.ts +5 -0
  245. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  246. package/dist/core/store/AppConfig/context.js.map +1 -1
  247. package/dist/core/store/CombineProviders.d.ts +6 -1
  248. package/dist/core/store/CombineProviders.d.ts.map +1 -1
  249. package/dist/core/store/CombineProviders.js +4 -3
  250. package/dist/core/store/CombineProviders.js.map +1 -1
  251. package/dist/core/types/tools.d.ts +2 -1
  252. package/dist/core/types/tools.d.ts.map +1 -1
  253. package/dist/core/utils/imageUtils.d.ts.map +1 -1
  254. package/dist/core/utils/imageUtils.js +2 -1
  255. package/dist/core/utils/imageUtils.js.map +1 -1
  256. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { Source, Layer } from 'react-map-gl/maplibre'\r\nimport type { MapMouseEvent } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../../store/Map/context'\r\nimport { useAppConfigContext } from '../../../../../../../store/AppConfig/context'\r\nimport { useSearchParams, useRouter } from 'next/navigation'\r\nimport { hexToRgba, buildSubdivisionUrl } from './countryLayerUtils'\r\n\r\nconst DEFAULT_BORDER_COLOR = '#73cee2'\r\n// satellite.json's openmaptiles source uses MapTiler's 'tiles/buildings' tileset which lacks the boundary + place layers. Pull both from the full openmaptiles v3 schema (same tileset blank.json uses).\r\nconst BOUNDARIES_SOURCE_ID = 'openmaptiles-boundaries'\r\n// Key is supplied by the consuming app via NEXT_PUBLIC_MAPTILER_KEY (Next inlines\r\n// it at build time). Kept out of source so @collabdt/core carries no secret.\r\nconst MAPTILER_KEY = process.env.NEXT_PUBLIC_MAPTILER_KEY\r\nconst BOUNDARIES_TILESET_URL = `https://api.maptiler.com/tiles/v3/tiles.json?key=${MAPTILER_KEY}`\r\nconst GLOBAL_LAYER_IDS = [\r\n 'global-borders-country',\r\n 'global-borders-region',\r\n 'global-labels-country',\r\n 'global-labels-state',\r\n 'global-labels-city',\r\n] as const\r\n\r\nfunction addGlobalBorderLayer(map: any, color: string) {\r\n try {\r\n if (!map.getSource(BOUNDARIES_SOURCE_ID)) {\r\n map.addSource(BOUNDARIES_SOURCE_ID, {\r\n type: 'vector',\r\n url: BOUNDARIES_TILESET_URL,\r\n })\r\n }\r\n\r\n // Country borders — visible at all zooms, slightly thinner up close where states take over.\r\n if (!map.getLayer('global-borders-country')) {\r\n map.addLayer({\r\n id: 'global-borders-country',\r\n type: 'line',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'boundary',\r\n filter: ['all', ['==', 'admin_level', 2], ['==', 'maritime', 0]],\r\n layout: { 'line-cap': 'round', 'line-join': 'round' },\r\n paint: {\r\n 'line-color': color,\r\n 'line-width': { base: 1, stops: [[0, 0.8], [4, 1.4], [10, 1.4], [14, 1]] },\r\n },\r\n })\r\n }\r\n\r\n // State / province borders — fade in around zoom 3, dominate from 5+.\r\n if (!map.getLayer('global-borders-region')) {\r\n map.addLayer({\r\n id: 'global-borders-region',\r\n type: 'line',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'boundary',\r\n filter: ['all', ['in', 'admin_level', 3, 4], ['==', 'maritime', 0]],\r\n minzoom: 2,\r\n layout: { 'line-cap': 'round', 'line-join': 'round' },\r\n paint: {\r\n 'line-color': color,\r\n 'line-width': { base: 1, stops: [[2, 0], [4, 0.5], [8, 1.4], [14, 2.4]] },\r\n 'line-opacity': { base: 1, stops: [[2, 0], [4, 0.7], [6, 1]] },\r\n },\r\n })\r\n }\r\n\r\n // Country labels — small/global up to zoom ~6, gone by 8.\r\n if (!map.getLayer('global-labels-country')) {\r\n map.addLayer({\r\n id: 'global-labels-country',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['==', 'class', 'country'],\r\n minzoom: 1,\r\n maxzoom: 8,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[1, 10], [4, 13], [6, 16]] },\r\n 'text-letter-spacing': 0.1,\r\n 'text-max-width': 8,\r\n 'text-transform': 'uppercase',\r\n },\r\n paint: {\r\n 'text-color': '#ffffff',\r\n 'text-halo-color': 'rgba(0,0,0,0.7)',\r\n 'text-halo-width': 1.2,\r\n 'text-opacity': { base: 1, stops: [[5, 1], [7, 0]] },\r\n },\r\n })\r\n }\r\n\r\n // State / province labels — cover zoom 3–8.\r\n if (!map.getLayer('global-labels-state')) {\r\n map.addLayer({\r\n id: 'global-labels-state',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['in', 'class', 'state', 'province'],\r\n minzoom: 3,\r\n maxzoom: 9,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[3, 9], [6, 12], [8, 14]] },\r\n 'text-letter-spacing': 0.05,\r\n 'text-max-width': 8,\r\n },\r\n paint: {\r\n 'text-color': '#e8e8e8',\r\n 'text-halo-color': 'rgba(0,0,0,0.6)',\r\n 'text-halo-width': 1,\r\n 'text-opacity': { base: 1, stops: [[3, 0], [4, 1], [8, 1], [9, 0]] },\r\n },\r\n })\r\n }\r\n\r\n // Major city labels (rank ≤ 4 = most prominent cities) — appear when zoomed in past country level.\r\n if (!map.getLayer('global-labels-city')) {\r\n map.addLayer({\r\n id: 'global-labels-city',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['in', 'class', 'city', 'town'],\r\n minzoom: 5,\r\n maxzoom: 13,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[5, 10], [9, 13], [12, 15]] },\r\n 'text-max-width': 8,\r\n },\r\n paint: {\r\n 'text-color': '#dcdcdc',\r\n 'text-halo-color': 'rgba(0,0,0,0.7)',\r\n 'text-halo-width': 1.1,\r\n },\r\n })\r\n }\r\n } catch {\r\n // style may be in a transitional state\r\n }\r\n}\r\n\r\nexport const CountryLayer = () => {\r\n const { state: mapState, dispatch: mapDispatch } = React.useContext(MapContext)\r\n const { map, currentLocation } = mapState.map\r\n const { state: appConfigState } = useAppConfigContext()\r\n const organization = appConfigState.appConfig.organization\r\n const searchParams = useSearchParams()\r\n const router = useRouter()\r\n const debounceRef = React.useRef<NodeJS.Timeout | null>(null)\r\n\r\n const countryCode = (organization?.country || 'CA').toUpperCase()\r\n const borderColor = hexToRgba((organization?.mainColor as string) || DEFAULT_BORDER_COLOR, 0.7)\r\n const subdivisionUrl = buildSubdivisionUrl(countryCode)\r\n\r\n // Add the global boundary line layer imperatively (vector-tile lines from the style's openmaptiles source). Re-adds on style swap so it survives basemap changes.\r\n React.useEffect(() => {\r\n if (!map) return\r\n const addNow = () => addGlobalBorderLayer(map, borderColor)\r\n if (map.isStyleLoaded()) addNow()\r\n map.on('styledata', addNow)\r\n return () => {\r\n try {\r\n map.off('styledata', addNow)\r\n for (const id of GLOBAL_LAYER_IDS) {\r\n if (map.getLayer(id)) map.removeLayer(id)\r\n }\r\n } catch {\r\n // map may be destroyed\r\n }\r\n }\r\n }, [map, borderColor])\r\n\r\n // If the org already has a fixed subdivision or municipality, lock them in and skip hover\r\n const orgHasLocation = !!(organization?.countrySubdivision || organization?.municipality)\r\n\r\n // When org has fixed location values, push them into currentLocation once\r\n React.useEffect(() => {\r\n if (!orgHasLocation) return\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: {\r\n currentLocation: {\r\n ...(currentLocation ?? {}),\r\n countrySubdivision: organization?.countrySubdivision ?? currentLocation?.countrySubdivision,\r\n municipality: organization?.municipality ?? currentLocation?.municipality,\r\n } as any,\r\n },\r\n })\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [orgHasLocation])\r\n\r\n React.useEffect(() => {\r\n if (orgHasLocation) return\r\n if (!(map && currentLocation)) return\r\n\r\n const currentCountrySubdivision = currentLocation.countrySubdivision || null\r\n const currentMunicipality = currentLocation.municipality || null\r\n\r\n function onMouseMove(e: MapMouseEvent) {\r\n if (!map.isStyleLoaded()) return\r\n\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n\r\n const eventPoint = e.point\r\n\r\n debounceRef.current = setTimeout(() => {\r\n const features = map.queryRenderedFeatures(eventPoint, {\r\n layers: ['admin-subdivisions-fill'],\r\n })\r\n\r\n // if (features.length > 0) {\r\n // console.group('[CountryLayer] hover')\r\n // features.forEach(f => console.log(f.properties))\r\n // console.groupEnd()\r\n // }\r\n\r\n let newCountrySubdivision = null\r\n\r\n if (features.length > 0) {\r\n const f = features[0]\r\n const isoCC = f.properties?.ISO_CC\r\n const isoCode = f.properties?.ISO_CODE\r\n // Build \"CA-ON\" from ISO_CC \"CA\" + ISO_CODE \"CAON\" → strip prefix to get \"ON\"\r\n if (isoCC && isoCode && isoCode.startsWith(isoCC)) {\r\n newCountrySubdivision = `${isoCC}-${isoCode.slice(isoCC.length)}`\r\n } else {\r\n newCountrySubdivision = (isoCode || f.properties?.NAME || null) as string | null\r\n }\r\n }\r\n\r\n const finalCountrySubdivision = newCountrySubdivision || currentCountrySubdivision\r\n\r\n if (finalCountrySubdivision !== currentCountrySubdivision) {\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: {\r\n currentLocation: {\r\n ...currentLocation,\r\n countrySubdivision: finalCountrySubdivision,\r\n municipality: currentMunicipality,\r\n },\r\n },\r\n })\r\n\r\n const params = new URLSearchParams(searchParams.toString())\r\n params.set('countrySubdivision', finalCountrySubdivision || '')\r\n router.replace(`?${params.toString()}`, { scroll: false })\r\n }\r\n }, 300)\r\n }\r\n\r\n if (map.isStyleLoaded()) {\r\n map.on('mousemove', onMouseMove)\r\n } else {\r\n map.once('styledata', () => {\r\n map.on('mousemove', onMouseMove)\r\n })\r\n }\r\n\r\n return () => {\r\n map.off('mousemove', onMouseMove)\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [map, mapDispatch, currentLocation, searchParams, router])\r\n\r\n if (orgHasLocation) return null\r\n\r\n // Invisible ArcGIS subdivision polygons for hover hit-detection (only mounted when the org hasn't locked a subdivision). The visible borders come from the imperative openmaptiles layer above.\r\n return (\r\n <Source\r\n id=\"admin-subdivisions-source\"\r\n type=\"geojson\"\r\n data={subdivisionUrl}\r\n >\r\n <Layer\r\n id=\"admin-subdivisions-fill\"\r\n type=\"fill\"\r\n paint={{ 'fill-color': 'transparent', 'fill-opacity': 0 }}\r\n />\r\n </Source>\r\n )\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6RM;AAxRN,YAAY,WAAW;AACvB,SAAS,QAAQ,aAAa;AAE9B,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AACpC,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,WAAW,2BAA2B;AAE/C,MAAM,uBAAuB;AAE7B,MAAM,uBAAuB;AAG7B,MAAM,eAAe,QAAQ,IAAI;AACjC,MAAM,yBAAyB,oDAAoD,YAAY;AAC/F,MAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,qBAAqB,KAAU,OAAe;AACrD,MAAI;AACF,QAAI,CAAC,IAAI,UAAU,oBAAoB,GAAG;AACxC,UAAI,UAAU,sBAAsB;AAAA,QAClC,MAAM;AAAA,QACN,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,IAAI,SAAS,wBAAwB,GAAG;AAC3C,UAAI,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,CAAC,OAAO,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,MAAM,YAAY,CAAC,CAAC;AAAA,QAC/D,QAAQ,EAAE,YAAY,SAAS,aAAa,QAAQ;AAAA,QACpD,OAAO;AAAA,UACL,cAAc;AAAA,UACd,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE;AAAA,QAC3E;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,IAAI,SAAS,uBAAuB,GAAG;AAC1C,UAAI,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,CAAC,OAAO,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,MAAM,YAAY,CAAC,CAAC;AAAA,QAClE,SAAS;AAAA,QACT,QAAQ,EAAE,YAAY,SAAS,aAAa,QAAQ;AAAA,QACpD,OAAO;AAAA,UACL,cAAc;AAAA,UACd,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE;AAAA,UACxE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,IAAI,SAAS,uBAAuB,GAAG;AAC1C,UAAI,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,CAAC,MAAM,SAAS,SAAS;AAAA,QACjC,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,cAAc,CAAC,YAAY,CAAC,OAAO,YAAY,GAAG,CAAC,OAAO,MAAM,CAAC;AAAA,UACjE,aAAa,CAAC,mBAAmB;AAAA,UACjC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE;AAAA,UAC3D,uBAAuB;AAAA,UACvB,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,QACpB;AAAA,QACA,OAAO;AAAA,UACL,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,mBAAmB;AAAA,UACnB,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;AAAA,QACrD;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,IAAI,SAAS,qBAAqB,GAAG;AACxC,UAAI,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,CAAC,MAAM,SAAS,SAAS,UAAU;AAAA,QAC3C,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,cAAc,CAAC,YAAY,CAAC,OAAO,YAAY,GAAG,CAAC,OAAO,MAAM,CAAC;AAAA,UACjE,aAAa,CAAC,mBAAmB;AAAA,UACjC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE;AAAA,UAC1D,uBAAuB;AAAA,UACvB,kBAAkB;AAAA,QACpB;AAAA,QACA,OAAO;AAAA,UACL,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,mBAAmB;AAAA,UACnB,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;AAAA,QACrE;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,IAAI,SAAS,oBAAoB,GAAG;AACvC,UAAI,SAAS;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,CAAC,MAAM,SAAS,QAAQ,MAAM;AAAA,QACtC,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,cAAc,CAAC,YAAY,CAAC,OAAO,YAAY,GAAG,CAAC,OAAO,MAAM,CAAC;AAAA,UACjE,aAAa,CAAC,mBAAmB;AAAA,UACjC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE;AAAA,UAC5D,kBAAkB;AAAA,QACpB;AAAA,QACA,OAAO;AAAA,UACL,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,mBAAmB;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAQ;AAAA,EAER;AACF;AAEO,MAAM,eAAe,MAAM;AAChC,QAAM,EAAE,OAAO,UAAU,UAAU,YAAY,IAAI,MAAM,WAAW,UAAU;AAC9E,QAAM,EAAE,KAAK,gBAAgB,IAAI,SAAS;AAC1C,QAAM,EAAE,OAAO,eAAe,IAAI,oBAAoB;AACtD,QAAM,eAAe,eAAe,UAAU;AAC9C,QAAM,eAAe,gBAAgB;AACrC,QAAM,SAAS,UAAU;AACzB,QAAM,cAAc,MAAM,OAA8B,IAAI;AAE5D,QAAM,gBAAe,6CAAc,YAAW,MAAM,YAAY;AAChE,QAAM,cAAc,WAAW,6CAAc,cAAwB,sBAAsB,GAAG;AAC9F,QAAM,iBAAiB,oBAAoB,WAAW;AAGtD,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,IAAK;AACV,UAAM,SAAS,MAAM,qBAAqB,KAAK,WAAW;AAC1D,QAAI,IAAI,cAAc,EAAG,QAAO;AAChC,QAAI,GAAG,aAAa,MAAM;AAC1B,WAAO,MAAM;AACX,UAAI;AACF,YAAI,IAAI,aAAa,MAAM;AAC3B,mBAAW,MAAM,kBAAkB;AACjC,cAAI,IAAI,SAAS,EAAE,EAAG,KAAI,YAAY,EAAE;AAAA,QAC1C;AAAA,MACF,SAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,WAAW,CAAC;AAGrB,QAAM,iBAAiB,CAAC,GAAE,6CAAc,wBAAsB,6CAAc;AAG5E,QAAM,UAAU,MAAM;AA3LxB;AA4LI,QAAI,CAAC,eAAgB;AACrB,gBAAY;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,QACP,iBAAiB,iCACX,4CAAmB,CAAC,IADT;AAAA,UAEf,qBAAoB,kDAAc,uBAAd,YAAoC,mDAAiB;AAAA,UACzE,eAAc,kDAAc,iBAAd,YAA8B,mDAAiB;AAAA,QAC/D;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EAEH,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,UAAU,MAAM;AACpB,QAAI,eAAgB;AACpB,QAAI,EAAE,OAAO,iBAAkB;AAE/B,UAAM,4BAA4B,gBAAgB,sBAAsB;AACxE,UAAM,sBAAsB,gBAAgB,gBAAgB;AAE5D,aAAS,YAAY,GAAkB;AACrC,UAAI,CAAC,IAAI,cAAc,EAAG;AAE1B,UAAI,YAAY,QAAS,cAAa,YAAY,OAAO;AAEzD,YAAM,aAAa,EAAE;AAErB,kBAAY,UAAU,WAAW,MAAM;AAxN7C;AAyNQ,cAAM,WAAW,IAAI,sBAAsB,YAAY;AAAA,UACrD,QAAQ,CAAC,yBAAyB;AAAA,QACpC,CAAC;AAQD,YAAI,wBAAwB;AAE5B,YAAI,SAAS,SAAS,GAAG;AACvB,gBAAM,IAAI,SAAS,CAAC;AACpB,gBAAM,SAAQ,OAAE,eAAF,mBAAc;AAC5B,gBAAM,WAAU,OAAE,eAAF,mBAAc;AAE9B,cAAI,SAAS,WAAW,QAAQ,WAAW,KAAK,GAAG;AACjD,oCAAwB,GAAG,KAAK,IAAI,QAAQ,MAAM,MAAM,MAAM,CAAC;AAAA,UACjE,OAAO;AACL,oCAAyB,aAAW,OAAE,eAAF,mBAAc,SAAQ;AAAA,UAC5D;AAAA,QACF;AAEA,cAAM,0BAA0B,yBAAyB;AAEzD,YAAI,4BAA4B,2BAA2B;AACzD,sBAAY;AAAA,YACV,MAAM;AAAA,YACN,SAAS;AAAA,cACP,iBAAiB,iCACZ,kBADY;AAAA,gBAEf,oBAAoB;AAAA,gBACpB,cAAc;AAAA,cAChB;AAAA,YACF;AAAA,UACF,CAAC;AAED,gBAAM,SAAS,IAAI,gBAAgB,aAAa,SAAS,CAAC;AAC1D,iBAAO,IAAI,sBAAsB,2BAA2B,EAAE;AAC9D,iBAAO,QAAQ,IAAI,OAAO,SAAS,CAAC,IAAI,EAAE,QAAQ,MAAM,CAAC;AAAA,QAC3D;AAAA,MACF,GAAG,GAAG;AAAA,IACR;AAEA,QAAI,IAAI,cAAc,GAAG;AACvB,UAAI,GAAG,aAAa,WAAW;AAAA,IACjC,OAAO;AACL,UAAI,KAAK,aAAa,MAAM;AAC1B,YAAI,GAAG,aAAa,WAAW;AAAA,MACjC,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,UAAI,IAAI,aAAa,WAAW;AAChC,UAAI,YAAY,QAAS,cAAa,YAAY,OAAO;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,KAAK,aAAa,iBAAiB,cAAc,MAAM,CAAC;AAE5D,MAAI,eAAgB,QAAO;AAG3B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAG;AAAA,MACH,MAAK;AAAA,MACL,MAAM;AAAA,MAEN;AAAA,QAAC;AAAA;AAAA,UACC,IAAG;AAAA,UACH,MAAK;AAAA,UACL,OAAO,EAAE,cAAc,eAAe,gBAAgB,EAAE;AAAA;AAAA,MAC1D;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { Source, Layer } from 'react-map-gl/maplibre'\r\nimport type { MapMouseEvent } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../../store/Map/context'\r\nimport { useSearchParams, useRouter } from 'next/navigation'\r\nimport { hexToRgba, buildSubdivisionUrl } from './countryLayerUtils'\r\nimport type { Organization } from '../../../../../../../types/dbTypes'\r\n\r\nconst DEFAULT_BORDER_COLOR = '#73cee2'\r\nconst BOUNDARIES_SOURCE_ID = 'openmaptiles-boundaries'\r\nconst GLOBAL_LAYER_IDS = [\r\n 'global-borders-country',\r\n 'global-borders-region',\r\n 'global-labels-country',\r\n 'global-labels-state',\r\n 'global-labels-city',\r\n] as const\r\n\r\nfunction addGlobalBorderLayer(map: any, color: string, maptilerKey?: string) {\r\n if (!maptilerKey) return\r\n try {\r\n if (!map.getSource(BOUNDARIES_SOURCE_ID)) {\r\n map.addSource(BOUNDARIES_SOURCE_ID, {\r\n type: 'vector',\r\n url: `https://api.maptiler.com/tiles/v3/tiles.json?key=${maptilerKey}`,\r\n })\r\n }\r\n\r\n // Country borders — visible at all zooms, slightly thinner up close where states take over.\r\n if (!map.getLayer('global-borders-country')) {\r\n map.addLayer({\r\n id: 'global-borders-country',\r\n type: 'line',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'boundary',\r\n filter: ['all', ['==', 'admin_level', 2], ['==', 'maritime', 0]],\r\n layout: { 'line-cap': 'round', 'line-join': 'round' },\r\n paint: {\r\n 'line-color': color,\r\n 'line-width': { base: 1, stops: [[0, 0.8], [4, 1.4], [10, 1.4], [14, 1]] },\r\n },\r\n })\r\n }\r\n\r\n // State / province borders — fade in around zoom 3, dominate from 5+.\r\n if (!map.getLayer('global-borders-region')) {\r\n map.addLayer({\r\n id: 'global-borders-region',\r\n type: 'line',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'boundary',\r\n filter: ['all', ['in', 'admin_level', 3, 4], ['==', 'maritime', 0]],\r\n minzoom: 2,\r\n layout: { 'line-cap': 'round', 'line-join': 'round' },\r\n paint: {\r\n 'line-color': color,\r\n 'line-width': { base: 1, stops: [[2, 0], [4, 0.5], [8, 1.4], [14, 2.4]] },\r\n 'line-opacity': { base: 1, stops: [[2, 0], [4, 0.7], [6, 1]] },\r\n },\r\n })\r\n }\r\n\r\n // Country labels — small/global up to zoom ~6, gone by 8.\r\n if (!map.getLayer('global-labels-country')) {\r\n map.addLayer({\r\n id: 'global-labels-country',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['==', 'class', 'country'],\r\n minzoom: 1,\r\n maxzoom: 8,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[1, 10], [4, 13], [6, 16]] },\r\n 'text-letter-spacing': 0.1,\r\n 'text-max-width': 8,\r\n 'text-transform': 'uppercase',\r\n },\r\n paint: {\r\n 'text-color': '#ffffff',\r\n 'text-halo-color': 'rgba(0,0,0,0.7)',\r\n 'text-halo-width': 1.2,\r\n 'text-opacity': { base: 1, stops: [[5, 1], [7, 0]] },\r\n },\r\n })\r\n }\r\n\r\n // State / province labels — cover zoom 3–8.\r\n if (!map.getLayer('global-labels-state')) {\r\n map.addLayer({\r\n id: 'global-labels-state',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['in', 'class', 'state', 'province'],\r\n minzoom: 3,\r\n maxzoom: 9,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[3, 9], [6, 12], [8, 14]] },\r\n 'text-letter-spacing': 0.05,\r\n 'text-max-width': 8,\r\n },\r\n paint: {\r\n 'text-color': '#e8e8e8',\r\n 'text-halo-color': 'rgba(0,0,0,0.6)',\r\n 'text-halo-width': 1,\r\n 'text-opacity': { base: 1, stops: [[3, 0], [4, 1], [8, 1], [9, 0]] },\r\n },\r\n })\r\n }\r\n\r\n // Major city labels (rank ≤ 4 = most prominent cities) — appear when zoomed in past country level.\r\n if (!map.getLayer('global-labels-city')) {\r\n map.addLayer({\r\n id: 'global-labels-city',\r\n type: 'symbol',\r\n source: BOUNDARIES_SOURCE_ID,\r\n 'source-layer': 'place',\r\n filter: ['in', 'class', 'city', 'town'],\r\n minzoom: 5,\r\n maxzoom: 13,\r\n layout: {\r\n 'text-field': ['coalesce', ['get', 'name:latin'], ['get', 'name']],\r\n 'text-font': ['Noto Sans Regular'],\r\n 'text-size': { base: 1, stops: [[5, 10], [9, 13], [12, 15]] },\r\n 'text-max-width': 8,\r\n },\r\n paint: {\r\n 'text-color': '#dcdcdc',\r\n 'text-halo-color': 'rgba(0,0,0,0.7)',\r\n 'text-halo-width': 1.1,\r\n },\r\n })\r\n }\r\n } catch {\r\n // style may be in a transitional state\r\n }\r\n}\r\n\r\nexport const CountryLayer = ({ organization, maptilerKey }: { organization?: Organization; maptilerKey?: string }) => {\r\n const { state: mapState, dispatch: mapDispatch } = React.useContext(MapContext)\r\n const { map, currentLocation } = mapState.map\r\n const searchParams = useSearchParams()\r\n const router = useRouter()\r\n const debounceRef = React.useRef<NodeJS.Timeout | null>(null)\r\n\r\n const countryCode = (organization?.country || 'CA').toUpperCase()\r\n const borderColor = hexToRgba((organization?.mainColor as string) || DEFAULT_BORDER_COLOR, 0.7)\r\n const subdivisionUrl = buildSubdivisionUrl(countryCode)\r\n\r\n // Add the global boundary line layer imperatively (vector-tile lines from the style's openmaptiles source). Re-adds on style swap so it survives basemap changes.\r\n React.useEffect(() => {\r\n if (!map) return\r\n const addNow = () => addGlobalBorderLayer(map, borderColor, maptilerKey)\r\n if (map.isStyleLoaded()) addNow()\r\n map.on('styledata', addNow)\r\n return () => {\r\n try {\r\n map.off('styledata', addNow)\r\n for (const id of GLOBAL_LAYER_IDS) {\r\n if (map.getLayer(id)) map.removeLayer(id)\r\n }\r\n } catch {\r\n // map may be destroyed\r\n }\r\n }\r\n }, [map, borderColor, maptilerKey])\r\n\r\n // If the org already has a fixed subdivision or municipality, lock them in and skip hover\r\n const orgHasLocation = !!(organization?.countrySubdivision || organization?.municipality)\r\n\r\n // When org has fixed location values, push them into currentLocation once\r\n React.useEffect(() => {\r\n if (!orgHasLocation) return\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: {\r\n currentLocation: {\r\n ...(currentLocation ?? {}),\r\n countrySubdivision: organization?.countrySubdivision ?? currentLocation?.countrySubdivision,\r\n municipality: organization?.municipality ?? currentLocation?.municipality,\r\n } as any,\r\n },\r\n })\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [orgHasLocation])\r\n\r\n React.useEffect(() => {\r\n if (orgHasLocation) return\r\n if (!(map && currentLocation)) return\r\n\r\n const currentCountrySubdivision = currentLocation.countrySubdivision || null\r\n const currentMunicipality = currentLocation.municipality || null\r\n\r\n function onMouseMove(e: MapMouseEvent) {\r\n if (!map.isStyleLoaded()) return\r\n\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n\r\n const eventPoint = e.point\r\n\r\n debounceRef.current = setTimeout(() => {\r\n const features = map.queryRenderedFeatures(eventPoint, {\r\n layers: ['admin-subdivisions-fill'],\r\n })\r\n\r\n // if (features.length > 0) {\r\n // console.group('[CountryLayer] hover')\r\n // features.forEach(f => console.log(f.properties))\r\n // console.groupEnd()\r\n // }\r\n\r\n let newCountrySubdivision = null\r\n\r\n if (features.length > 0) {\r\n const f = features[0]\r\n const isoCC = f.properties?.ISO_CC\r\n const isoCode = f.properties?.ISO_CODE\r\n // Build \"CA-ON\" from ISO_CC \"CA\" + ISO_CODE \"CAON\" → strip prefix to get \"ON\"\r\n if (isoCC && isoCode && isoCode.startsWith(isoCC)) {\r\n newCountrySubdivision = `${isoCC}-${isoCode.slice(isoCC.length)}`\r\n } else {\r\n newCountrySubdivision = (isoCode || f.properties?.NAME || null) as string | null\r\n }\r\n }\r\n\r\n const finalCountrySubdivision = newCountrySubdivision || currentCountrySubdivision\r\n\r\n if (finalCountrySubdivision !== currentCountrySubdivision) {\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: {\r\n currentLocation: {\r\n ...currentLocation,\r\n countrySubdivision: finalCountrySubdivision,\r\n municipality: currentMunicipality,\r\n },\r\n },\r\n })\r\n\r\n const params = new URLSearchParams(searchParams.toString())\r\n params.set('countrySubdivision', finalCountrySubdivision || '')\r\n router.replace(`?${params.toString()}`, { scroll: false })\r\n }\r\n }, 300)\r\n }\r\n\r\n if (map.isStyleLoaded()) {\r\n map.on('mousemove', onMouseMove)\r\n } else {\r\n map.once('styledata', () => {\r\n map.on('mousemove', onMouseMove)\r\n })\r\n }\r\n\r\n return () => {\r\n map.off('mousemove', onMouseMove)\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [map, mapDispatch, currentLocation, searchParams, router])\r\n\r\n if (orgHasLocation) return null\r\n\r\n // Invisible ArcGIS subdivision polygons for hover hit-detection (only mounted when the org hasn't locked a subdivision). The visible borders come from the imperative openmaptiles layer above.\r\n return (\r\n <Source\r\n id=\"admin-subdivisions-source\"\r\n type=\"geojson\"\r\n data={subdivisionUrl}\r\n >\r\n <Layer\r\n id=\"admin-subdivisions-fill\"\r\n type=\"fill\"\r\n paint={{ 'fill-color': 'transparent', 'fill-opacity': 0 }}\r\n />\r\n </Source>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,3 +1,5 @@
1
1
  import * as React from 'react';
2
- export declare const SensorLayers: () => React.JSX.Element;
2
+ export declare const SensorLayers: ({ minioBaseUrl }: {
3
+ minioBaseUrl?: string;
4
+ }) => React.JSX.Element;
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqD9B,eAAO,MAAM,YAAY,yBA6TxB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAoD9B,eAAO,MAAM,YAAY,GAAI,kBAAkB;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,sBA4TvE,CAAA"}
@@ -34,7 +34,6 @@ import { useSession } from "next-auth/react";
34
34
  import { createClusterLayer, createClusterCountLayer, createUnclusteredPointLayer } from "../mapLayersUtils";
35
35
  import { useSensorTypes } from "../../../../../../../hooks/sensorTypes/sensorTypes";
36
36
  import * as LR from "lucide-react";
37
- import { useAppConfigContext } from "../../../../../../../store/AppConfig/context";
38
37
  import { UNTAGGED_TAG } from "../../../../../../ui/Sensors/SensorsSection";
39
38
  const SensorIconMarker = ({ feature, isHighlighted, onMouseEnter, onMouseLeave, sensorTypes }) => {
40
39
  var _a, _b;
@@ -68,7 +67,7 @@ const SensorIconMarker = ({ feature, isHighlighted, onMouseEnter, onMouseLeave,
68
67
  }
69
68
  ) }, String((_b = (_a = feature.properties) == null ? void 0 : _a.id) != null ? _b : `${coords.lng},${coords.lat}`));
70
69
  };
71
- const SensorLayers = () => {
70
+ const SensorLayers = ({ minioBaseUrl }) => {
72
71
  var _a, _b;
73
72
  const [hoveredSensorId, setHoveredSensorId] = React.useState(null);
74
73
  const clusterLayer = createClusterLayer("sensors");
@@ -76,7 +75,6 @@ const SensorLayers = () => {
76
75
  const unclusteredPointLayer = createUnclusteredPointLayer("sensors");
77
76
  const t = useTranslations("SensorLayers");
78
77
  const tSensors = useTranslations("SensorsSection");
79
- const { state: appConfigState } = useAppConfigContext();
80
78
  const { state: mapState } = React.useContext(MapContext);
81
79
  const { map, mapClickManager } = mapState.map;
82
80
  const { sensors } = useSensors();
@@ -230,11 +228,11 @@ const SensorLayers = () => {
230
228
  };
231
229
  }, [map]);
232
230
  const renderPopup = () => {
233
- var _a2, _b2;
231
+ var _a2;
234
232
  if (!popupInfo) return null;
235
233
  const sensorType = sensorTypes.find((t2) => t2.id === popupInfo.typeId);
236
234
  const liveSensor = sensors.find((s) => s.id === popupInfo.id);
237
- const dataUrl = popupInfo.url ? `${(_a2 = appConfigState.runtimeConfig.minioUrl) != null ? _a2 : ""}/sensors/${popupInfo.url}` : popupInfo.data || "";
235
+ const dataUrl = popupInfo.url ? `${minioBaseUrl != null ? minioBaseUrl : ""}/sensors/${popupInfo.url}` : popupInfo.data || "";
238
236
  return /* @__PURE__ */ jsxs(
239
237
  Popup,
240
238
  {
@@ -253,7 +251,7 @@ const SensorLayers = () => {
253
251
  sensorName: popupInfo.name || "",
254
252
  sensorType,
255
253
  sensorId: popupInfo.id,
256
- tags: (_b2 = liveSensor == null ? void 0 : liveSensor.tags) != null ? _b2 : [],
254
+ tags: (_a2 = liveSensor == null ? void 0 : liveSensor.tags) != null ? _a2 : [],
257
255
  onAddTag: async (tag) => {
258
256
  var _a3;
259
257
  await updateSensor({ tags: [...(_a3 = liveSensor == null ? void 0 : liveSensor.tags) != null ? _a3 : [], tag] });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/SensorsLayer/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 { MapContext, MenusContext } from '../../../../../../../store'\r\nimport * as React from 'react'\r\nimport { Source, Layer, Popup, Marker } from 'react-map-gl/maplibre'\r\nimport type { MapGeoJSONFeature, MapLayerMouseEvent } from 'maplibre-gl'\r\nimport Sensor from '../../../../../../ui/Sensors/Sensor'\r\nimport { SensorType, ViewerNames, type Sensor as ISensor} from '../../../../../../../types/dbTypes'\r\n\r\nimport { MapLayerClickPriority, ClickCallback } from '../../../../utils/MapEventManager/MapClickManager'\r\nimport { extractCoordinatesFromFeature } from '../../../../utils/extractCoordinates'\r\nimport { useSensor, useSensors } from '../../../../../../../hooks/sensors/sensors'\r\nimport { useUsers } from '../../../../../../../hooks/users/users'\r\nimport { toast } from 'sonner'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { createClusterLayer, createClusterCountLayer, createUnclusteredPointLayer } from '../mapLayersUtils'\r\nimport { useSensorTypes } from '../../../../../../../hooks/sensorTypes/sensorTypes'\r\nimport * as LR from 'lucide-react'\r\nimport { useAppConfigContext } from '../../../../../../../store/AppConfig/context'\r\nimport { UNTAGGED_TAG } from '../../../../../../ui/Sensors/SensorsSection'\r\n\r\nconst SensorIconMarker = ({ feature, isHighlighted, onMouseEnter, onMouseLeave, sensorTypes }: { feature: MapGeoJSONFeature; isHighlighted?: boolean; onMouseEnter?: () => void; onMouseLeave?: () => void; sensorTypes: SensorType[] }) => {\r\n\r\n const coords = extractCoordinatesFromFeature(feature)\r\n if (!coords) return null\r\n\r\n const sensorType = sensorTypes.find(t => t.id === feature.properties?.typeId)\r\n const icon = sensorType?.icon || 'Radio'\r\n const SensorIcon = LR[icon] || LR.Radio\r\n\r\n return (\r\n <Marker key={String(feature.properties?.id ?? `${coords.lng},${coords.lat}`)} longitude={coords.lng} latitude={coords.lat} anchor=\"center\">\r\n <div\r\n style={{\r\n width: '36px',\r\n height: '36px',\r\n borderRadius: '50%',\r\n border: isHighlighted ? '3px solid #73cee2' : '2px solid white',\r\n backgroundColor: 'black',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n boxShadow: isHighlighted ? '0 0 12px rgba(115, 206, 226, 0.5)' : 'none',\r\n transition: 'all 0.2s ease-in-out',\r\n transform: isHighlighted ? 'scale(1.2)' : 'scale(1)',\r\n }}\r\n onMouseEnter={onMouseEnter}\r\n onMouseLeave={onMouseLeave}\r\n >\r\n <SensorIcon style={{ width: '20px', height: '20px', color: 'hsl(var(--primary-foreground))' }} />\r\n </div>\r\n </Marker>\r\n )\r\n}\r\n\r\nexport const SensorLayers = () => {\r\n const [hoveredSensorId, setHoveredSensorId] = React.useState<number | null>(null)\r\n const clusterLayer = createClusterLayer('sensors')\r\n const clusterCountLayer = createClusterCountLayer('sensors')\r\n const unclusteredPointLayer = createUnclusteredPointLayer('sensors')\r\n\r\n // global map state\r\n\r\n const t = useTranslations('SensorLayers')\r\n const tSensors = useTranslations('SensorsSection')\r\n\r\n const { state: appConfigState } = useAppConfigContext()\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { map, mapClickManager } = mapState.map\r\n const { sensors } = useSensors()\r\n const { users } = useUsers()\r\n const user = useSession().data?.user\r\n\r\n const [popupInfo, setPopUpInfo] = React.useState<Partial<ISensor & { sensorType: SensorType }> | null>(null)\r\n const { deleteSensor, updateSensor } = useSensor(popupInfo?.id ?? null)\r\n const { state: menusState } = React.useContext(MenusContext)\r\n const { visibleSensorTypes, visibleSensorTags, currentSensorId } = menusState.menus\r\n const typesVisible = visibleSensorTypes?.[ViewerNames.map] || []\r\n const tagsVisible = visibleSensorTags?.[ViewerNames.map] || []\r\n\r\n const {sensorTypes} = useSensorTypes()\r\n\r\n const eligibleSensors: Array<ISensor & { authorName: string } & { sensorType: SensorType }> = sensors\r\n .filter((sensor) => sensor.viewer === ViewerNames.map)\r\n .filter((sensor) => {\r\n const matchesType = typesVisible.includes(sensor.typeId)\r\n const hasNoTags = !sensor.tags?.length\r\n const matchesTag = hasNoTags\r\n ? tagsVisible.includes(UNTAGGED_TAG)\r\n : sensor.tags?.some(tag => tagsVisible.includes(tag)) ?? false\r\n return matchesType || matchesTag\r\n })\r\n .map((sensor) => {\r\n const user = users.find(u => u.id === sensor.authorId)\r\n const sensorType = sensorTypes.find(t => t.id === sensor.typeId)\r\n return {\r\n ...sensor,\r\n authorName: user?.name ?? 'Unknown User',\r\n sensorType,\r\n }\r\n })\r\n\r\n // Close popup if the sensor was deleted\r\n React.useEffect(() => {\r\n if (popupInfo && !sensors.find((s) => s.id === popupInfo.id)) {\r\n setPopUpInfo(null)\r\n }\r\n }, [sensors, popupInfo])\r\n\r\n const geojsonSensorData = React.useMemo(() => {\r\n const convertDataToGeojson = (sensorData: typeof eligibleSensors): GeoJSON.FeatureCollection<GeoJSON.Point, { [key: string]: any }> => {\r\n const sensorFeatures: GeoJSON.Feature<GeoJSON.Point, { [key: string]: any }>[] = sensorData\r\n .map((sensor) => {\r\n const { longitude, latitude, id, name, typeId, sensorType, data, dataFormat, updateFrequency, createdAt, authorId, organizationId, visible, url, authorName } = sensor\r\n\r\n return {\r\n type: 'Feature',\r\n geometry: {\r\n type: 'Point',\r\n coordinates: [longitude, latitude],\r\n },\r\n properties: {\r\n id: Number(id),\r\n organizationId,\r\n visible,\r\n longitude,\r\n latitude,\r\n authorId: Number(authorId),\r\n authorName,\r\n name,\r\n typeId: Number(typeId),\r\n typeIcon: sensorType?.icon,\r\n data,\r\n dataFormat,\r\n updateFrequency,\r\n url,\r\n createdAt,\r\n viewer: ViewerNames.map,\r\n },\r\n }\r\n })\r\n\r\n \r\n\r\n const sensorFC: GeoJSON.FeatureCollection<GeoJSON.Point, { [key: string]: any }> = {\r\n type: 'FeatureCollection',\r\n features: sensorFeatures,\r\n }\r\n return sensorFC\r\n }\r\n return convertDataToGeojson(eligibleSensors)\r\n }, [eligibleSensors])\r\n\r\n // event listeners for sensor unclustered points\r\n React.useEffect(() => {\r\n if (!map) return\r\n const showSensorPopUp: ClickCallback = (e: MapLayerMouseEvent, features: MapGeoJSONFeature[]) => {\r\n const feature = features?.[0]\r\n\r\n if (!feature || feature.properties.point_count) return\r\n\r\n if (feature.geometry.type != 'Point') return\r\n const [longitude, latitude] = feature.geometry.coordinates\r\n const { id, authorId, name, typeId, data, dataFormat, updateFrequency, createdAt, url } = feature.properties\r\n setPopUpInfo({\r\n id: Number(id),\r\n authorId: Number(authorId),\r\n organizationId: feature.properties?.organizationId,\r\n visible: feature.properties?.visible,\r\n longitude,\r\n latitude,\r\n name,\r\n typeId: Number(typeId),\r\n data,\r\n dataFormat,\r\n updateFrequency,\r\n url,\r\n createdAt,\r\n viewer: ViewerNames.map,\r\n })\r\n }\r\n\r\n const mouseEnterChangeCursor = () => {\r\n map.getCanvas().style.cursor = 'pointer'\r\n }\r\n const mouseLeaveChangeCursor = () => {\r\n map.getCanvas().style.cursor = ''\r\n }\r\n\r\n // event listener for clicking on single point to show sensor, hover to change cursor\r\n mapClickManager.register('sensors-unclustered-points', MapLayerClickPriority.CommentLayersClickPriority, showSensorPopUp)\r\n\r\n map.on('mouseenter', 'sensors-unclustered-points', mouseEnterChangeCursor)\r\n map.on('mouseleave', 'sensors-unclustered-points', mouseLeaveChangeCursor)\r\n return () => {\r\n mapClickManager.unregister('sensors-unclustered-points')\r\n map.off('mouseenter', 'sensors-unclustered-points', mouseEnterChangeCursor)\r\n map.off('mouseleave', 'sensors-unclustered-points', mouseLeaveChangeCursor)\r\n }\r\n }, [map, mapClickManager])\r\n\r\n const handleRemoveSensor = () => {\r\n toast.success(t('sensorDeleted'))\r\n deleteSensor()\r\n setPopUpInfo(null)\r\n }\r\n\r\n // event listeners for clustered points\r\n React.useEffect(() => {\r\n if (!map) return\r\n\r\n const zoomInToDecluster = (e: MapLayerMouseEvent) => {\r\n const feature = e.features?.[0] // only proceed if this is actually a cluster\r\n if (!feature || !feature.properties.cluster_id) return\r\n\r\n const clusterId = feature.properties.cluster_id as number\r\n\r\n // Check if geometry has coordinates (not a GeometryCollection)\r\n if (!('coordinates' in feature.geometry)) return\r\n const [lng, lat] = feature.geometry.coordinates as [number, number]\r\n\r\n const source = map.getSource('sensors') as any\r\n console.log(source)\r\n console.log(clusterId)\r\n source.getClusterExpansionZoom(clusterId).then(\r\n (zoom: number) => {\r\n console.log('easing to')\r\n map.easeTo({ center: [lng, lat], zoom })\r\n },\r\n )\r\n .catch((error) => {\r\n console.error(error)\r\n })\r\n }\r\n\r\n const mouseEnterChangeCursor = () => { map.getCanvas().style.cursor = 'pointer' }\r\n const mouseLeaveChangeCursor = () => { map.getCanvas().style.cursor = '' }\r\n\r\n // event listener for clicking on single point to zoom in and decluster, hover to change cursor\r\n map.on('click', 'sensors-clusters', zoomInToDecluster)\r\n map.on('mouseenter', 'sensors-clusters', mouseEnterChangeCursor)\r\n map.on('mouseleave', 'sensors-clusters', mouseLeaveChangeCursor)\r\n return () => {\r\n map.off('click', 'sensors-clusters', zoomInToDecluster)\r\n map.off('mouseenter', 'sensors-clusters', mouseEnterChangeCursor)\r\n map.off('mouseleave', 'sensors-clusters', mouseLeaveChangeCursor)\r\n }\r\n }, [map])\r\n\r\n const renderPopup = () => {\r\n if (!popupInfo) return null\r\n const sensorType = sensorTypes.find(t => t.id === popupInfo.typeId)\r\n const liveSensor = sensors.find(s => s.id === popupInfo.id)\r\n const dataUrl = popupInfo.url\r\n ? `${appConfigState.runtimeConfig.minioUrl ?? ''}/sensors/${popupInfo.url}`\r\n : popupInfo.data || ''\r\n \r\n return (\r\n <Popup\r\n className=\"noBorderPopup\"\r\n longitude={popupInfo.longitude}\r\n latitude={popupInfo.latitude}\r\n closeOnClick={false}\r\n onClose={() => setPopUpInfo(null)}\r\n anchor=\"bottom\"\r\n style={{ height: '50px', border: 'none', boxShadow: 'none' }}\r\n offset={[0, 10]}\r\n >\r\n <Sensor\r\n sensorName={popupInfo.name || ''}\r\n sensorType={sensorType}\r\n sensorId={popupInfo.id}\r\n tags={liveSensor?.tags ?? []}\r\n onAddTag={async (tag) => { await updateSensor({ tags: [...(liveSensor?.tags ?? []), tag] }) }}\r\n onDeleteTag={async (tag) => { await updateSensor({ tags: (liveSensor?.tags ?? []).filter(t => t !== tag) }) }}\r\n tagsTranslations={{\r\n addTag: tSensors('addTag'),\r\n removeTag: tSensors('removeTag'),\r\n cancel: tSensors('cancel'),\r\n newTagPlaceholder: tSensors('newTagPlaceholder'),\r\n }}\r\n dataUrl={dataUrl}\r\n dataFormat={popupInfo.dataFormat}\r\n updateFrequency={popupInfo.updateFrequency}\r\n buildingId={popupInfo.buildingId}\r\n createdAt={popupInfo.createdAt}\r\n onRemove={user.id === String(popupInfo.authorId) ? handleRemoveSensor : null}\r\n onClose={() => setPopUpInfo(null)}\r\n size=\"sm\"\r\n />\r\n {/* inline styles to override MapLibre's Pop up CSS */}\r\n <style>\r\n {`\r\n .noBorderPopup .maplibregl-popup-content {\r\n border: none !important;\r\n box-shadow: none !important;\r\n background: transparent !important;\r\n }\r\n .noBorderPopup .maplibregl-popup-tip {\r\n display: none !important;\r\n }\r\n `}\r\n </style>\r\n </Popup>\r\n )\r\n }\r\n\r\n // Track unclustered sensors to display icons\r\n const [unclusteredFeatures, setUnclusteredFeatures] = React.useState<MapGeoJSONFeature[]>([])\r\n\r\n React.useEffect(() => {\r\n if (!map) return\r\n\r\n const updateUnclusteredFeatures = () => {\r\n const allFeatures = map.querySourceFeatures('sensors')\r\n const unclusteredOnly = allFeatures.filter(\r\n (f) => !f.properties?.cluster && !f.properties?.point_count\r\n )\r\n // Deduplicate by id\r\n const uniqueFeatures = new Map()\r\n unclusteredOnly.forEach((f) => uniqueFeatures.set(f.properties.id, f))\r\n setUnclusteredFeatures(Array.from(uniqueFeatures.values()))\r\n }\r\n\r\n const onSourceData = (e: any) => {\r\n if (e?.sourceId === 'sensors') updateUnclusteredFeatures()\r\n }\r\n\r\n map.on('sourcedata', onSourceData)\r\n map.on('moveend', updateUnclusteredFeatures)\r\n map.on('zoomend', updateUnclusteredFeatures)\r\n\r\n updateUnclusteredFeatures()\r\n\r\n return () => {\r\n map.off('sourcedata', onSourceData)\r\n map.off('moveend', updateUnclusteredFeatures)\r\n map.off('zoomend', updateUnclusteredFeatures)\r\n }\r\n }, [map])\r\n\r\n return (\r\n <>\r\n {(typesVisible.length > 0 || tagsVisible.length > 0) &&\r\n <Source\r\n id=\"sensors\"\r\n type=\"geojson\"\r\n data={geojsonSensorData}\r\n cluster={true}\r\n clusterMaxZoom={14}\r\n clusterRadius={40}\r\n >\r\n <Layer {...clusterLayer} />\r\n <Layer {...clusterCountLayer} />\r\n <Layer {...unclusteredPointLayer} />\r\n\r\n {renderPopup()}\r\n {unclusteredFeatures\r\n .filter((feature) => feature.properties?.id !== popupInfo?.id)\r\n .map((feature) => (\r\n <SensorIconMarker\r\n key={String(feature.properties?.id)}\r\n feature={feature}\r\n isHighlighted={currentSensorId === feature.properties?.id || hoveredSensorId === feature.properties?.id}\r\n onMouseEnter={() => setHoveredSensorId(feature.properties?.id)}\r\n onMouseLeave={() => setHoveredSensorId(null)}\r\n sensorTypes={sensorTypes}\r\n />\r\n ))}\r\n </Source>}\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","user","t"]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/SensorsLayer/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 { MapContext, MenusContext } from '../../../../../../../store'\r\nimport * as React from 'react'\r\nimport { Source, Layer, Popup, Marker } from 'react-map-gl/maplibre'\r\nimport type { MapGeoJSONFeature, MapLayerMouseEvent } from 'maplibre-gl'\r\nimport Sensor from '../../../../../../ui/Sensors/Sensor'\r\nimport { SensorType, ViewerNames, type Sensor as ISensor} from '../../../../../../../types/dbTypes'\r\n\r\nimport { MapLayerClickPriority, ClickCallback } from '../../../../utils/MapEventManager/MapClickManager'\r\nimport { extractCoordinatesFromFeature } from '../../../../utils/extractCoordinates'\r\nimport { useSensor, useSensors } from '../../../../../../../hooks/sensors/sensors'\r\nimport { useUsers } from '../../../../../../../hooks/users/users'\r\nimport { toast } from 'sonner'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { createClusterLayer, createClusterCountLayer, createUnclusteredPointLayer } from '../mapLayersUtils'\r\nimport { useSensorTypes } from '../../../../../../../hooks/sensorTypes/sensorTypes'\r\nimport * as LR from 'lucide-react'\r\nimport { UNTAGGED_TAG } from '../../../../../../ui/Sensors/SensorsSection'\r\n\r\nconst SensorIconMarker = ({ feature, isHighlighted, onMouseEnter, onMouseLeave, sensorTypes }: { feature: MapGeoJSONFeature; isHighlighted?: boolean; onMouseEnter?: () => void; onMouseLeave?: () => void; sensorTypes: SensorType[] }) => {\r\n\r\n const coords = extractCoordinatesFromFeature(feature)\r\n if (!coords) return null\r\n\r\n const sensorType = sensorTypes.find(t => t.id === feature.properties?.typeId)\r\n const icon = sensorType?.icon || 'Radio'\r\n const SensorIcon = LR[icon] || LR.Radio\r\n\r\n return (\r\n <Marker key={String(feature.properties?.id ?? `${coords.lng},${coords.lat}`)} longitude={coords.lng} latitude={coords.lat} anchor=\"center\">\r\n <div\r\n style={{\r\n width: '36px',\r\n height: '36px',\r\n borderRadius: '50%',\r\n border: isHighlighted ? '3px solid #73cee2' : '2px solid white',\r\n backgroundColor: 'black',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n boxShadow: isHighlighted ? '0 0 12px rgba(115, 206, 226, 0.5)' : 'none',\r\n transition: 'all 0.2s ease-in-out',\r\n transform: isHighlighted ? 'scale(1.2)' : 'scale(1)',\r\n }}\r\n onMouseEnter={onMouseEnter}\r\n onMouseLeave={onMouseLeave}\r\n >\r\n <SensorIcon style={{ width: '20px', height: '20px', color: 'hsl(var(--primary-foreground))' }} />\r\n </div>\r\n </Marker>\r\n )\r\n}\r\n\r\nexport const SensorLayers = ({ minioBaseUrl }: { minioBaseUrl?: string }) => {\r\n const [hoveredSensorId, setHoveredSensorId] = React.useState<number | null>(null)\r\n const clusterLayer = createClusterLayer('sensors')\r\n const clusterCountLayer = createClusterCountLayer('sensors')\r\n const unclusteredPointLayer = createUnclusteredPointLayer('sensors')\r\n\r\n // global map state\r\n\r\n const t = useTranslations('SensorLayers')\r\n const tSensors = useTranslations('SensorsSection')\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { map, mapClickManager } = mapState.map\r\n const { sensors } = useSensors()\r\n const { users } = useUsers()\r\n const user = useSession().data?.user\r\n\r\n const [popupInfo, setPopUpInfo] = React.useState<Partial<ISensor & { sensorType: SensorType }> | null>(null)\r\n const { deleteSensor, updateSensor } = useSensor(popupInfo?.id ?? null)\r\n const { state: menusState } = React.useContext(MenusContext)\r\n const { visibleSensorTypes, visibleSensorTags, currentSensorId } = menusState.menus\r\n const typesVisible = visibleSensorTypes?.[ViewerNames.map] || []\r\n const tagsVisible = visibleSensorTags?.[ViewerNames.map] || []\r\n\r\n const {sensorTypes} = useSensorTypes()\r\n\r\n const eligibleSensors: Array<ISensor & { authorName: string } & { sensorType: SensorType }> = sensors\r\n .filter((sensor) => sensor.viewer === ViewerNames.map)\r\n .filter((sensor) => {\r\n const matchesType = typesVisible.includes(sensor.typeId)\r\n const hasNoTags = !sensor.tags?.length\r\n const matchesTag = hasNoTags\r\n ? tagsVisible.includes(UNTAGGED_TAG)\r\n : sensor.tags?.some(tag => tagsVisible.includes(tag)) ?? false\r\n return matchesType || matchesTag\r\n })\r\n .map((sensor) => {\r\n const user = users.find(u => u.id === sensor.authorId)\r\n const sensorType = sensorTypes.find(t => t.id === sensor.typeId)\r\n return {\r\n ...sensor,\r\n authorName: user?.name ?? 'Unknown User',\r\n sensorType,\r\n }\r\n })\r\n\r\n // Close popup if the sensor was deleted\r\n React.useEffect(() => {\r\n if (popupInfo && !sensors.find((s) => s.id === popupInfo.id)) {\r\n setPopUpInfo(null)\r\n }\r\n }, [sensors, popupInfo])\r\n\r\n const geojsonSensorData = React.useMemo(() => {\r\n const convertDataToGeojson = (sensorData: typeof eligibleSensors): GeoJSON.FeatureCollection<GeoJSON.Point, { [key: string]: any }> => {\r\n const sensorFeatures: GeoJSON.Feature<GeoJSON.Point, { [key: string]: any }>[] = sensorData\r\n .map((sensor) => {\r\n const { longitude, latitude, id, name, typeId, sensorType, data, dataFormat, updateFrequency, createdAt, authorId, organizationId, visible, url, authorName } = sensor\r\n\r\n return {\r\n type: 'Feature',\r\n geometry: {\r\n type: 'Point',\r\n coordinates: [longitude, latitude],\r\n },\r\n properties: {\r\n id: Number(id),\r\n organizationId,\r\n visible,\r\n longitude,\r\n latitude,\r\n authorId: Number(authorId),\r\n authorName,\r\n name,\r\n typeId: Number(typeId),\r\n typeIcon: sensorType?.icon,\r\n data,\r\n dataFormat,\r\n updateFrequency,\r\n url,\r\n createdAt,\r\n viewer: ViewerNames.map,\r\n },\r\n }\r\n })\r\n\r\n \r\n\r\n const sensorFC: GeoJSON.FeatureCollection<GeoJSON.Point, { [key: string]: any }> = {\r\n type: 'FeatureCollection',\r\n features: sensorFeatures,\r\n }\r\n return sensorFC\r\n }\r\n return convertDataToGeojson(eligibleSensors)\r\n }, [eligibleSensors])\r\n\r\n // event listeners for sensor unclustered points\r\n React.useEffect(() => {\r\n if (!map) return\r\n const showSensorPopUp: ClickCallback = (e: MapLayerMouseEvent, features: MapGeoJSONFeature[]) => {\r\n const feature = features?.[0]\r\n\r\n if (!feature || feature.properties.point_count) return\r\n\r\n if (feature.geometry.type != 'Point') return\r\n const [longitude, latitude] = feature.geometry.coordinates\r\n const { id, authorId, name, typeId, data, dataFormat, updateFrequency, createdAt, url } = feature.properties\r\n setPopUpInfo({\r\n id: Number(id),\r\n authorId: Number(authorId),\r\n organizationId: feature.properties?.organizationId,\r\n visible: feature.properties?.visible,\r\n longitude,\r\n latitude,\r\n name,\r\n typeId: Number(typeId),\r\n data,\r\n dataFormat,\r\n updateFrequency,\r\n url,\r\n createdAt,\r\n viewer: ViewerNames.map,\r\n })\r\n }\r\n\r\n const mouseEnterChangeCursor = () => {\r\n map.getCanvas().style.cursor = 'pointer'\r\n }\r\n const mouseLeaveChangeCursor = () => {\r\n map.getCanvas().style.cursor = ''\r\n }\r\n\r\n // event listener for clicking on single point to show sensor, hover to change cursor\r\n mapClickManager.register('sensors-unclustered-points', MapLayerClickPriority.CommentLayersClickPriority, showSensorPopUp)\r\n\r\n map.on('mouseenter', 'sensors-unclustered-points', mouseEnterChangeCursor)\r\n map.on('mouseleave', 'sensors-unclustered-points', mouseLeaveChangeCursor)\r\n return () => {\r\n mapClickManager.unregister('sensors-unclustered-points')\r\n map.off('mouseenter', 'sensors-unclustered-points', mouseEnterChangeCursor)\r\n map.off('mouseleave', 'sensors-unclustered-points', mouseLeaveChangeCursor)\r\n }\r\n }, [map, mapClickManager])\r\n\r\n const handleRemoveSensor = () => {\r\n toast.success(t('sensorDeleted'))\r\n deleteSensor()\r\n setPopUpInfo(null)\r\n }\r\n\r\n // event listeners for clustered points\r\n React.useEffect(() => {\r\n if (!map) return\r\n\r\n const zoomInToDecluster = (e: MapLayerMouseEvent) => {\r\n const feature = e.features?.[0] // only proceed if this is actually a cluster\r\n if (!feature || !feature.properties.cluster_id) return\r\n\r\n const clusterId = feature.properties.cluster_id as number\r\n\r\n // Check if geometry has coordinates (not a GeometryCollection)\r\n if (!('coordinates' in feature.geometry)) return\r\n const [lng, lat] = feature.geometry.coordinates as [number, number]\r\n\r\n const source = map.getSource('sensors') as any\r\n console.log(source)\r\n console.log(clusterId)\r\n source.getClusterExpansionZoom(clusterId).then(\r\n (zoom: number) => {\r\n console.log('easing to')\r\n map.easeTo({ center: [lng, lat], zoom })\r\n },\r\n )\r\n .catch((error) => {\r\n console.error(error)\r\n })\r\n }\r\n\r\n const mouseEnterChangeCursor = () => { map.getCanvas().style.cursor = 'pointer' }\r\n const mouseLeaveChangeCursor = () => { map.getCanvas().style.cursor = '' }\r\n\r\n // event listener for clicking on single point to zoom in and decluster, hover to change cursor\r\n map.on('click', 'sensors-clusters', zoomInToDecluster)\r\n map.on('mouseenter', 'sensors-clusters', mouseEnterChangeCursor)\r\n map.on('mouseleave', 'sensors-clusters', mouseLeaveChangeCursor)\r\n return () => {\r\n map.off('click', 'sensors-clusters', zoomInToDecluster)\r\n map.off('mouseenter', 'sensors-clusters', mouseEnterChangeCursor)\r\n map.off('mouseleave', 'sensors-clusters', mouseLeaveChangeCursor)\r\n }\r\n }, [map])\r\n\r\n const renderPopup = () => {\r\n if (!popupInfo) return null\r\n const sensorType = sensorTypes.find(t => t.id === popupInfo.typeId)\r\n const liveSensor = sensors.find(s => s.id === popupInfo.id)\r\n const dataUrl = popupInfo.url\r\n ? `${minioBaseUrl ?? ''}/sensors/${popupInfo.url}`\r\n : popupInfo.data || ''\r\n \r\n return (\r\n <Popup\r\n className=\"noBorderPopup\"\r\n longitude={popupInfo.longitude}\r\n latitude={popupInfo.latitude}\r\n closeOnClick={false}\r\n onClose={() => setPopUpInfo(null)}\r\n anchor=\"bottom\"\r\n style={{ height: '50px', border: 'none', boxShadow: 'none' }}\r\n offset={[0, 10]}\r\n >\r\n <Sensor\r\n sensorName={popupInfo.name || ''}\r\n sensorType={sensorType}\r\n sensorId={popupInfo.id}\r\n tags={liveSensor?.tags ?? []}\r\n onAddTag={async (tag) => { await updateSensor({ tags: [...(liveSensor?.tags ?? []), tag] }) }}\r\n onDeleteTag={async (tag) => { await updateSensor({ tags: (liveSensor?.tags ?? []).filter(t => t !== tag) }) }}\r\n tagsTranslations={{\r\n addTag: tSensors('addTag'),\r\n removeTag: tSensors('removeTag'),\r\n cancel: tSensors('cancel'),\r\n newTagPlaceholder: tSensors('newTagPlaceholder'),\r\n }}\r\n dataUrl={dataUrl}\r\n dataFormat={popupInfo.dataFormat}\r\n updateFrequency={popupInfo.updateFrequency}\r\n buildingId={popupInfo.buildingId}\r\n createdAt={popupInfo.createdAt}\r\n onRemove={user.id === String(popupInfo.authorId) ? handleRemoveSensor : null}\r\n onClose={() => setPopUpInfo(null)}\r\n size=\"sm\"\r\n />\r\n {/* inline styles to override MapLibre's Pop up CSS */}\r\n <style>\r\n {`\r\n .noBorderPopup .maplibregl-popup-content {\r\n border: none !important;\r\n box-shadow: none !important;\r\n background: transparent !important;\r\n }\r\n .noBorderPopup .maplibregl-popup-tip {\r\n display: none !important;\r\n }\r\n `}\r\n </style>\r\n </Popup>\r\n )\r\n }\r\n\r\n // Track unclustered sensors to display icons\r\n const [unclusteredFeatures, setUnclusteredFeatures] = React.useState<MapGeoJSONFeature[]>([])\r\n\r\n React.useEffect(() => {\r\n if (!map) return\r\n\r\n const updateUnclusteredFeatures = () => {\r\n const allFeatures = map.querySourceFeatures('sensors')\r\n const unclusteredOnly = allFeatures.filter(\r\n (f) => !f.properties?.cluster && !f.properties?.point_count\r\n )\r\n // Deduplicate by id\r\n const uniqueFeatures = new Map()\r\n unclusteredOnly.forEach((f) => uniqueFeatures.set(f.properties.id, f))\r\n setUnclusteredFeatures(Array.from(uniqueFeatures.values()))\r\n }\r\n\r\n const onSourceData = (e: any) => {\r\n if (e?.sourceId === 'sensors') updateUnclusteredFeatures()\r\n }\r\n\r\n map.on('sourcedata', onSourceData)\r\n map.on('moveend', updateUnclusteredFeatures)\r\n map.on('zoomend', updateUnclusteredFeatures)\r\n\r\n updateUnclusteredFeatures()\r\n\r\n return () => {\r\n map.off('sourcedata', onSourceData)\r\n map.off('moveend', updateUnclusteredFeatures)\r\n map.off('zoomend', updateUnclusteredFeatures)\r\n }\r\n }, [map])\r\n\r\n return (\r\n <>\r\n {(typesVisible.length > 0 || tagsVisible.length > 0) &&\r\n <Source\r\n id=\"sensors\"\r\n type=\"geojson\"\r\n data={geojsonSensorData}\r\n cluster={true}\r\n clusterMaxZoom={14}\r\n clusterRadius={40}\r\n >\r\n <Layer {...clusterLayer} />\r\n <Layer {...clusterCountLayer} />\r\n <Layer {...unclusteredPointLayer} />\r\n\r\n {renderPopup()}\r\n {unclusteredFeatures\r\n .filter((feature) => feature.properties?.id !== popupInfo?.id)\r\n .map((feature) => (\r\n <SensorIconMarker\r\n key={String(feature.properties?.id)}\r\n feature={feature}\r\n isHighlighted={currentSensorId === feature.properties?.id || hoveredSensorId === feature.properties?.id}\r\n onMouseEnter={() => setHoveredSensorId(feature.properties?.id)}\r\n onMouseLeave={() => setHoveredSensorId(null)}\r\n sensorTypes={sensorTypes}\r\n />\r\n ))}\r\n </Source>}\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","user","t"]}
@@ -1,3 +1,8 @@
1
1
  import * as React from 'react';
2
- export declare function MapSidebar(): React.JSX.Element;
2
+ import { Organization } from '../../../../../types/dbTypes';
3
+ export declare function MapSidebar({ minioBaseUrl, martinBaseUrl, organization }: {
4
+ minioBaseUrl?: string;
5
+ martinBaseUrl?: string;
6
+ organization?: Organization;
7
+ }): React.JSX.Element;
3
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,wBAAgB,UAAU,sBA2BzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3D,wBAAgB,UAAU,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,qBA4BvJ"}
@@ -9,7 +9,7 @@ import { SettingsTab } from "./src/SettingsTab";
9
9
  import { InfoSidebarContainer } from "../../../../../components/ui/InfoSidebar/Container";
10
10
  import { CommunicationTab } from "./src/CommunicationTab";
11
11
  import { SensorsTab } from "./src/SensorsTab";
12
- function MapSidebar() {
12
+ function MapSidebar({ minioBaseUrl, martinBaseUrl, organization }) {
13
13
  const { ability } = usePermissions();
14
14
  const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext);
15
15
  const { selectedTab } = menusState.menus;
@@ -19,6 +19,7 @@ function MapSidebar() {
19
19
  return /* @__PURE__ */ jsxs(
20
20
  InfoSidebarContainer,
21
21
  {
22
+ organization,
22
23
  tabSelector: /* @__PURE__ */ jsx(
23
24
  TabSelector,
24
25
  {
@@ -28,10 +29,10 @@ function MapSidebar() {
28
29
  ),
29
30
  children: [
30
31
  selectedTab === "file" && ability.can("read", "File") && /* @__PURE__ */ jsx(FileTab, {}),
31
- selectedTab === "layers" && ability.can("read", "File") && /* @__PURE__ */ jsx(LayersTab, {}),
32
+ selectedTab === "layers" && ability.can("read", "File") && /* @__PURE__ */ jsx(LayersTab, { martinBaseUrl, organization }),
32
33
  selectedTab === "communication" && ability.can("read", "Comment") && /* @__PURE__ */ jsx(CommunicationTab, {}),
33
- selectedTab === "sensors" && ability.can("read", "Sensor") && /* @__PURE__ */ jsx(SensorsTab, {}),
34
- selectedTab === "settings" && /* @__PURE__ */ jsx(SettingsTab, {})
34
+ selectedTab === "sensors" && ability.can("read", "Sensor") && /* @__PURE__ */ jsx(SensorsTab, { minioBaseUrl }),
35
+ selectedTab === "settings" && /* @__PURE__ */ jsx(SettingsTab, { countryCode: organization == null ? void 0 : organization.country })
35
36
  ]
36
37
  }
37
38
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { TabSelector } from './TabSelector'\r\nimport { MenusContext, usePermissions } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\nimport { LayersTab } from './src/LayersTab'\r\n\r\nimport { SettingsTab } from './src/SettingsTab'\r\nimport { InfoSidebarContainer } from '../../../../../components/ui/InfoSidebar/Container'\r\nimport { CommunicationTab } from './src/CommunicationTab'\r\nimport { SensorsTab } from './src/SensorsTab'\r\n\r\nexport function MapSidebar() {\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { selectedTab } = menusState.menus\r\n\r\n const handleTabChange = (selectedTab: SidebarTabType) => {\r\n menusDispatch({ type: 'SET_SIDEBAR_SELECTED_TAB', payload: { selectedTab } })\r\n }\r\n\r\n return (\r\n <InfoSidebarContainer\r\n tabSelector={\r\n <TabSelector\r\n activeTab={selectedTab}\r\n onTabChangeAction={handleTabChange}\r\n />\r\n }\r\n >\r\n {selectedTab === 'file' && ability.can('read', 'File') && <FileTab />}\r\n {selectedTab === 'layers' && ability.can('read', 'File') && <LayersTab />}\r\n {selectedTab === 'communication' && ability.can('read', 'Comment') && <CommunicationTab />}\r\n {selectedTab === 'sensors' && ability.can('read', 'Sensor') && <SensorsTab />}\r\n {selectedTab === 'settings' && <SettingsTab />} \r\n </InfoSidebarContainer>\r\n )\r\n}"],"mappings":";AA6BI,SAEI,KAFJ;AAxBJ,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAC5B,SAAS,cAAc,sBAAsB;AAE7C,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAE1B,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAEpB,SAAS,aAAa;AAE3B,QAAM,EAAE,QAAQ,IAAI,eAAe;AAEnC,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,YAAY,IAAI,WAAW;AAEnC,QAAM,kBAAkB,CAACA,iBAAgC;AACvD,kBAAc,EAAE,MAAM,4BAA4B,SAAS,EAAE,aAAAA,aAAY,EAAE,CAAC;AAAA,EAC9E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,mBAAmB;AAAA;AAAA,MACrB;AAAA,MAGD;AAAA,wBAAgB,UAAU,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,WAAQ;AAAA,QAClE,gBAAgB,YAAY,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,aAAU;AAAA,QACtE,gBAAgB,mBAAmB,QAAQ,IAAI,QAAQ,SAAS,KAAK,oBAAC,oBAAiB;AAAA,QACvF,gBAAgB,aAAa,QAAQ,IAAI,QAAQ,QAAQ,KAAK,oBAAC,cAAW;AAAA,QAC1E,gBAAgB,cAAc,oBAAC,eAAY;AAAA;AAAA;AAAA,EAC9C;AAEJ;","names":["selectedTab"]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { TabSelector } from './TabSelector'\r\nimport { MenusContext, usePermissions } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\nimport { LayersTab } from './src/LayersTab'\r\n\r\nimport { SettingsTab } from './src/SettingsTab'\r\nimport { InfoSidebarContainer } from '../../../../../components/ui/InfoSidebar/Container'\r\nimport { CommunicationTab } from './src/CommunicationTab'\r\nimport { SensorsTab } from './src/SensorsTab'\r\nimport { Organization } from '../../../../../types/dbTypes'\r\n\r\nexport function MapSidebar({ minioBaseUrl, martinBaseUrl, organization }: { minioBaseUrl?: string; martinBaseUrl?: string; organization?: Organization }) {\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { selectedTab } = menusState.menus\r\n\r\n const handleTabChange = (selectedTab: SidebarTabType) => {\r\n menusDispatch({ type: 'SET_SIDEBAR_SELECTED_TAB', payload: { selectedTab } })\r\n }\r\n\r\n return (\r\n <InfoSidebarContainer\r\n organization={organization}\r\n tabSelector={\r\n <TabSelector\r\n activeTab={selectedTab}\r\n onTabChangeAction={handleTabChange}\r\n />\r\n }\r\n >\r\n {selectedTab === 'file' && ability.can('read', 'File') && <FileTab />}\r\n {selectedTab === 'layers' && ability.can('read', 'File') && <LayersTab martinBaseUrl={martinBaseUrl} organization={organization} />}\r\n {selectedTab === 'communication' && ability.can('read', 'Comment') && <CommunicationTab />}\r\n {selectedTab === 'sensors' && ability.can('read', 'Sensor') && <SensorsTab minioBaseUrl={minioBaseUrl} />}\r\n {selectedTab === 'settings' && <SettingsTab countryCode={organization?.country} />}\r\n </InfoSidebarContainer>\r\n )\r\n}"],"mappings":";AA8BI,SAGI,KAHJ;AAzBJ,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAC5B,SAAS,cAAc,sBAAsB;AAE7C,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAE1B,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAGpB,SAAS,WAAW,EAAE,cAAc,eAAe,aAAa,GAAmF;AAExJ,QAAM,EAAE,QAAQ,IAAI,eAAe;AAEnC,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,YAAY,IAAI,WAAW;AAEnC,QAAM,kBAAkB,CAACA,iBAAgC;AACvD,kBAAc,EAAE,MAAM,4BAA4B,SAAS,EAAE,aAAAA,aAAY,EAAE,CAAC;AAAA,EAC9E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,mBAAmB;AAAA;AAAA,MACrB;AAAA,MAGD;AAAA,wBAAgB,UAAU,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,WAAQ;AAAA,QAClE,gBAAgB,YAAY,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,aAAU,eAA8B,cAA4B;AAAA,QAChI,gBAAgB,mBAAmB,QAAQ,IAAI,QAAQ,SAAS,KAAK,oBAAC,oBAAiB;AAAA,QACvF,gBAAgB,aAAa,QAAQ,IAAI,QAAQ,QAAQ,KAAK,oBAAC,cAAW,cAA4B;AAAA,QACtG,gBAAgB,cAAc,oBAAC,eAAY,aAAa,6CAAc,SAAS;AAAA;AAAA;AAAA,EAClF;AAEJ;","names":["selectedTab"]}
@@ -1,3 +1,7 @@
1
1
  import * as React from 'react';
2
- export declare function LayersTab(): React.JSX.Element;
2
+ import { Organization } from '../../../../../../../types/dbTypes';
3
+ export declare function LayersTab({ martinBaseUrl, organization }: {
4
+ martinBaseUrl?: string;
5
+ organization?: Organization;
6
+ }): React.JSX.Element;
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyF9B,wBAAgB,SAAS,sBAwJxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,OAAO,EAAgB,YAAY,EAAE,MAAM,oCAAoC,CAAA;AA+E/E,wBAAgB,SAAS,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,qBAuJjH"}
@@ -3,7 +3,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { usePathname } from "next/navigation";
5
5
  import { DatasetsContext, MenusContext, useMapContext } from "../../../../../../../store";
6
- import { useAppConfigContext } from "../../../../../../../store/AppConfig/context";
7
6
  import {
8
7
  useOpenDataPortalsByCountrySubdivision,
9
8
  useOpenDataPortalsByGroup,
@@ -74,14 +73,13 @@ function sanitizeDatasets(list) {
74
73
  });
75
74
  return filtered.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
76
75
  }
77
- function LayersTab() {
76
+ function LayersTab({ martinBaseUrl, organization }) {
78
77
  var _a, _b, _c, _d;
79
78
  const [searchQuery, setSearchQuery] = React.useState("");
80
79
  const [favourites, setFavourites] = React.useState([]);
81
80
  const { state: mapState } = useMapContext();
82
81
  const { currentLocation } = mapState.map;
83
- const { state: appConfigState } = useAppConfigContext();
84
- const org = appConfigState.appConfig.organization;
82
+ const org = organization;
85
83
  const orgCountry = ((org == null ? void 0 : org.country) || "").toUpperCase();
86
84
  const municipality = (_b = (_a = currentLocation == null ? void 0 : currentLocation.municipality) != null ? _a : org == null ? void 0 : org.municipality) != null ? _b : null;
87
85
  const countrySubdivision = (_d = (_c = currentLocation == null ? void 0 : currentLocation.countrySubdivision) != null ? _c : org == null ? void 0 : org.countrySubdivision) != null ? _d : null;
@@ -118,11 +116,10 @@ function LayersTab() {
118
116
  const national = useDatasetsForPortals(filteredNationalPortals, { rowsPerPage });
119
117
  React.useEffect(() => {
120
118
  const loadOrganizationalDatasets = async () => {
121
- var _a2;
122
119
  try {
123
- const martinBaseUrl = (_a2 = appConfigState.runtimeConfig.martinUrl) == null ? void 0 : _a2.replace(/\/+$/, "");
124
- if (!martinBaseUrl) return;
125
- const datasetsUrl = martinBaseUrl.includes("/tiles/index.json") ? martinBaseUrl : `${martinBaseUrl}/tiles/index.json`;
120
+ const martinBaseUrlClean = (martinBaseUrl != null ? martinBaseUrl : "").replace(/\/+$/, "");
121
+ if (!martinBaseUrlClean) return;
122
+ const datasetsUrl = martinBaseUrlClean.includes("/tiles/index.json") ? martinBaseUrlClean : `${martinBaseUrlClean}/tiles/index.json`;
126
123
  const localPortal = {
127
124
  id: -1,
128
125
  name: "Organizational Datasets",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { usePathname } from 'next/navigation'\r\n\r\nimport { DatasetsContext, MenusContext, useMapContext } from '../../../../../../../store'\r\nimport { useAppConfigContext } from '../../../../../../../store/AppConfig/context'\r\nimport {\r\n useOpenDataPortalsByCountrySubdivision,\r\n useOpenDataPortalsByGroup,\r\n useOpenDataPortalsByMunicipality,\r\n} from '../../../../../../../hooks/openDataPortals/openDataPortals'\r\nimport { DatasetGroup } from '../../../../../../../types/dbTypes'\r\nimport type { Dataset } from '../../../../../../../types/datasetTypes'\r\nimport { useDatasetsForPortals } from '../../../../datasets/src/useDatasetsForPortals'\r\nimport { fetchLocalDatasets } from '../../../../datasets/src/localDatasets'\r\nimport { SearchInput } from '../../../../../../ui'\r\nimport { AppliedDatasetsSection } from './src/AppliedDatasetsSection'\r\nimport { AvailableDatasetsSection } from './src/AvailableDatasetsSection'\r\n\r\ntype OrgVisibility = {\r\n isAdmin: boolean\r\n currentOrgId: number\r\n allowedOrgIds: number[]\r\n}\r\n\r\nconst ADMIN_ALLOWED_ORGS = [1, 2, 3, 4, 5, 6]\r\nconst ORG_BY_PATH_PREFIX: Record<string, number> = {\r\n '/envirocentre': 1,\r\n '/dnd': 3,\r\n '/canada': 4,\r\n '/gac': 5,\r\n '/carleton': 6,\r\n}\r\n\r\nfunction normalizeOrgId(org?: number | string | null) {\r\n if (org === null || org === undefined) return undefined\r\n const parsed = typeof org === 'number' ? org : Number.parseInt(String(org), 10)\r\n return Number.isFinite(parsed) ? parsed : undefined\r\n}\r\n\r\nfunction getOrgVisibilityFromPath(pathname?: string | null): OrgVisibility {\r\n const normalizedPath = (pathname || '').toLowerCase()\r\n const firstSegment = normalizedPath.split('/').filter(Boolean)[0]\r\n const prefix = firstSegment ? `/${firstSegment}` : ''\r\n\r\n if (prefix === '/cdt') {\r\n return { isAdmin: true, currentOrgId: 1, allowedOrgIds: ADMIN_ALLOWED_ORGS }\r\n }\r\n\r\n const currentOrgId = ORG_BY_PATH_PREFIX[prefix] ?? 2\r\n return { isAdmin: false, currentOrgId, allowedOrgIds: Array.from(new Set([2, currentOrgId])) }\r\n}\r\n\r\nfunction datasetVisibleForOrg(dataset: Dataset, visibility: OrgVisibility) {\r\n if (visibility.isAdmin) return true\r\n if (dataset.group !== DatasetGroup.Organizational) return true\r\n const orgId = normalizeOrgId(dataset.organization)\r\n if (orgId === undefined) return false\r\n return visibility.allowedOrgIds.includes(orgId)\r\n}\r\n\r\nconst BLOCKLIST_URLS = [\r\n '/2021_statistics_canada_boundaries/featureserver',\r\n '/limites_du_recensement_de_statistique_canada_(2021)/featureserver',\r\n]\r\nconst BLOCKLIST_NAMES = [\r\n '2021 statistics canada boundaries',\r\n 'limites du recensement de statistique canada (2021)',\r\n]\r\n\r\nfunction isBlocklisted(ds: Dataset) {\r\n const url = (ds.url || '').toLowerCase()\r\n const name = (ds.name || '').toLowerCase()\r\n return BLOCKLIST_URLS.some(u => url.includes(u)) || BLOCKLIST_NAMES.some(n => name.includes(n))\r\n}\r\n\r\nfunction sanitizeDatasets(list: Dataset[]) {\r\n const uniqueByName = new Map<string, Dataset>()\r\n for (const ds of list) {\r\n const name = ds.name?.toLowerCase() || ''\r\n if (!uniqueByName.has(name)) uniqueByName.set(name, ds)\r\n }\r\n const filtered = [...uniqueByName.values()].filter((ds) => {\r\n const name = ds.name?.toLowerCase() || ''\r\n const type = ds.type?.toLowerCase() || ''\r\n return !name.includes('basemap') && !type.includes('geocoding') && !isBlocklisted(ds)\r\n })\r\n return filtered.sort((a, b) => (a.name || '').localeCompare(b.name || ''))\r\n}\r\n\r\nexport function LayersTab() {\r\n const [searchQuery, setSearchQuery] = React.useState('')\r\n const [favourites, setFavourites] = React.useState<Dataset[]>([])\r\n\r\n const { state: mapState } = useMapContext()\r\n const { currentLocation } = mapState.map\r\n const { state: appConfigState } = useAppConfigContext()\r\n const org = appConfigState.appConfig.organization\r\n const orgCountry = (org?.country || '').toUpperCase()\r\n\r\n const municipality = currentLocation?.municipality ?? org?.municipality ?? null\r\n const countrySubdivision = currentLocation?.countrySubdivision ?? org?.countrySubdivision ?? null\r\n\r\n const { state: datasetState, dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { state: menusState } = React.useContext(MenusContext)\r\n const { rowsPerPage } = menusState.menus\r\n\r\n const pathname = usePathname()\r\n const orgVisibility = React.useMemo(() => getOrgVisibilityFromPath(pathname), [pathname])\r\n\r\n const { openDataPortals: municipalPortals } = useOpenDataPortalsByMunicipality(municipality)\r\n const { openDataPortals: subdivisionPortals } = useOpenDataPortalsByCountrySubdivision(countrySubdivision)\r\n const { openDataPortals: nationalPortals } = useOpenDataPortalsByGroup(DatasetGroup.National)\r\n\r\n const matchesOrgCountry = React.useCallback(\r\n (portalCountry: string | null | undefined) => {\r\n if (!orgCountry) return true\r\n if (!portalCountry) return true\r\n return portalCountry.toUpperCase() === orgCountry\r\n },\r\n [orgCountry],\r\n )\r\n\r\n const filteredMunicipalPortals = React.useMemo(\r\n () => (Array.isArray(municipalPortals) ? municipalPortals.filter(p => matchesOrgCountry(p.country)) : []),\r\n [municipalPortals, matchesOrgCountry],\r\n )\r\n const filteredSubdivisionPortals = React.useMemo(\r\n () => (Array.isArray(subdivisionPortals)\r\n ? subdivisionPortals.filter(p => p.municipality == null && matchesOrgCountry(p.country))\r\n : []),\r\n [subdivisionPortals, matchesOrgCountry],\r\n )\r\n const filteredNationalPortals = React.useMemo(\r\n () => (Array.isArray(nationalPortals) ? nationalPortals.filter(p => matchesOrgCountry(p.country)) : []),\r\n [nationalPortals, matchesOrgCountry],\r\n )\r\n\r\n const municipal = useDatasetsForPortals(filteredMunicipalPortals, { rowsPerPage })\r\n const subdivision = useDatasetsForPortals(filteredSubdivisionPortals, { rowsPerPage })\r\n const national = useDatasetsForPortals(filteredNationalPortals, { rowsPerPage })\r\n\r\n React.useEffect(() => {\r\n const loadOrganizationalDatasets = async () => {\r\n try {\r\n const martinBaseUrl = appConfigState.runtimeConfig.martinUrl?.replace(/\\/+$/, '')\r\n if (!martinBaseUrl) return\r\n\r\n const datasetsUrl = martinBaseUrl.includes('/tiles/index.json')\r\n ? martinBaseUrl\r\n : `${martinBaseUrl}/tiles/index.json`\r\n\r\n const localPortal = {\r\n id: -1,\r\n name: 'Organizational Datasets',\r\n apiUrl: datasetsUrl,\r\n dataManagementSystem: 'Other' as const,\r\n countrySubdivision: null,\r\n municipality: null,\r\n group: 'Organizational' as const,\r\n }\r\n\r\n const organizationalDatasets = await fetchLocalDatasets(localPortal as any)\r\n const visible = organizationalDatasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))\r\n if (visible.length > 0) {\r\n datasetDispatch({ type: 'SET_DATASETS', payload: { datasets: visible } })\r\n }\r\n }\r\n catch (error) {\r\n console.error('Failed to load organizational datasets:', error)\r\n }\r\n }\r\n loadOrganizationalDatasets()\r\n }, [datasetDispatch, orgVisibility])\r\n\r\n const nationalDatasets = React.useMemo(\r\n () => sanitizeDatasets(national.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [national.datasets, orgVisibility],\r\n )\r\n const subdivisionDatasets = React.useMemo(\r\n () => sanitizeDatasets(subdivision.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [subdivision.datasets, orgVisibility],\r\n )\r\n const municipalDatasets = React.useMemo(\r\n () => sanitizeDatasets(municipal.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [municipal.datasets, orgVisibility],\r\n )\r\n const orgDatasets = React.useMemo(\r\n () => sanitizeDatasets((datasetState.datasets.datasets || []).filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [datasetState.datasets.datasets, orgVisibility],\r\n )\r\n\r\n const allDatasets = React.useMemo(() => {\r\n const combined = [...nationalDatasets, ...subdivisionDatasets, ...municipalDatasets, ...orgDatasets]\r\n return sanitizeDatasets(combined)\r\n }, [nationalDatasets, subdivisionDatasets, municipalDatasets, orgDatasets])\r\n\r\n const liveDatasets = React.useMemo(\r\n () => allDatasets.filter(ds => ds.portal?.live === true),\r\n [allDatasets],\r\n )\r\n\r\n const toggleFavourite = React.useCallback((dataset: Dataset) => {\r\n setFavourites(prev => (\r\n prev.some(f => f.name === dataset.name)\r\n ? prev.filter(f => f.name !== dataset.name)\r\n : [...prev, dataset]\r\n ))\r\n }, [])\r\n\r\n const showMunicipal = Boolean(municipality)\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-4 py-4 overflow-hidden\">\r\n <div className=\"px-4\">\r\n <SearchInput\r\n placeholder=\"Search...\"\r\n value={searchQuery}\r\n onChange={e => setSearchQuery(e.target.value)}\r\n />\r\n </div>\r\n <div className=\"flex-1 min-h-0 overflow-y-auto space-y-2 divide-y\">\r\n <div className=\"pb-2\">\r\n <AppliedDatasetsSection />\r\n </div>\r\n <div className=\"pt-2\">\r\n <AvailableDatasetsSection\r\n query={searchQuery}\r\n allDatasets={allDatasets}\r\n nationalDatasets={nationalDatasets}\r\n subdivisionDatasets={subdivisionDatasets}\r\n municipalDatasets={municipalDatasets}\r\n organizationalDatasets={orgDatasets}\r\n liveDatasets={liveDatasets}\r\n showMunicipal={showMunicipal}\r\n favourites={favourites}\r\n onFavouriteToggle={toggleFavourite}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a"]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { usePathname } from 'next/navigation'\r\n\r\nimport { DatasetsContext, MenusContext, useMapContext } from '../../../../../../../store'\r\n// import { useAppConfigContext } from '../../../../../../../store/AppConfig/context'\r\nimport {\r\n useOpenDataPortalsByCountrySubdivision,\r\n useOpenDataPortalsByGroup,\r\n useOpenDataPortalsByMunicipality,\r\n} from '../../../../../../../hooks/openDataPortals/openDataPortals'\r\nimport { DatasetGroup, Organization } from '../../../../../../../types/dbTypes'\r\nimport type { Dataset } from '../../../../../../../types/datasetTypes'\r\nimport { useDatasetsForPortals } from '../../../../datasets/src/useDatasetsForPortals'\r\nimport { fetchLocalDatasets } from '../../../../datasets/src/localDatasets'\r\nimport { SearchInput } from '../../../../../../ui'\r\nimport { AppliedDatasetsSection } from './src/AppliedDatasetsSection'\r\nimport { AvailableDatasetsSection } from './src/AvailableDatasetsSection'\r\n\r\ntype OrgVisibility = {\r\n isAdmin: boolean\r\n currentOrgId: number\r\n allowedOrgIds: number[]\r\n}\r\n\r\nconst ADMIN_ALLOWED_ORGS = [1, 2, 3, 4, 5, 6]\r\nconst ORG_BY_PATH_PREFIX: Record<string, number> = {\r\n '/envirocentre': 1,\r\n '/dnd': 3,\r\n '/canada': 4,\r\n '/gac': 5,\r\n '/carleton': 6,\r\n}\r\n\r\nfunction normalizeOrgId(org?: number | string | null) {\r\n if (org === null || org === undefined) return undefined\r\n const parsed = typeof org === 'number' ? org : Number.parseInt(String(org), 10)\r\n return Number.isFinite(parsed) ? parsed : undefined\r\n}\r\n\r\nfunction getOrgVisibilityFromPath(pathname?: string | null): OrgVisibility {\r\n const normalizedPath = (pathname || '').toLowerCase()\r\n const firstSegment = normalizedPath.split('/').filter(Boolean)[0]\r\n const prefix = firstSegment ? `/${firstSegment}` : ''\r\n\r\n if (prefix === '/cdt') {\r\n return { isAdmin: true, currentOrgId: 1, allowedOrgIds: ADMIN_ALLOWED_ORGS }\r\n }\r\n\r\n const currentOrgId = ORG_BY_PATH_PREFIX[prefix] ?? 2\r\n return { isAdmin: false, currentOrgId, allowedOrgIds: Array.from(new Set([2, currentOrgId])) }\r\n}\r\n\r\nfunction datasetVisibleForOrg(dataset: Dataset, visibility: OrgVisibility) {\r\n if (visibility.isAdmin) return true\r\n if (dataset.group !== DatasetGroup.Organizational) return true\r\n const orgId = normalizeOrgId(dataset.organization)\r\n if (orgId === undefined) return false\r\n return visibility.allowedOrgIds.includes(orgId)\r\n}\r\n\r\nconst BLOCKLIST_URLS = [\r\n '/2021_statistics_canada_boundaries/featureserver',\r\n '/limites_du_recensement_de_statistique_canada_(2021)/featureserver',\r\n]\r\nconst BLOCKLIST_NAMES = [\r\n '2021 statistics canada boundaries',\r\n 'limites du recensement de statistique canada (2021)',\r\n]\r\n\r\nfunction isBlocklisted(ds: Dataset) {\r\n const url = (ds.url || '').toLowerCase()\r\n const name = (ds.name || '').toLowerCase()\r\n return BLOCKLIST_URLS.some(u => url.includes(u)) || BLOCKLIST_NAMES.some(n => name.includes(n))\r\n}\r\n\r\nfunction sanitizeDatasets(list: Dataset[]) {\r\n const uniqueByName = new Map<string, Dataset>()\r\n for (const ds of list) {\r\n const name = ds.name?.toLowerCase() || ''\r\n if (!uniqueByName.has(name)) uniqueByName.set(name, ds)\r\n }\r\n const filtered = [...uniqueByName.values()].filter((ds) => {\r\n const name = ds.name?.toLowerCase() || ''\r\n const type = ds.type?.toLowerCase() || ''\r\n return !name.includes('basemap') && !type.includes('geocoding') && !isBlocklisted(ds)\r\n })\r\n return filtered.sort((a, b) => (a.name || '').localeCompare(b.name || ''))\r\n}\r\n\r\nexport function LayersTab({ martinBaseUrl, organization }: { martinBaseUrl?: string; organization?: Organization }) {\r\n const [searchQuery, setSearchQuery] = React.useState('')\r\n const [favourites, setFavourites] = React.useState<Dataset[]>([])\r\n\r\n const { state: mapState } = useMapContext()\r\n const { currentLocation } = mapState.map\r\n const org = organization\r\n const orgCountry = (org?.country || '').toUpperCase()\r\n\r\n const municipality = currentLocation?.municipality ?? org?.municipality ?? null\r\n const countrySubdivision = currentLocation?.countrySubdivision ?? org?.countrySubdivision ?? null\r\n\r\n const { state: datasetState, dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { state: menusState } = React.useContext(MenusContext)\r\n const { rowsPerPage } = menusState.menus\r\n\r\n const pathname = usePathname()\r\n const orgVisibility = React.useMemo(() => getOrgVisibilityFromPath(pathname), [pathname])\r\n\r\n const { openDataPortals: municipalPortals } = useOpenDataPortalsByMunicipality(municipality)\r\n const { openDataPortals: subdivisionPortals } = useOpenDataPortalsByCountrySubdivision(countrySubdivision)\r\n const { openDataPortals: nationalPortals } = useOpenDataPortalsByGroup(DatasetGroup.National)\r\n\r\n const matchesOrgCountry = React.useCallback(\r\n (portalCountry: string | null | undefined) => {\r\n if (!orgCountry) return true\r\n if (!portalCountry) return true\r\n return portalCountry.toUpperCase() === orgCountry\r\n },\r\n [orgCountry],\r\n )\r\n\r\n const filteredMunicipalPortals = React.useMemo(\r\n () => (Array.isArray(municipalPortals) ? municipalPortals.filter(p => matchesOrgCountry(p.country)) : []),\r\n [municipalPortals, matchesOrgCountry],\r\n )\r\n const filteredSubdivisionPortals = React.useMemo(\r\n () => (Array.isArray(subdivisionPortals)\r\n ? subdivisionPortals.filter(p => p.municipality == null && matchesOrgCountry(p.country))\r\n : []),\r\n [subdivisionPortals, matchesOrgCountry],\r\n )\r\n const filteredNationalPortals = React.useMemo(\r\n () => (Array.isArray(nationalPortals) ? nationalPortals.filter(p => matchesOrgCountry(p.country)) : []),\r\n [nationalPortals, matchesOrgCountry],\r\n )\r\n\r\n const municipal = useDatasetsForPortals(filteredMunicipalPortals, { rowsPerPage })\r\n const subdivision = useDatasetsForPortals(filteredSubdivisionPortals, { rowsPerPage })\r\n const national = useDatasetsForPortals(filteredNationalPortals, { rowsPerPage })\r\n\r\n React.useEffect(() => {\r\n const loadOrganizationalDatasets = async () => {\r\n try {\r\n const martinBaseUrlClean = (martinBaseUrl ?? '').replace(/\\/+$/, '')\r\n if (!martinBaseUrlClean) return\r\n\r\n const datasetsUrl = martinBaseUrlClean.includes('/tiles/index.json')\r\n ? martinBaseUrlClean\r\n : `${martinBaseUrlClean}/tiles/index.json`\r\n\r\n const localPortal = {\r\n id: -1,\r\n name: 'Organizational Datasets',\r\n apiUrl: datasetsUrl,\r\n dataManagementSystem: 'Other' as const,\r\n countrySubdivision: null,\r\n municipality: null,\r\n group: 'Organizational' as const,\r\n }\r\n\r\n const organizationalDatasets = await fetchLocalDatasets(localPortal as any)\r\n const visible = organizationalDatasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))\r\n if (visible.length > 0) {\r\n datasetDispatch({ type: 'SET_DATASETS', payload: { datasets: visible } })\r\n }\r\n }\r\n catch (error) {\r\n console.error('Failed to load organizational datasets:', error)\r\n }\r\n }\r\n loadOrganizationalDatasets()\r\n }, [datasetDispatch, orgVisibility])\r\n\r\n const nationalDatasets = React.useMemo(\r\n () => sanitizeDatasets(national.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [national.datasets, orgVisibility],\r\n )\r\n const subdivisionDatasets = React.useMemo(\r\n () => sanitizeDatasets(subdivision.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [subdivision.datasets, orgVisibility],\r\n )\r\n const municipalDatasets = React.useMemo(\r\n () => sanitizeDatasets(municipal.datasets.filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [municipal.datasets, orgVisibility],\r\n )\r\n const orgDatasets = React.useMemo(\r\n () => sanitizeDatasets((datasetState.datasets.datasets || []).filter(ds => datasetVisibleForOrg(ds, orgVisibility))),\r\n [datasetState.datasets.datasets, orgVisibility],\r\n )\r\n\r\n const allDatasets = React.useMemo(() => {\r\n const combined = [...nationalDatasets, ...subdivisionDatasets, ...municipalDatasets, ...orgDatasets]\r\n return sanitizeDatasets(combined)\r\n }, [nationalDatasets, subdivisionDatasets, municipalDatasets, orgDatasets])\r\n\r\n const liveDatasets = React.useMemo(\r\n () => allDatasets.filter(ds => ds.portal?.live === true),\r\n [allDatasets],\r\n )\r\n\r\n const toggleFavourite = React.useCallback((dataset: Dataset) => {\r\n setFavourites(prev => (\r\n prev.some(f => f.name === dataset.name)\r\n ? prev.filter(f => f.name !== dataset.name)\r\n : [...prev, dataset]\r\n ))\r\n }, [])\r\n\r\n const showMunicipal = Boolean(municipality)\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-4 py-4 overflow-hidden\">\r\n <div className=\"px-4\">\r\n <SearchInput\r\n placeholder=\"Search...\"\r\n value={searchQuery}\r\n onChange={e => setSearchQuery(e.target.value)}\r\n />\r\n </div>\r\n <div className=\"flex-1 min-h-0 overflow-y-auto space-y-2 divide-y\">\r\n <div className=\"pb-2\">\r\n <AppliedDatasetsSection />\r\n </div>\r\n <div className=\"pt-2\">\r\n <AvailableDatasetsSection\r\n query={searchQuery}\r\n allDatasets={allDatasets}\r\n nationalDatasets={nationalDatasets}\r\n subdivisionDatasets={subdivisionDatasets}\r\n municipalDatasets={municipalDatasets}\r\n organizationalDatasets={orgDatasets}\r\n liveDatasets={liveDatasets}\r\n showMunicipal={showMunicipal}\r\n favourites={favourites}\r\n onFavouriteToggle={toggleFavourite}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a"]}
@@ -5,5 +5,7 @@ export interface FileItem {
5
5
  icon: React.ElementType;
6
6
  visible: boolean;
7
7
  }
8
- export declare function SensorsTab(): React.JSX.Element;
8
+ export declare function SensorsTab({ minioBaseUrl }: {
9
+ minioBaseUrl?: string;
10
+ }): React.JSX.Element;
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAA;AAE3D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,CAAC,WAAW,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,UAAU,sBAMzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAA;AAE3D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,CAAC,WAAW,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,YAAY,EAAE,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,qBAMrE"}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { SensorsSection } from "../../../../../../ui/Sensors/SensorsSection";
4
- function SensorsTab() {
5
- return /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col space-y-6 py-4 overflow-hidden", children: /* @__PURE__ */ jsx(SensorsSection, {}) });
4
+ function SensorsTab({ minioBaseUrl }) {
5
+ return /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col space-y-6 py-4 overflow-hidden", children: /* @__PURE__ */ jsx(SensorsSection, { minioBaseUrl }) });
6
6
  }
7
7
  export {
8
8
  SensorsTab
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { DbFile } from '../../../../../../../types/dbTypes'\r\nimport { SensorsSection } from '../../../../../../ui/Sensors/SensorsSection'\r\nexport interface FileItem {\r\n task: DbFile\r\n icon: React.ElementType\r\n visible: boolean\r\n}\r\n\r\nexport function SensorsTab() {\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-6 py-4 overflow-hidden\">\r\n <SensorsSection />\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAiBM;AAVN,SAAS,sBAAsB;AAOxB,SAAS,aAAa;AAC3B,SACE,oBAAC,SAAI,WAAU,uDACb,8BAAC,kBAAe,GAClB;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport { DbFile } from '../../../../../../../types/dbTypes'\r\nimport { SensorsSection } from '../../../../../../ui/Sensors/SensorsSection'\r\nexport interface FileItem {\r\n task: DbFile\r\n icon: React.ElementType\r\n visible: boolean\r\n}\r\n\r\nexport function SensorsTab({ minioBaseUrl }: { minioBaseUrl?: string }) {\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-6 py-4 overflow-hidden\">\r\n <SensorsSection minioBaseUrl={minioBaseUrl} />\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAiBM;AAVN,SAAS,sBAAsB;AAOxB,SAAS,WAAW,EAAE,aAAa,GAA8B;AACtE,SACE,oBAAC,SAAI,WAAU,uDACb,8BAAC,kBAAe,cAA4B,GAC9C;AAEJ;","names":[]}
@@ -1,3 +1,5 @@
1
1
  import * as React from "react";
2
- export declare function SettingsTab(): React.JSX.Element;
2
+ export declare function SettingsTab({ countryCode }: {
3
+ countryCode?: string;
4
+ }): React.JSX.Element;
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,wBAAgB,WAAW,sBAO1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,qBAOpE"}
@@ -2,10 +2,10 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { LocationSettings } from "./src/LocationSettings";
4
4
  import { MapCustomization } from "./src/MapCustomization";
5
- function SettingsTab() {
5
+ function SettingsTab({ countryCode }) {
6
6
  return /* @__PURE__ */ jsxs("div", { className: "w-full h-full flex flex-col gap-6 p-4 overflow-y-auto point", children: [
7
7
  /* @__PURE__ */ jsx(MapCustomization, {}),
8
- /* @__PURE__ */ jsx(LocationSettings, {})
8
+ /* @__PURE__ */ jsx(LocationSettings, { countryCode })
9
9
  ] });
10
10
  }
11
11
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\nimport { LocationSettings } from './src/LocationSettings';\r\nimport { MapCustomization } from './src/MapCustomization';\r\n\r\nexport function SettingsTab() {\r\n return (\r\n <div className=\"w-full h-full flex flex-col gap-6 p-4 overflow-y-auto point\">\r\n <MapCustomization />\r\n <LocationSettings />\r\n </div>\r\n )\r\n}"],"mappings":";AAWI,SACE,KADF;AALJ,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAE1B,SAAS,cAAc;AAC5B,SACE,qBAAC,SAAI,WAAU,+DACb;AAAA,wBAAC,oBAAiB;AAAA,IAClB,oBAAC,oBAAiB;AAAA,KACpB;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/index.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\nimport { LocationSettings } from './src/LocationSettings';\r\nimport { MapCustomization } from './src/MapCustomization';\r\n\r\nexport function SettingsTab({ countryCode }: { countryCode?: string }) {\r\n return (\r\n <div className=\"w-full h-full flex flex-col gap-6 p-4 overflow-y-auto point\">\r\n <MapCustomization />\r\n <LocationSettings countryCode={countryCode} />\r\n </div>\r\n )\r\n}"],"mappings":";AAWI,SACE,KADF;AALJ,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAE1B,SAAS,YAAY,EAAE,YAAY,GAA6B;AACrE,SACE,qBAAC,SAAI,WAAU,+DACb;AAAA,wBAAC,oBAAiB;AAAA,IAClB,oBAAC,oBAAiB,aAA0B;AAAA,KAC9C;AAEJ;","names":[]}
@@ -1,3 +1,5 @@
1
1
  import * as React from "react";
2
- export declare function LocationSettings(): React.JSX.Element;
2
+ export declare function LocationSettings({ countryCode }: {
3
+ countryCode?: string;
4
+ }): React.JSX.Element;
3
5
  //# sourceMappingURL=LocationSettings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LocationSettings.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,wBAAgB,gBAAgB,sBAkU/B"}
1
+ {"version":3,"file":"LocationSettings.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/LocationSettings.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,wBAAgB,gBAAgB,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,qBAiUzE"}