@collabdt/core 0.0.42 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/components/Toolbar.d.ts.map +1 -1
- package/dist/core/components/Toolbar.js.map +1 -1
- package/dist/core/components/ToolbarBody.js.map +1 -1
- package/dist/core/components/TopNavigationBar.js.map +1 -1
- package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
- package/dist/core/components/authentication/Signin.js.map +1 -1
- package/dist/core/components/authentication/Signup.js.map +1 -1
- package/dist/core/components/settings/src/OrganizationSkeleton.js.map +1 -1
- package/dist/core/components/settings/src/SettingsSkeleton.js.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
- package/dist/core/components/ui/DataTable.d.ts.map +1 -1
- package/dist/core/components/ui/DataTable.js +7 -0
- package/dist/core/components/ui/DataTable.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileItemComponent.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileItemComponent.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts +5 -2
- package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileMarker.js +84 -21
- package/dist/core/components/ui/FilesManager/src/FileMarker.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.js.map +1 -1
- package/dist/core/components/ui/Icons/IfcIcon.d.ts.map +1 -1
- package/dist/core/components/ui/Icons/IfcIcon.js.map +1 -1
- package/dist/core/components/ui/InfoSidebar/index.d.ts.map +1 -1
- package/dist/core/components/ui/InfoSidebar/index.js.map +1 -1
- package/dist/core/components/ui/Navbar.d.ts.map +1 -1
- package/dist/core/components/ui/Navbar.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.d.ts.map +1 -1
- package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.js.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js +2 -2
- package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js.map +1 -1
- package/dist/core/components/viewers/Data/infrastructureDetails/FieldRenderer.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/infrastructureDetails/FieldRenderer.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js +2 -2
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
- package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
- package/dist/core/components/viewers/Viewer.js +5 -1
- package/dist/core/components/viewers/Viewer.js.map +1 -1
- package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
- package/dist/core/components/viewers/bim/BimViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/BimViewer.js +14 -5
- package/dist/core/components/viewers/bim/BimViewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.js +6 -0
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +168 -39
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
- package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts +14 -37
- package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/DXFLoader/index.js +31 -318
- package/dist/core/components/viewers/bim/src/DXFLoader/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts +66 -7
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.js +253 -21
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ModelManager/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ModelManager/index.js +9 -0
- package/dist/core/components/viewers/bim/src/ModelManager/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/SimpleBimViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/SimpleBimViewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts +3 -2
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.js.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js +3 -4
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +40 -18
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts +2 -5
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js +45 -59
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts +10 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js +25 -73
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts +7 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js +42 -78
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js +52 -75
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts +15 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js +165 -105
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js.map +1 -1
- package/dist/core/components/viewers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/index.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +32 -8
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.js +4 -3
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/RowActions.js +148 -0
- package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.js +32 -15
- package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts +4 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js +43 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js +39 -3
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +2 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts +47 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.js +114 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.js.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts +49 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.js +100 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.js.map +1 -0
- package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/Geocoder.js +9 -9
- package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +25 -43
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js +19 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts +9 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js +28 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +1 -16
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js +31 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts +21 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js +111 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js +77 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js +19 -9
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +10 -3
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.d.ts +6 -2
- package/dist/core/components/viewers/map/utils/geocoder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.js +10 -62
- package/dist/core/components/viewers/map/utils/geocoder.js.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts +5 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.js +192 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +6 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.js +14 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.d.ts +8 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.js +44 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts +6 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.js +39 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts +8 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.js +35 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -0
- package/dist/core/components/viewers/pointcloud/PointCloudToolbar.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/PointCloudToolbar.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +1 -3
- package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js +8 -2
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js +9 -9
- package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js.map +1 -1
- package/dist/core/hooks/provider.js.map +1 -1
- package/dist/core/plugins/host/provider.d.ts.map +1 -1
- package/dist/core/plugins/host/provider.js.map +1 -1
- package/dist/core/store/AppConfig/context.d.ts.map +1 -1
- package/dist/core/store/AppConfig/context.js.map +1 -1
- package/dist/core/store/BIM/context.d.ts.map +1 -1
- package/dist/core/store/BIM/context.js.map +1 -1
- package/dist/core/store/BIM/reducer.d.ts +0 -1
- package/dist/core/store/BIM/reducer.d.ts.map +1 -1
- package/dist/core/store/BIM/reducer.js +0 -4
- package/dist/core/store/BIM/reducer.js.map +1 -1
- package/dist/core/store/Buildings/context.d.ts.map +1 -1
- package/dist/core/store/Buildings/context.js.map +1 -1
- package/dist/core/store/Content/context.d.ts.map +1 -1
- package/dist/core/store/Content/context.js.map +1 -1
- package/dist/core/store/Datasets/context.d.ts.map +1 -1
- package/dist/core/store/Datasets/context.js +2 -1
- package/dist/core/store/Datasets/context.js.map +1 -1
- package/dist/core/store/Datasets/reducer.d.ts +2 -0
- package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
- package/dist/core/store/Datasets/reducer.js +9 -4
- package/dist/core/store/Datasets/reducer.js.map +1 -1
- package/dist/core/store/Files/context.d.ts.map +1 -1
- package/dist/core/store/Files/context.js.map +1 -1
- package/dist/core/store/Map/context.d.ts.map +1 -1
- package/dist/core/store/Map/context.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Permissions/context.d.ts.map +1 -1
- package/dist/core/store/Permissions/context.js.map +1 -1
- package/dist/core/store/PointCloud/context.d.ts.map +1 -1
- package/dist/core/store/PointCloud/context.js.map +1 -1
- package/dist/core/store/Tools/context.d.ts.map +1 -1
- package/dist/core/store/Tools/context.js.map +1 -1
- package/dist/core/types/datasetTypes.d.ts +8 -1
- package/dist/core/types/datasetTypes.d.ts.map +1 -1
- package/dist/core/types/dbTypes.d.ts +13 -13
- package/dist/core/types/dbTypes.d.ts.map +1 -1
- package/dist/core/types/dbTypes.js +13 -13
- package/dist/core/types/dbTypes.js.map +1 -1
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js.map +1 -1
- package/dist/core/utils/imageUtils.js +1 -1
- package/dist/core/utils/imageUtils.js.map +1 -1
- package/package.json +4 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts +0 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts.map +0 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js +0 -173
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"sourcesContent":["'use client'\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Context\r\nimport { MapContext } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { fetchSuggestions, parseLocation, handleLocationSelect, buildingToFeature } from '../utils/geocoder'\r\n\r\n// Import the shadcn components\r\nimport { Command, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '../../../ui/Command'\r\nimport { Button } from '../../../ui/Button'\r\nimport { Input } from '../../../ui/Input'\r\nimport { Separator } from '../../../ui/Separator'\r\n\r\n// Icons\r\nimport { Search } from 'lucide-react'\r\n\r\n// Building data hook\r\nimport { useBuildings } from '../../../../hooks/buildings/buildings'\r\n\r\nimport { usePathname } from 'next/navigation'\r\nimport type { CurrentLocation } from '../../../../types/map'\r\nimport { LoadingSpinner } from '../../../ui/LoadingSpinner'\r\n\r\ninterface GeocoderProps {\r\n onSelect?: (addressData: any) => void\r\n showDatabaseBuildings?: boolean\r\n alwaysExpanded?: boolean\r\n}\r\n\r\nexport default function Geocoder({\r\n onSelect,\r\n showDatabaseBuildings = true,\r\n alwaysExpanded = false,\r\n}: GeocoderProps) {\r\n // Translation\r\n const t = useTranslations('Geocoder')\r\n\r\n const [address, setAddress] = React.useState<string>('')\r\n const [query, setQuery] = React.useState('')\r\n const [suggestions, setSuggestions] = React.useState([])\r\n const [buildingResults, setBuildingResults] = React.useState([])\r\n const [focused, setFocused] = React.useState(alwaysExpanded)\r\n const [selectedAddress, setSelectedAddress] = React.useState(null)\r\n const [isExpanded, setIsExpanded] = React.useState(alwaysExpanded)\r\n const [loading, setLoading] = React.useState(false)\r\n\r\n const pathname = usePathname()\r\n\r\n const suggestionsRef = React.useRef(null)\r\n const inputRef = React.useRef(null)\r\n const debounceRef = React.useRef(null)\r\n\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n const { map, currentLocation, organizationCountry } = mapState.map\r\n\r\n // Fetch buildings data from API only if showDatabaseBuildings is true\r\n const { buildings, isLoading: isBuildingsLoading } = useBuildings()\r\n\r\n // Filter buildings based on search query\r\n const filterBuildings = React.useCallback((searchQuery) => {\r\n if (!showDatabaseBuildings || !buildings || !searchQuery || searchQuery.length < 3) return []\r\n\r\n const lowerQuery = searchQuery.toLowerCase()\r\n\r\n if (Array.isArray(buildings) && buildings.length > 0) {\r\n return buildings.filter((building) => {\r\n return (\r\n (building.buildingName && building.buildingName.toLowerCase().includes(lowerQuery))\r\n || (building.buildingAddress && building.buildingAddress.toLowerCase().includes(lowerQuery))\r\n || (building.buildingMunicipality && building.buildingMunicipality.toLowerCase().includes(lowerQuery))\r\n || (building.buildingCountrySubdivision && building.buildingCountrySubdivision.toLowerCase().includes(lowerQuery))\r\n )\r\n }).slice(0, 3) // Limit to 3 results\r\n }\r\n return []\r\n }, [buildings, showDatabaseBuildings])\r\n\r\n // Debounce the API request to avoid rate limiting and excessive requests\r\n React.useEffect(() => {\r\n if (debounceRef.current) {\r\n clearTimeout(debounceRef.current)\r\n }\r\n\r\n debounceRef.current = setTimeout(async () => {\r\n if (!query || query.length < 3) {\r\n setSuggestions([])\r\n setBuildingResults([])\r\n setLoading(false)\r\n return\r\n }\r\n\r\n setLoading(true)\r\n try {\r\n // Filter buildings from our database only if enabled\r\n if (showDatabaseBuildings) {\r\n const filteredBuildings = filterBuildings(query)\r\n setBuildingResults(filteredBuildings)\r\n }\r\n\r\n // Fetch geocoding suggestions\r\n const geocodeResults = await fetchSuggestions(query, organizationCountry)\r\n \r\n // Deduplicate geocode results based on name and region\r\n const deduplicatedResults = geocodeResults.reduce((acc, feature) => {\r\n const location = parseLocation(feature)\r\n // Create a unique key based on name and region (case-insensitive)\r\n const key = `${location.name?.toLowerCase() || ''}_${location.region?.toLowerCase() || ''}`\r\n \r\n // Only add if we haven't seen this combination before\r\n if (!acc.seen.has(key)) {\r\n acc.seen.add(key)\r\n acc.features.push(feature)\r\n }\r\n \r\n return acc\r\n }, { seen: new Set(), features: [] })\r\n \r\n setSuggestions(deduplicatedResults.features)\r\n }\r\n catch (error) {\r\n console.error('Error fetching suggestions:', error)\r\n setSuggestions([])\r\n }\r\n finally {\r\n setLoading(false)\r\n }\r\n }, 300) // Increased debounce time for better API rate limiting\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [query, filterBuildings, showDatabaseBuildings])\r\n\r\n // Handle click outside to close suggestions\r\n React.useEffect(() => {\r\n const handleClickOutside = (event) => {\r\n if (suggestionsRef.current && !suggestionsRef.current.contains(event.target)\r\n && inputRef.current && !inputRef.current.contains(event.target) // Don't close if alwaysExpanded is true\r\n && !alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n }\r\n\r\n document.addEventListener('mousedown', handleClickOutside)\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside)\r\n }\r\n }, [alwaysExpanded])\r\n\r\n // Handle suggestion selection\r\n const handleSelectSuggestion = (feature, type = '') => {\r\n setQuery('') // Clear the input field\r\n setSuggestions([])\r\n setBuildingResults([])\r\n if (!alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n\r\n // handleLocationSelect will automatically remove any existing marker and add a new one\r\n const addressData = handleLocationSelect(feature, map, type)\r\n\r\n const address = addressData.formatted_address || feature.properties?.label || ''\r\n setAddress(address)\r\n setSelectedAddress(addressData)\r\n\r\n if (onSelect) onSelect(addressData)\r\n\r\n if (mapDispatch && currentLocation) {\r\n const [lng, lat] = addressData.coordinates\r\n const countrySubdivision: string = addressData.properties?.region_a\r\n // Extract municipality (3rd from the right)\r\n const parts = address.split(',').map(p => p.trim())\r\n const partsReverse = [...parts].reverse()\r\n console.log('parts', parts, 'partsReverse', partsReverse)\r\n let municipality = ''\r\n if (partsReverse[1] === countrySubdivision) municipality = partsReverse[2] || ''\r\n\r\n const newCurrentLocation: CurrentLocation = { ...currentLocation, municipality, countrySubdivision, longitude: lng, latitude: lat, address: parts[0] }\r\n mapDispatch({ type: 'UPDATE_LOCATION', payload: { currentLocation: newCurrentLocation } })\r\n if (municipality && countrySubdivision) {\r\n const url = new URL(window.location.href)\r\n url.searchParams.set('municipality', municipality)\r\n url.searchParams.set('countrySubdivision', countrySubdivision)\r\n url.searchParams.set('address', parts[0])\r\n url.searchParams.set('lng', lng.toString())\r\n url.searchParams.set('lat', lat.toString())\r\n url.searchParams.set('zoom', '18')\r\n window.history.replaceState({}, '', url.toString())\r\n }\r\n }\r\n }\r\n\r\n // Handle expand of menubar to display search input\r\n const handleExpand = () => {\r\n if (alwaysExpanded) return // Don't allow toggling if always expanded\r\n\r\n setIsExpanded(!isExpanded)\r\n if (isExpanded) {\r\n setFocused(false)\r\n setQuery('') // clear input and suggestions when collapsed\r\n setSuggestions([])\r\n setBuildingResults([])\r\n }\r\n else {\r\n setFocused(true)\r\n setTimeout(() => {\r\n inputRef.current?.focus()\r\n }, 100) // Small delay to ensure the input is rendered\r\n }\r\n }\r\n\r\n return (\r\n <Command>\r\n {/* Search input + button */}\r\n <div className={`flex flex-row justify-start items-center w-full h-auto `}>\r\n {!alwaysExpanded && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={handleExpand}\r\n className=\"opacity-70 w-6 justify-end hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <Search />\r\n </Button>\r\n )}\r\n {alwaysExpanded && (\r\n <Search className=\"h-4 w-4 opacity-50\" />\r\n )}\r\n <Input\r\n ref={inputRef}\r\n type=\"text\"\r\n value={query}\r\n onChange={e => setQuery(e.target.value)}\r\n onFocus={() => setFocused(true)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n inputRef.current?.blur()\r\n }\r\n }}\r\n placeholder={alwaysExpanded ? t('placeholder1') : t('placeholder2')}\r\n className={`border-none focus-visible:ring-transparent text-sm transition-all ease-in-out duration-200 ${\r\n alwaysExpanded || isExpanded ? 'w-full' : 'w-0 p-0'\r\n }`}\r\n />\r\n </div>\r\n\r\n {focused && (loading || buildingResults.length > 0 || suggestions.length > 0) && (\r\n <div ref={suggestionsRef}>\r\n <Separator />\r\n <CommandList>\r\n {!loading && buildingResults.length === 0 && suggestions.length === 0 && query.length >= 3 && (\r\n <CommandEmpty>{showDatabaseBuildings ? t('noResults') : t('noAddresses')}</CommandEmpty>\r\n )}\r\n\r\n {loading && (\r\n <CommandEmpty><LoadingSpinner /></CommandEmpty>\r\n )}\r\n\r\n {/* Database Buildings section - only show if enabled */}\r\n {showDatabaseBuildings && !loading && buildingResults.length > 0 && (\r\n <CommandGroup heading={t('buildingHeader')}>\r\n {buildingResults.map((building) => {\r\n const buildingFeature = buildingToFeature(building)\r\n\r\n return (\r\n <CommandItem\r\n key={`building-${building.id}`}\r\n onSelect={() => handleSelectSuggestion(buildingFeature, 'dbBuilding')}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{building.buildingName}</div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {building.buildingAddress}\r\n </div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n\r\n {/* Separator between sections if both have results */}\r\n {showDatabaseBuildings && buildingResults.length > 0 && suggestions.length > 0 && (\r\n <CommandSeparator />\r\n )}\r\n\r\n {/* Geocoder suggestions section */}\r\n {!loading && suggestions.length > 0 && (\r\n <CommandGroup heading={showDatabaseBuildings ? t('suggestionsHeader') : undefined}>\r\n {suggestions.map((feature) => {\r\n const location = parseLocation(feature)\r\n const uniqueKey = feature.properties?.gid\r\n || `${feature.properties?.name}-${feature.geometry?.coordinates?.[0]}-${feature.geometry?.coordinates?.[1]}`\r\n\r\n return (\r\n <CommandItem\r\n key={uniqueKey}\r\n onSelect={() => handleSelectSuggestion(feature)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{location.name}</div>\r\n <div className=\"text-sm text-muted-foreground\">{location.region}</div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n </CommandList>\r\n </div>\r\n )}\r\n </Command>\r\n )\r\n}"],"mappings":"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","names":["address"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"sourcesContent":["'use client'\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Context\r\nimport { MapContext } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { fetchSuggestions, parseLocation, handleLocationSelect, buildingToFeature } from '../utils/geocoder'\r\n\r\n// Import the shadcn components\r\nimport { Command, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '../../../ui/Command'\r\nimport { Button } from '../../../ui/Button'\r\nimport { Input } from '../../../ui/Input'\r\nimport { Separator } from '../../../ui/Separator'\r\n\r\n// Icons\r\nimport { Search } from 'lucide-react'\r\n\r\n// Building data hook\r\nimport { useBuildings } from '../../../../hooks/buildings/buildings'\r\n\r\nimport { usePathname } from 'next/navigation'\r\nimport type { CurrentLocation } from '../../../../types/map'\r\nimport { LoadingSpinner } from '../../../ui/LoadingSpinner'\r\n\r\ninterface GeocoderProps {\r\n onSelect?: (addressData: any) => void\r\n showDatabaseBuildings?: boolean\r\n alwaysExpanded?: boolean\r\n}\r\n\r\nexport default function Geocoder({\r\n onSelect,\r\n showDatabaseBuildings = true,\r\n alwaysExpanded = false,\r\n}: GeocoderProps) {\r\n // Translation\r\n const t = useTranslations('Geocoder')\r\n\r\n const [address, setAddress] = React.useState<string>('')\r\n const [query, setQuery] = React.useState('')\r\n const [suggestions, setSuggestions] = React.useState([])\r\n const [buildingResults, setBuildingResults] = React.useState([])\r\n const [focused, setFocused] = React.useState(alwaysExpanded)\r\n const [selectedAddress, setSelectedAddress] = React.useState(null)\r\n const [isExpanded, setIsExpanded] = React.useState(alwaysExpanded)\r\n const [loading, setLoading] = React.useState(false)\r\n\r\n const pathname = usePathname()\r\n\r\n const suggestionsRef = React.useRef(null)\r\n const inputRef = React.useRef(null)\r\n const debounceRef = React.useRef(null)\r\n\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n const { map, currentLocation, organizationCountry } = mapState.map\r\n\r\n // Fetch buildings data from API only if showDatabaseBuildings is true\r\n const { buildings, isLoading: isBuildingsLoading } = useBuildings()\r\n\r\n // Filter buildings based on search query\r\n const filterBuildings = React.useCallback((searchQuery) => {\r\n if (!showDatabaseBuildings || !buildings || !searchQuery || searchQuery.length < 3) return []\r\n\r\n const lowerQuery = searchQuery.toLowerCase()\r\n\r\n if (Array.isArray(buildings) && buildings.length > 0) {\r\n return buildings.filter((building) => {\r\n return (\r\n (building.buildingName && building.buildingName.toLowerCase().includes(lowerQuery))\r\n || (building.buildingAddress && building.buildingAddress.toLowerCase().includes(lowerQuery))\r\n || (building.buildingMunicipality && building.buildingMunicipality.toLowerCase().includes(lowerQuery))\r\n || (building.buildingCountrySubdivision && building.buildingCountrySubdivision.toLowerCase().includes(lowerQuery))\r\n )\r\n }).slice(0, 3) // Limit to 3 results\r\n }\r\n return []\r\n }, [buildings, showDatabaseBuildings])\r\n\r\n // Debounce the API request to avoid rate limiting and excessive requests\r\n React.useEffect(() => {\r\n if (debounceRef.current) {\r\n clearTimeout(debounceRef.current)\r\n }\r\n\r\n debounceRef.current = setTimeout(async () => {\r\n if (!query || query.length < 3) {\r\n setSuggestions([])\r\n setBuildingResults([])\r\n setLoading(false)\r\n return\r\n }\r\n\r\n setLoading(true)\r\n try {\r\n // Filter buildings from our database only if enabled\r\n if (showDatabaseBuildings) {\r\n const filteredBuildings = filterBuildings(query)\r\n setBuildingResults(filteredBuildings)\r\n }\r\n\r\n // Fetch geocoding suggestions\r\n const geocodeResults = await fetchSuggestions(query, organizationCountry)\r\n \r\n // Deduplicate geocode results based on name and region\r\n const deduplicatedResults = geocodeResults.reduce((acc, feature) => {\r\n const location = parseLocation(feature)\r\n // Create a unique key based on name and region (case-insensitive)\r\n const key = `${location.name?.toLowerCase() || ''}_${location.region?.toLowerCase() || ''}`\r\n \r\n // Only add if we haven't seen this combination before\r\n if (!acc.seen.has(key)) {\r\n acc.seen.add(key)\r\n acc.features.push(feature)\r\n }\r\n \r\n return acc\r\n }, { seen: new Set(), features: [] })\r\n \r\n setSuggestions(deduplicatedResults.features)\r\n }\r\n catch (error) {\r\n console.error('Error fetching suggestions:', error)\r\n setSuggestions([])\r\n }\r\n finally {\r\n setLoading(false)\r\n }\r\n }, 300) // Increased debounce time for better API rate limiting\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [query, filterBuildings, showDatabaseBuildings])\r\n\r\n // Handle click outside to close suggestions\r\n React.useEffect(() => {\r\n const handleClickOutside = (event) => {\r\n if (suggestionsRef.current && !suggestionsRef.current.contains(event.target)\r\n && inputRef.current && !inputRef.current.contains(event.target) // Don't close if alwaysExpanded is true\r\n && !alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n }\r\n\r\n document.addEventListener('mousedown', handleClickOutside)\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside)\r\n }\r\n }, [alwaysExpanded])\r\n\r\n // Handle suggestion selection\r\n const handleSelectSuggestion = (feature, type = '') => {\r\n setQuery('') // Clear the input field\r\n setSuggestions([])\r\n setBuildingResults([])\r\n if (!alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n\r\n // handleLocationSelect will automatically remove any existing marker and add a new one\r\n const addressData = handleLocationSelect(feature, map, type)\r\n\r\n const address = addressData.formatted_address || feature.properties?.label || ''\r\n setAddress(address)\r\n setSelectedAddress(addressData)\r\n\r\n if (onSelect) onSelect(addressData)\r\n\r\n if (mapDispatch && currentLocation) {\r\n const [lng, lat] = addressData.coordinates\r\n const props = addressData.properties || {}\r\n const parts = address.split(',').map(p => p.trim())\r\n // Read structured properties (provider-agnostic) instead of parsing label tokens,\r\n // which only matched Geocode Earth's \"…, ON, Canada\" abbreviation format and broke\r\n // on the Photon/Nominatim fallback.\r\n const countrySubdivision: string = props.region_a || props.region || ''\r\n const municipality: string = props.locality || props.neighbourhood || props.county || ''\r\n\r\n const newCurrentLocation: CurrentLocation = { ...currentLocation, municipality, countrySubdivision, longitude: lng, latitude: lat, address: parts[0] }\r\n mapDispatch({ type: 'UPDATE_LOCATION', payload: { currentLocation: newCurrentLocation } })\r\n if (municipality || countrySubdivision) {\r\n const url = new URL(window.location.href)\r\n // Write each field only when present, so an empty param doesn't shadow the\r\n // organization fallback MapViewer applies on reload.\r\n if (municipality) url.searchParams.set('municipality', municipality)\r\n else url.searchParams.delete('municipality')\r\n if (countrySubdivision) url.searchParams.set('countrySubdivision', countrySubdivision)\r\n else url.searchParams.delete('countrySubdivision')\r\n url.searchParams.set('address', parts[0])\r\n url.searchParams.set('lng', lng.toString())\r\n url.searchParams.set('lat', lat.toString())\r\n url.searchParams.set('zoom', '18')\r\n window.history.replaceState({}, '', url.toString())\r\n }\r\n }\r\n }\r\n\r\n // Handle expand of menubar to display search input\r\n const handleExpand = () => {\r\n if (alwaysExpanded) return // Don't allow toggling if always expanded\r\n\r\n setIsExpanded(!isExpanded)\r\n if (isExpanded) {\r\n setFocused(false)\r\n setQuery('') // clear input and suggestions when collapsed\r\n setSuggestions([])\r\n setBuildingResults([])\r\n }\r\n else {\r\n setFocused(true)\r\n setTimeout(() => {\r\n inputRef.current?.focus()\r\n }, 100) // Small delay to ensure the input is rendered\r\n }\r\n }\r\n\r\n return (\r\n <Command>\r\n {/* Search input + button */}\r\n <div className={`flex flex-row justify-start items-center w-full h-auto `}>\r\n {!alwaysExpanded && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={handleExpand}\r\n className=\"opacity-70 w-6 justify-end hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <Search />\r\n </Button>\r\n )}\r\n {alwaysExpanded && (\r\n <Search className=\"h-4 w-4 opacity-50\" />\r\n )}\r\n <Input\r\n ref={inputRef}\r\n type=\"text\"\r\n value={query}\r\n onChange={e => setQuery(e.target.value)}\r\n onFocus={() => setFocused(true)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n inputRef.current?.blur()\r\n }\r\n }}\r\n placeholder={alwaysExpanded ? t('placeholder1') : t('placeholder2')}\r\n className={`border-none focus-visible:ring-transparent text-sm transition-all ease-in-out duration-200 ${\r\n alwaysExpanded || isExpanded ? 'w-full' : 'w-0 p-0'\r\n }`}\r\n />\r\n </div>\r\n\r\n {focused && (loading || buildingResults.length > 0 || suggestions.length > 0) && (\r\n <div ref={suggestionsRef}>\r\n <Separator />\r\n <CommandList>\r\n {!loading && buildingResults.length === 0 && suggestions.length === 0 && query.length >= 3 && (\r\n <CommandEmpty>{showDatabaseBuildings ? t('noResults') : t('noAddresses')}</CommandEmpty>\r\n )}\r\n\r\n {loading && (\r\n <CommandEmpty><LoadingSpinner /></CommandEmpty>\r\n )}\r\n\r\n {/* Database Buildings section - only show if enabled */}\r\n {showDatabaseBuildings && !loading && buildingResults.length > 0 && (\r\n <CommandGroup heading={t('buildingHeader')}>\r\n {buildingResults.map((building) => {\r\n const buildingFeature = buildingToFeature(building)\r\n\r\n return (\r\n <CommandItem\r\n key={`building-${building.id}`}\r\n onSelect={() => handleSelectSuggestion(buildingFeature, 'dbBuilding')}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{building.buildingName}</div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {building.buildingAddress}\r\n </div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n\r\n {/* Separator between sections if both have results */}\r\n {showDatabaseBuildings && buildingResults.length > 0 && suggestions.length > 0 && (\r\n <CommandSeparator />\r\n )}\r\n\r\n {/* Geocoder suggestions section */}\r\n {!loading && suggestions.length > 0 && (\r\n <CommandGroup heading={showDatabaseBuildings ? t('suggestionsHeader') : undefined}>\r\n {suggestions.map((feature) => {\r\n const location = parseLocation(feature)\r\n const uniqueKey = feature.properties?.gid\r\n || `${feature.properties?.name}-${feature.geometry?.coordinates?.[0]}-${feature.geometry?.coordinates?.[1]}`\r\n\r\n return (\r\n <CommandItem\r\n key={uniqueKey}\r\n onSelect={() => handleSelectSuggestion(feature)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{location.name}</div>\r\n <div className=\"text-sm text-muted-foreground\">{location.region}</div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n </CommandList>\r\n </div>\r\n )}\r\n </Command>\r\n )\r\n}"],"mappings":"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","names":["address"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NonDatabaseBuildingPopover.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"NonDatabaseBuildingPopover.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAWpD,UAAU,+BAA+B;IACvC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,EACjD,OAAO,EACP,aAAa,GACd,EAAE,+BAA+B,qBA4cjC"}
|
package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js
CHANGED
|
@@ -34,6 +34,7 @@ import * as LR from "lucide-react";
|
|
|
34
34
|
import { MapContext } from "../../../../../../store";
|
|
35
35
|
import { useMenusContext } from "../../../../../../store";
|
|
36
36
|
import { MarkerManager } from "../../../utils/MarkerManager";
|
|
37
|
+
import { getDetailedAddress } from "../../../utils/geocoder";
|
|
37
38
|
import { useCreateBuilding, useBuildings, useBuilding } from "../../../../../../hooks/buildings/buildings";
|
|
38
39
|
import { LoadingSpinner } from "../../../../../ui/LoadingSpinner";
|
|
39
40
|
function NonDatabaseBuildingPopover({
|
|
@@ -45,7 +46,7 @@ function NonDatabaseBuildingPopover({
|
|
|
45
46
|
const { data: session } = useSession();
|
|
46
47
|
const user = session == null ? void 0 : session.user;
|
|
47
48
|
const { state: mapState } = React.useContext(MapContext);
|
|
48
|
-
const { currentLocation, map } = mapState.map;
|
|
49
|
+
const { currentLocation, map, organizationCountry } = mapState.map;
|
|
49
50
|
const { setSelectedItem } = useMenusContext();
|
|
50
51
|
const { createBuilding, isMutating, createError, createdData } = useCreateBuilding();
|
|
51
52
|
const { buildings } = useBuildings();
|
|
@@ -82,49 +83,30 @@ function NonDatabaseBuildingPopover({
|
|
|
82
83
|
}, [setSelectedItem]);
|
|
83
84
|
React.useEffect(() => {
|
|
84
85
|
var _a;
|
|
85
|
-
const getAddress = async (
|
|
86
|
-
|
|
87
|
-
"api_key": process.env.NEXT_PUBLIC_GEOCODE_EARTH_API_KEY,
|
|
88
|
-
"point.lat": latitude,
|
|
89
|
-
"point.lon": longitude,
|
|
90
|
-
"boundary.country": "CA",
|
|
91
|
-
"layers": "address",
|
|
92
|
-
"size": "1"
|
|
93
|
-
// Limit to 1 result
|
|
94
|
-
});
|
|
95
|
-
const reverseGeocoderUrl = `https://api.geocode.earth/v1/reverse?${params}`;
|
|
86
|
+
const getAddress = async (longitude, latitude) => {
|
|
87
|
+
var _a2;
|
|
96
88
|
try {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (!response.ok) {
|
|
103
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
89
|
+
const result = await getDetailedAddress([longitude, latitude], organizationCountry);
|
|
90
|
+
const geocodedAddress = (_a2 = result == null ? void 0 : result.properties) == null ? void 0 : _a2.name;
|
|
91
|
+
if (!geocodedAddress) {
|
|
92
|
+
clearExistingBuildingMatches();
|
|
93
|
+
return;
|
|
104
94
|
}
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
setSelectedMatchingBuildingId(matches[0].id.toString());
|
|
121
|
-
setShowExistingBuildings(true);
|
|
122
|
-
if (setSelectedItem) {
|
|
123
|
-
setSelectedItem(matches[0]);
|
|
124
|
-
didSetSelectedItemRef.current = true;
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
clearExistingBuildingMatches();
|
|
95
|
+
setAddress(geocodedAddress);
|
|
96
|
+
if (buildings && buildings.length > 0) {
|
|
97
|
+
const normalizedGeocodedAddress = normalizeAddress(geocodedAddress);
|
|
98
|
+
const matches = buildings.filter((building) => {
|
|
99
|
+
if (!building.buildingAddress) return false;
|
|
100
|
+
const normalizedBuildingAddress = normalizeAddress(building.buildingAddress);
|
|
101
|
+
return normalizedBuildingAddress === normalizedGeocodedAddress || normalizedBuildingAddress.includes(normalizedGeocodedAddress) || normalizedGeocodedAddress.includes(normalizedBuildingAddress);
|
|
102
|
+
});
|
|
103
|
+
if (matches.length > 0) {
|
|
104
|
+
setMatchingBuildings(matches);
|
|
105
|
+
setSelectedMatchingBuildingId(matches[0].id.toString());
|
|
106
|
+
setShowExistingBuildings(true);
|
|
107
|
+
if (setSelectedItem) {
|
|
108
|
+
setSelectedItem(matches[0]);
|
|
109
|
+
didSetSelectedItemRef.current = true;
|
|
128
110
|
}
|
|
129
111
|
} else {
|
|
130
112
|
clearExistingBuildingMatches();
|
|
@@ -139,7 +121,7 @@ function NonDatabaseBuildingPopover({
|
|
|
139
121
|
if ((_a = feature.properties) == null ? void 0 : _a.coordinates) {
|
|
140
122
|
const longitude = feature.properties.coordinates[0];
|
|
141
123
|
const latitude = feature.properties.coordinates[1];
|
|
142
|
-
getAddress(
|
|
124
|
+
getAddress(longitude, latitude);
|
|
143
125
|
}
|
|
144
126
|
}, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches]);
|
|
145
127
|
React.useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"sourcesContent":["'use client'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../../../store'\r\nimport { toast } from 'sonner'\r\n\r\n// Shadcn Components\r\nimport { Button, Label } from '../../../../../ui/'\r\nimport { PopoverContent } from '../../../../../ui/Popover'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Types / Utilities\r\nimport type { MapGeoJSONFeature } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../store'\r\nimport { useMenusContext } from '../../../../../../store'\r\nimport type { Building } from '../../../../../../types/dbTypes'\r\nimport { MarkerManager } from '../../../utils/MarkerManager'\r\n\r\n// Hooks\r\nimport { useCreateBuilding, useBuildings, useBuilding } from '../../../../../../hooks/buildings/buildings'\r\nimport { LoadingSpinner } from '../../../../../ui/LoadingSpinner'\r\n\r\ninterface NonDatabaseBuildingPopoverProps {\r\n feature: MapGeoJSONFeature\r\n isOpen: boolean\r\n onCloseAction: () => void\r\n}\r\n\r\nexport default function NonDatabaseBuildingPopover({\r\n feature,\r\n onCloseAction,\r\n}: NonDatabaseBuildingPopoverProps) {\r\n // Translation\r\n const t = useTranslations('NonDatabaseBuildingPopover')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { currentLocation, map } = mapState.map\r\n\r\n const { setSelectedItem } = useMenusContext()\r\n\r\n // Use the create building hook\r\n const { createBuilding, isMutating, createError, createdData } = useCreateBuilding()\r\n \r\n // Get all buildings for searching\r\n const { buildings } = useBuildings()\r\n\r\n const featureProps = feature?.properties || {}\r\n const featureid = feature?.id\r\n const [name, setName] = React.useState('')\r\n const [address, setAddress] = React.useState('')\r\n const [type, setType] = React.useState('')\r\n const [matchingBuildings, setMatchingBuildings] = React.useState<Building[]>([])\r\n const [selectedMatchingBuildingId, setSelectedMatchingBuildingId] = React.useState<string>('')\r\n const [showExistingBuildings, setShowExistingBuildings] = React.useState(false)\r\n const [isAttaching, setIsAttaching] = React.useState(false)\r\n\r\n const { updateBuilding, isMutating: isUpdating } = useBuilding(selectedMatchingBuildingId ? Number(selectedMatchingBuildingId) : null)\r\n\r\n const normalizeAddress = React.useCallback((value: string) => {\r\n return value\r\n .toLowerCase()\r\n .replace(/\\./g, '')\r\n .replace(/,/g, ' ')\r\n .replace(/\\bdr\\b/g, 'drive')\r\n .replace(/\\brd\\b/g, 'road')\r\n .replace(/\\bst\\b/g, 'street')\r\n .replace(/\\bave\\b/g, 'avenue')\r\n .replace(/\\s+/g, ' ')\r\n .trim()\r\n }, [])\r\n\r\n const clearExistingBuildingMatches = React.useCallback(() => {\r\n setMatchingBuildings([])\r\n setSelectedMatchingBuildingId('')\r\n setShowExistingBuildings(false)\r\n\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Track if we set the selected item in this component\r\n const didSetSelectedItemRef = React.useRef(false)\r\n\r\n // Cleanup on unmount\r\n React.useEffect(() => {\r\n return () => {\r\n // Clear selected item if we set it\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Get address and search for matching buildings\r\n React.useEffect(() => {\r\n const getAddress = async (latitude: string, longitude: string) => {\r\n const params = new URLSearchParams({\r\n 'api_key': process.env.NEXT_PUBLIC_GEOCODE_EARTH_API_KEY,\r\n 'point.lat': latitude,\r\n 'point.lon': longitude,\r\n 'boundary.country': 'CA',\r\n 'layers': 'address',\r\n 'size': '1', // Limit to 1 result\r\n })\r\n \r\n const reverseGeocoderUrl = `https://api.geocode.earth/v1/reverse?${params}`\r\n \r\n try {\r\n const response = await fetch(reverseGeocoderUrl, {\r\n headers: {\r\n 'User-Agent': 'CDT/1.0 (cdt@email.com)',\r\n },\r\n })\r\n \r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`)\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (data.features && data.features.length > 0) {\r\n const feature = data.features[0]\r\n const properties = feature.properties\r\n \r\n const geocodedAddress = properties.name\r\n setAddress(geocodedAddress)\r\n \r\n // Search for existing buildings with this address\r\n if (geocodedAddress && buildings && buildings.length > 0) {\r\n const normalizedGeocodedAddress = normalizeAddress(geocodedAddress)\r\n\r\n const matches = buildings.filter((building) => {\r\n if (!building.buildingAddress) return false\r\n\r\n const normalizedBuildingAddress = normalizeAddress(building.buildingAddress)\r\n return (\r\n normalizedBuildingAddress === normalizedGeocodedAddress ||\r\n normalizedBuildingAddress.includes(normalizedGeocodedAddress) ||\r\n normalizedGeocodedAddress.includes(normalizedBuildingAddress)\r\n )\r\n })\r\n \r\n if (matches.length > 0) {\r\n setMatchingBuildings(matches)\r\n setSelectedMatchingBuildingId(matches[0].id.toString())\r\n setShowExistingBuildings(true)\r\n \r\n // Set the first match as the selected item for the update hook\r\n if (setSelectedItem) {\r\n setSelectedItem(matches[0])\r\n didSetSelectedItemRef.current = true\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and countrySubdivision:', error)\r\n }\r\n }\r\n \r\n if (feature.properties?.coordinates) {\r\n const longitude = feature.properties.coordinates[0]\r\n const latitude = feature.properties.coordinates[1]\r\n getAddress(latitude, longitude)\r\n }\r\n }, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches])\r\n\r\n React.useEffect(() => {\r\n if (!setSelectedItem || !selectedMatchingBuildingId) return\r\n\r\n const selectedBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n if (!selectedBuilding) return\r\n\r\n setSelectedItem(selectedBuilding)\r\n didSetSelectedItemRef.current = true\r\n }, [matchingBuildings, selectedMatchingBuildingId, setSelectedItem])\r\n\r\n // Fallbacks from feature or map state\r\n const buildingCountrySubdivision = featureProps.de_ao_prov || currentLocation.countrySubdivision || null\r\n const buildingMunicipality = featureProps.de_ao_city || currentLocation.municipality || null\r\n const buildingPostalCode = featureProps.de_ao_post || currentLocation.postalCode || null\r\n const site = currentLocation.site || null\r\n const buildingOsmId = featureid.toString()\r\n\r\n // Create MarkerManager instance\r\n const markerManagerRef = React.useRef<MarkerManager | null>(null)\r\n\r\n // Initialize MarkerManager\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) {\r\n markerManagerRef.current = new MarkerManager()\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.destroy()\r\n markerManagerRef.current = null\r\n }\r\n }\r\n }, [])\r\n\r\n // Get coordinates data from feature\r\n const [coordinates, setCoordinates] = React.useState(featureProps.coordinates || null)\r\n\r\n // Listen for marker coordinate changes\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) return\r\n\r\n const cleanup = markerManagerRef.current.onMoved((event) => {\r\n const newCoordinates = event.detail.coordinates\r\n if (newCoordinates) {\r\n setCoordinates(newCoordinates)\r\n }\r\n })\r\n\r\n return cleanup\r\n }, [])\r\n\r\n const handleBuildingNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setName(event.target.value)\r\n }\r\n\r\n const handleAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setAddress(event.target.value)\r\n }\r\n\r\n const handleBuildingTypeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\r\n setType(event.target.value)\r\n }\r\n\r\n const selectedMatchingBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n const handleAttachExistingBuilding = async (building: Building) => {\r\n setIsAttaching(true)\r\n \r\n try {\r\n // Add OSM ID to existing building\r\n const result = await updateBuilding({\r\n buildingOsmId,\r\n // Set default storey number of 2 if building doesn't have one\r\n ...(building.buildingStoreyNum == null && { buildingStoreyNum: 2 })\r\n })\r\n \r\n toast.success(t('toastAttachSuccess'))\r\n \r\n // Clear the selected item after successful update\r\n if (setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n \r\n // Close the popover\r\n onCloseAction()\r\n \r\n } catch (error) {\r\n console.error('Error attaching building:', error)\r\n \r\n if (error?.status !== 401) {\r\n toast.error(t('toastAttachError'))\r\n }\r\n } finally {\r\n setIsAttaching(false)\r\n }\r\n }\r\n\r\n const handleCreateNewBuilding = async (event: React.FormEvent) => {\r\n event.preventDefault()\r\n\r\n // Get final values (prioritize user input, then existing data)\r\n const buildingName = name.trim() || featureProps._name || ''\r\n const finalAddress = address.trim() || address || ''\r\n\r\n if (!user?.organizationId) {\r\n toast.error(t('userNotFound'))\r\n return\r\n }\r\n\r\n // Use updated coordinates from marker if available\r\n const buildingCoordinates = coordinates || [featureProps.longitude, featureProps.latitude]\r\n\r\n const newBuilding: Partial<Building> = {\r\n buildingName,\r\n buildingAddress: finalAddress,\r\n buildingType: [type || 'Other'],\r\n buildingOsmId,\r\n buildingLatitude: buildingCoordinates ? buildingCoordinates[1] : null,\r\n buildingLongitude: buildingCoordinates ? buildingCoordinates[0] : null,\r\n buildingCountrySubdivision,\r\n buildingMunicipality,\r\n buildingPostalCode,\r\n }\r\n\r\n try {\r\n const result = await createBuilding({\r\n buildingData: newBuilding,\r\n organizationId: user.organizationId.toString(),\r\n })\r\n\r\n // Remove marker after creating building\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.remove()\r\n }\r\n \r\n toast.success(t('toastSuccess'))\r\n \r\n // Close the popover on success\r\n onCloseAction()\r\n }\r\n catch (error) {\r\n console.error('Error creating building:', error)\r\n toast.error(t('toastError'))\r\n }\r\n }\r\n\r\n const handleLocationEdit = () => {\r\n // Create marker at current coordinates with editing enabled\r\n if (markerManagerRef.current && coordinates && map) {\r\n console.log('Creating editable marker at coordinates:', coordinates)\r\n markerManagerRef.current.create(coordinates as [number, number], map, {\r\n editing: true })\r\n }\r\n else {\r\n console.warn('Cannot create marker: missing coordinates or map instance')\r\n }\r\n }\r\n\r\n return (\r\n <PopoverContent className=\"w-64 -m-1\" side=\"top\">\r\n <form onSubmit={handleCreateNewBuilding}>\r\n <div className=\"grid gap-4\">\r\n <Button\r\n type=\"button\"\r\n onClick={onCloseAction}\r\n variant=\"ghost\"\r\n className=\"absolute top-1 right-2 p-1 text-muted-foreground hover:text-foreground\"\r\n aria-label={t('closeAriaLabel')}\r\n >\r\n <LR.X className=\"w-4 h-4\" />\r\n </Button>\r\n \r\n {/* Show existing building if match found */}\r\n {showExistingBuildings && matchingBuildings.length > 0 && (\r\n <div className=\"space-y-1 mt-6\">\r\n <div className=\"text-xs text-muted-foreground\">\r\n {t('existingBuildingFound')}\r\n </div>\r\n <div className=\"flex flex-col justify-between gap-2 p-2 bg-muted/50 border rounded-lg\">\r\n <div className=\"grid gap-1\">\r\n <Label htmlFor=\"existing-building-select\" className=\"text-xs text-muted-foreground\">\r\n {t('selectExistingBuildingLabel')}\r\n </Label>\r\n <Select\r\n value={selectedMatchingBuildingId}\r\n onValueChange={setSelectedMatchingBuildingId}\r\n >\r\n <SelectTrigger id=\"existing-building-select\" className=\"h-9 w-full\">\r\n <SelectValue placeholder={t('selectExistingBuildingPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {matchingBuildings.map((building) => (\r\n <SelectItem key={building.id} value={building.id.toString()}>\r\n {building.buildingName || building.buildingAddress || `${t('na')} (${building.id})`}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className='w-full'\r\n onClick={() => selectedMatchingBuilding && handleAttachExistingBuilding(selectedMatchingBuilding)}\r\n disabled={isAttaching || isUpdating || !selectedMatchingBuilding}\r\n >\r\n {(isAttaching || isUpdating) ? (\r\n <>\r\n <LoadingSpinner />\r\n <span>{t('attaching')}</span>\r\n </>\r\n ) : (\r\n <>\r\n <LR.Link />\r\n {t('attachBuilding')}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n \r\n <div className=\"space-y-4\">\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-name\" className=\"text-xs text-muted-foreground\">\r\n {t('nameLabel')}\r\n </Label>\r\n <input\r\n id=\"building-name\"\r\n value={name}\r\n onChange={handleBuildingNameChange}\r\n placeholder={name || t('namePlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${name ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('nameInputAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-address\" className=\"text-xs text-muted-foreground\">\r\n {t('addressLabel')}\r\n </Label>\r\n <input\r\n id=\"building-address\"\r\n value={address}\r\n onChange={handleAddressChange}\r\n placeholder={address || t('addressPlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${address ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('addressAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-type\" className=\"text-xs text-muted-foreground\">\r\n {t('typeLabel')}\r\n </Label>\r\n <select\r\n id=\"building-type\"\r\n value={type}\r\n onChange={handleBuildingTypeChange}\r\n className=\"font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1\"\r\n aria-label={t('typeAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <option value=\"\">{t('defaultOption')}</option>\r\n <option value=\"Townhouses\">{t('townhouse')}</option>\r\n <option value=\"<4 Storey MURB\">{t('4MURB')}</option>\r\n <option value=\"4+ Storey MURB\">{t('4PlusMURB')}</option>\r\n <option value=\"Stacked Townhouses\">{t('stackedTownhouses')}</option>\r\n <option value=\"Detached\">{t('detached')}</option>\r\n <option value=\"Semi Detached\">{t('semiDetached')}</option>\r\n <option value=\"Other\">{t('other')}</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 py-2 px-1\">\r\n <Label className=\"text-xs text-muted-foreground min-w-fit\">{t('osmId')}</Label>\r\n <span className=\"text-sm font-medium text-foreground\">{buildingOsmId ?? t('na')}</span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3 justify-center mt-4\">\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n aria-label=\"Edit Location\"\r\n title=\"Edit Location\"\r\n onClick={handleLocationEdit}\r\n disabled={!ability.can('update', 'Building')}\r\n >\r\n <LR.LocationEdit className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n <Button\r\n type=\"submit\"\r\n variant=\"outline\"\r\n aria-label={t('addBuilding')}\r\n title={t('addBuilding')}\r\n disabled={isMutating || !ability.can('create', 'Building')}\r\n >\r\n {isMutating\r\n ? (\r\n <>``\r\n <LoadingSpinner />\r\n <span className=\"text-sm\">{t('creating')}</span>\r\n </>\r\n )\r\n : (\r\n <>\r\n <LR.Building2 className=\"w-4 h-4\" />\r\n <span className=\"text-sm\">{t('addBuilding')}</span>\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </form>\r\n </PopoverContent>\r\n )\r\n}"],"mappings":"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","names":["feature"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"sourcesContent":["'use client'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../../../store'\r\nimport { toast } from 'sonner'\r\n\r\n// Shadcn Components\r\nimport { Button, Label } from '../../../../../ui/'\r\nimport { PopoverContent } from '../../../../../ui/Popover'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Types / Utilities\r\nimport type { MapGeoJSONFeature } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../store'\r\nimport { useMenusContext } from '../../../../../../store'\r\nimport type { Building } from '../../../../../../types/dbTypes'\r\nimport { MarkerManager } from '../../../utils/MarkerManager'\r\nimport { getDetailedAddress } from '../../../utils/geocoder'\r\n\r\n// Hooks\r\nimport { useCreateBuilding, useBuildings, useBuilding } from '../../../../../../hooks/buildings/buildings'\r\nimport { LoadingSpinner } from '../../../../../ui/LoadingSpinner'\r\n\r\ninterface NonDatabaseBuildingPopoverProps {\r\n feature: MapGeoJSONFeature\r\n isOpen: boolean\r\n onCloseAction: () => void\r\n}\r\n\r\nexport default function NonDatabaseBuildingPopover({\r\n feature,\r\n onCloseAction,\r\n}: NonDatabaseBuildingPopoverProps) {\r\n // Translation\r\n const t = useTranslations('NonDatabaseBuildingPopover')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { currentLocation, map, organizationCountry } = mapState.map\r\n\r\n const { setSelectedItem } = useMenusContext()\r\n\r\n // Use the create building hook\r\n const { createBuilding, isMutating, createError, createdData } = useCreateBuilding()\r\n\r\n // Get all buildings for searching\r\n const { buildings } = useBuildings()\r\n\r\n const featureProps = feature?.properties || {}\r\n const featureid = feature?.id\r\n const [name, setName] = React.useState('')\r\n const [address, setAddress] = React.useState('')\r\n const [type, setType] = React.useState('')\r\n const [matchingBuildings, setMatchingBuildings] = React.useState<Building[]>([])\r\n const [selectedMatchingBuildingId, setSelectedMatchingBuildingId] = React.useState<string>('')\r\n const [showExistingBuildings, setShowExistingBuildings] = React.useState(false)\r\n const [isAttaching, setIsAttaching] = React.useState(false)\r\n\r\n const { updateBuilding, isMutating: isUpdating } = useBuilding(selectedMatchingBuildingId ? Number(selectedMatchingBuildingId) : null)\r\n\r\n const normalizeAddress = React.useCallback((value: string) => {\r\n return value\r\n .toLowerCase()\r\n .replace(/\\./g, '')\r\n .replace(/,/g, ' ')\r\n .replace(/\\bdr\\b/g, 'drive')\r\n .replace(/\\brd\\b/g, 'road')\r\n .replace(/\\bst\\b/g, 'street')\r\n .replace(/\\bave\\b/g, 'avenue')\r\n .replace(/\\s+/g, ' ')\r\n .trim()\r\n }, [])\r\n\r\n const clearExistingBuildingMatches = React.useCallback(() => {\r\n setMatchingBuildings([])\r\n setSelectedMatchingBuildingId('')\r\n setShowExistingBuildings(false)\r\n\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Track if we set the selected item in this component\r\n const didSetSelectedItemRef = React.useRef(false)\r\n\r\n // Cleanup on unmount\r\n React.useEffect(() => {\r\n return () => {\r\n // Clear selected item if we set it\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Get address and search for matching buildings\r\n React.useEffect(() => {\r\n const getAddress = async (longitude: number, latitude: number) => {\r\n try {\r\n // Reverse geocode through the shared provider (Geocode Earth / self-hosted\r\n // Pelias, falling back to public OSM) so this stays in sync with the geocoder.\r\n const result = await getDetailedAddress([longitude, latitude], organizationCountry)\r\n const geocodedAddress = result?.properties?.name as string | undefined\r\n\r\n if (!geocodedAddress) {\r\n clearExistingBuildingMatches()\r\n return\r\n }\r\n\r\n setAddress(geocodedAddress)\r\n\r\n // Search for existing buildings with this address\r\n if (buildings && buildings.length > 0) {\r\n const normalizedGeocodedAddress = normalizeAddress(geocodedAddress)\r\n\r\n const matches = buildings.filter((building) => {\r\n if (!building.buildingAddress) return false\r\n\r\n const normalizedBuildingAddress = normalizeAddress(building.buildingAddress)\r\n return (\r\n normalizedBuildingAddress === normalizedGeocodedAddress ||\r\n normalizedBuildingAddress.includes(normalizedGeocodedAddress) ||\r\n normalizedGeocodedAddress.includes(normalizedBuildingAddress)\r\n )\r\n })\r\n\r\n if (matches.length > 0) {\r\n setMatchingBuildings(matches)\r\n setSelectedMatchingBuildingId(matches[0].id.toString())\r\n setShowExistingBuildings(true)\r\n\r\n // Set the first match as the selected item for the update hook\r\n if (setSelectedItem) {\r\n setSelectedItem(matches[0])\r\n didSetSelectedItemRef.current = true\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and countrySubdivision:', error)\r\n }\r\n }\r\n\r\n if (feature.properties?.coordinates) {\r\n const longitude = feature.properties.coordinates[0]\r\n const latitude = feature.properties.coordinates[1]\r\n getAddress(longitude, latitude)\r\n }\r\n }, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches])\r\n\r\n React.useEffect(() => {\r\n if (!setSelectedItem || !selectedMatchingBuildingId) return\r\n\r\n const selectedBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n if (!selectedBuilding) return\r\n\r\n setSelectedItem(selectedBuilding)\r\n didSetSelectedItemRef.current = true\r\n }, [matchingBuildings, selectedMatchingBuildingId, setSelectedItem])\r\n\r\n // Fallbacks from feature or map state\r\n const buildingCountrySubdivision = featureProps.de_ao_prov || currentLocation.countrySubdivision || null\r\n const buildingMunicipality = featureProps.de_ao_city || currentLocation.municipality || null\r\n const buildingPostalCode = featureProps.de_ao_post || currentLocation.postalCode || null\r\n const site = currentLocation.site || null\r\n const buildingOsmId = featureid.toString()\r\n\r\n // Create MarkerManager instance\r\n const markerManagerRef = React.useRef<MarkerManager | null>(null)\r\n\r\n // Initialize MarkerManager\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) {\r\n markerManagerRef.current = new MarkerManager()\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.destroy()\r\n markerManagerRef.current = null\r\n }\r\n }\r\n }, [])\r\n\r\n // Get coordinates data from feature\r\n const [coordinates, setCoordinates] = React.useState(featureProps.coordinates || null)\r\n\r\n // Listen for marker coordinate changes\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) return\r\n\r\n const cleanup = markerManagerRef.current.onMoved((event) => {\r\n const newCoordinates = event.detail.coordinates\r\n if (newCoordinates) {\r\n setCoordinates(newCoordinates)\r\n }\r\n })\r\n\r\n return cleanup\r\n }, [])\r\n\r\n const handleBuildingNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setName(event.target.value)\r\n }\r\n\r\n const handleAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setAddress(event.target.value)\r\n }\r\n\r\n const handleBuildingTypeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\r\n setType(event.target.value)\r\n }\r\n\r\n const selectedMatchingBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n const handleAttachExistingBuilding = async (building: Building) => {\r\n setIsAttaching(true)\r\n\r\n try {\r\n // Add OSM ID to existing building\r\n const result = await updateBuilding({\r\n buildingOsmId,\r\n // Set default storey number of 2 if building doesn't have one\r\n ...(building.buildingStoreyNum == null && { buildingStoreyNum: 2 })\r\n })\r\n\r\n toast.success(t('toastAttachSuccess'))\r\n\r\n // Clear the selected item after successful update\r\n if (setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n\r\n // Close the popover\r\n onCloseAction()\r\n\r\n } catch (error) {\r\n console.error('Error attaching building:', error)\r\n\r\n if (error?.status !== 401) {\r\n toast.error(t('toastAttachError'))\r\n }\r\n } finally {\r\n setIsAttaching(false)\r\n }\r\n }\r\n\r\n const handleCreateNewBuilding = async (event: React.FormEvent) => {\r\n event.preventDefault()\r\n\r\n // Get final values (prioritize user input, then existing data)\r\n const buildingName = name.trim() || featureProps._name || ''\r\n const finalAddress = address.trim() || address || ''\r\n\r\n if (!user?.organizationId) {\r\n toast.error(t('userNotFound'))\r\n return\r\n }\r\n\r\n // Use updated coordinates from marker if available\r\n const buildingCoordinates = coordinates || [featureProps.longitude, featureProps.latitude]\r\n\r\n const newBuilding: Partial<Building> = {\r\n buildingName,\r\n buildingAddress: finalAddress,\r\n buildingType: [type || 'Other'],\r\n buildingOsmId,\r\n buildingLatitude: buildingCoordinates ? buildingCoordinates[1] : null,\r\n buildingLongitude: buildingCoordinates ? buildingCoordinates[0] : null,\r\n buildingCountrySubdivision,\r\n buildingMunicipality,\r\n buildingPostalCode,\r\n }\r\n\r\n try {\r\n const result = await createBuilding({\r\n buildingData: newBuilding,\r\n organizationId: user.organizationId.toString(),\r\n })\r\n\r\n // Remove marker after creating building\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.remove()\r\n }\r\n\r\n toast.success(t('toastSuccess'))\r\n\r\n // Close the popover on success\r\n onCloseAction()\r\n }\r\n catch (error) {\r\n console.error('Error creating building:', error)\r\n toast.error(t('toastError'))\r\n }\r\n }\r\n\r\n const handleLocationEdit = () => {\r\n // Create marker at current coordinates with editing enabled\r\n if (markerManagerRef.current && coordinates && map) {\r\n console.log('Creating editable marker at coordinates:', coordinates)\r\n markerManagerRef.current.create(coordinates as [number, number], map, {\r\n editing: true\r\n })\r\n }\r\n else {\r\n console.warn('Cannot create marker: missing coordinates or map instance')\r\n }\r\n }\r\n\r\n return (\r\n <PopoverContent className=\"w-64 -m-1\" side=\"top\">\r\n <form onSubmit={handleCreateNewBuilding}>\r\n <div className=\"grid gap-4\">\r\n <Button\r\n type=\"button\"\r\n onClick={onCloseAction}\r\n variant=\"ghost\"\r\n className=\"absolute top-1 right-2 p-1 text-muted-foreground hover:text-foreground\"\r\n aria-label={t('closeAriaLabel')}\r\n >\r\n <LR.X className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n {/* Show existing building if match found */}\r\n {showExistingBuildings && matchingBuildings.length > 0 && (\r\n <div className=\"space-y-1 mt-6\">\r\n <div className=\"text-xs text-muted-foreground\">\r\n {t('existingBuildingFound')}\r\n </div>\r\n <div className=\"flex flex-col justify-between gap-2 p-2 bg-muted/50 border rounded-lg\">\r\n <div className=\"grid gap-1\">\r\n <Label htmlFor=\"existing-building-select\" className=\"text-xs text-muted-foreground\">\r\n {t('selectExistingBuildingLabel')}\r\n </Label>\r\n <Select\r\n value={selectedMatchingBuildingId}\r\n onValueChange={setSelectedMatchingBuildingId}\r\n >\r\n <SelectTrigger id=\"existing-building-select\" className=\"h-9 w-full\">\r\n <SelectValue placeholder={t('selectExistingBuildingPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {matchingBuildings.map((building) => (\r\n <SelectItem key={building.id} value={building.id.toString()}>\r\n {building.buildingName || building.buildingAddress || `${t('na')} (${building.id})`}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className='w-full'\r\n onClick={() => selectedMatchingBuilding && handleAttachExistingBuilding(selectedMatchingBuilding)}\r\n disabled={isAttaching || isUpdating || !selectedMatchingBuilding}\r\n >\r\n {(isAttaching || isUpdating) ? (\r\n <>\r\n <LoadingSpinner />\r\n <span>{t('attaching')}</span>\r\n </>\r\n ) : (\r\n <>\r\n <LR.Link />\r\n {t('attachBuilding')}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"space-y-4\">\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-name\" className=\"text-xs text-muted-foreground\">\r\n {t('nameLabel')}\r\n </Label>\r\n <input\r\n id=\"building-name\"\r\n value={name}\r\n onChange={handleBuildingNameChange}\r\n placeholder={name || t('namePlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${name ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('nameInputAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-address\" className=\"text-xs text-muted-foreground\">\r\n {t('addressLabel')}\r\n </Label>\r\n <input\r\n id=\"building-address\"\r\n value={address}\r\n onChange={handleAddressChange}\r\n placeholder={address || t('addressPlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${address ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('addressAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-type\" className=\"text-xs text-muted-foreground\">\r\n {t('typeLabel')}\r\n </Label>\r\n <select\r\n id=\"building-type\"\r\n value={type}\r\n onChange={handleBuildingTypeChange}\r\n className=\"font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1\"\r\n aria-label={t('typeAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <option value=\"\">{t('defaultOption')}</option>\r\n <option value=\"Townhouses\">{t('townhouse')}</option>\r\n <option value=\"<4 Storey MURB\">{t('4MURB')}</option>\r\n <option value=\"4+ Storey MURB\">{t('4PlusMURB')}</option>\r\n <option value=\"Stacked Townhouses\">{t('stackedTownhouses')}</option>\r\n <option value=\"Detached\">{t('detached')}</option>\r\n <option value=\"Semi Detached\">{t('semiDetached')}</option>\r\n <option value=\"Other\">{t('other')}</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 py-2 px-1\">\r\n <Label className=\"text-xs text-muted-foreground min-w-fit\">{t('osmId')}</Label>\r\n <span className=\"text-sm font-medium text-foreground\">{buildingOsmId ?? t('na')}</span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3 justify-center mt-4\">\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n aria-label=\"Edit Location\"\r\n title=\"Edit Location\"\r\n onClick={handleLocationEdit}\r\n disabled={!ability.can('update', 'Building')}\r\n >\r\n <LR.LocationEdit className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n <Button\r\n type=\"submit\"\r\n variant=\"outline\"\r\n aria-label={t('addBuilding')}\r\n title={t('addBuilding')}\r\n disabled={isMutating || !ability.can('create', 'Building')}\r\n >\r\n {isMutating\r\n ? (\r\n <>``\r\n <LoadingSpinner />\r\n <span className=\"text-sm\">{t('creating')}</span>\r\n </>\r\n )\r\n : (\r\n <>\r\n <LR.Building2 className=\"w-4 h-4\" />\r\n <span className=\"text-sm\">{t('addBuilding')}</span>\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </form>\r\n </PopoverContent>\r\n )\r\n}"],"mappings":"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","names":["_a"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAsB9B,eAAO,MAAM,SAAS,yBAYrB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport dynamic from 'next/dynamic'\r\n\r\nimport { CountryLayer } from './src/CountryLayer'\r\nimport { CommentLayer } from './src/CommentLayer'\r\nimport { SensorLayers } from './src/SensorsLayer'\r\nimport { FileLayers } from './src/FileLayer'\r\nimport { OpenDataLayers } from './src/OpenDataLayer/src'\r\nimport { BuildingLayer } from './src/BuildingLayers'\r\nimport { useBimContext } from '../../../../../store'\r\n\r\
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"sourcesContent":["\r\n\r\n\r\n\r\n'use client'\r\n\r\nimport * as React from 'react'\r\nimport dynamic from 'next/dynamic'\r\n\r\nimport { CountryLayer } from './src/CountryLayer'\r\nimport { CommentLayer } from './src/CommentLayer'\r\nimport { SensorLayers } from './src/SensorsLayer'\r\nimport { FileLayers } from './src/FileLayer'\r\nimport { OpenDataLayers } from './src/OpenDataLayer/src'\r\nimport { BuildingLayer } from './src/BuildingLayers'\r\nimport { useBimContext } from '../../../../../store'\r\n\r\nconst LazyBimLayer = dynamic(\r\n () => import('./src/BimLayer').then(m => ({ default: m.BimLayer })),\r\n { ssr: false },\r\n)\r\n\r\nfunction BimLayerGate() {\r\n const { state: bimState } = useBimContext()\r\n if (bimState.bim.bimModelsAddedToMap.length === 0) return null\r\n return <LazyBimLayer />\r\n}\r\n\r\nexport const MapLayers = () => {\r\n return (\r\n <>\r\n <CountryLayer />\r\n <OpenDataLayers />\r\n <BuildingLayer />\r\n <CommentLayer />\r\n <SensorLayers />\r\n <FileLayers />\r\n <BimLayerGate />\r\n </>\r\n )\r\n}\r\n"],"mappings":";AAyBS,SAKL,UALK,KAKL,YALK;AAlBT,OAAO,aAAa;AAEpB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAE9B,MAAM,eAAe;AAAA,EACnB,MAAM,OAAO,gBAAgB,EAAE,KAAK,QAAM,EAAE,SAAS,EAAE,SAAS,EAAE;AAAA,EAClE,EAAE,KAAK,MAAM;AACf;AAEA,SAAS,eAAe;AACtB,QAAM,EAAE,OAAO,SAAS,IAAI,cAAc;AAC1C,MAAI,SAAS,IAAI,oBAAoB,WAAW,EAAG,QAAO;AAC1D,SAAO,oBAAC,gBAAa;AACvB;AAEO,MAAM,YAAY,MAAM;AAC7B,SACE,iCACE;AAAA,wBAAC,gBAAa;AAAA,IACd,oBAAC,kBAAe;AAAA,IAChB,oBAAC,iBAAc;AAAA,IACf,oBAAC,gBAAa;AAAA,IACd,oBAAC,gBAAa;AAAA,IACd,oBAAC,cAAW;AAAA,IACZ,oBAAC,gBAAa;AAAA,KAChB;AAEJ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,eAAO,MAAM,QAAQ,yBAwdpB,CAAC"}
|
|
@@ -147,6 +147,16 @@ const BimLayer = () => {
|
|
|
147
147
|
let model = null;
|
|
148
148
|
let lastAppliedRotation = originalRotation;
|
|
149
149
|
let lastLodUpdate = 0;
|
|
150
|
+
let cachedTerrainElev = 0;
|
|
151
|
+
let lastMoveTime = performance.now();
|
|
152
|
+
const SETTLE_MS = 1e3;
|
|
153
|
+
const recomputeTerrainElev = () => {
|
|
154
|
+
const { lng, lat } = extractPositionAndRotation(bimFile, building);
|
|
155
|
+
if (lng !== null && lat !== null) {
|
|
156
|
+
const e = map.queryTerrainElevation([lng, lat]);
|
|
157
|
+
if (e !== null && e !== void 0) cachedTerrainElev = e;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
150
160
|
let onMapMove;
|
|
151
161
|
let onMapMoveEnd;
|
|
152
162
|
const renderCamera = new THREE.PerspectiveCamera();
|
|
@@ -168,6 +178,8 @@ const BimLayer = () => {
|
|
|
168
178
|
this.scene = scene;
|
|
169
179
|
loadModel(buildingModel, fragments, scene, map2, lodCamera).then((loaded) => {
|
|
170
180
|
model = loaded;
|
|
181
|
+
lastMoveTime = performance.now();
|
|
182
|
+
recomputeTerrainElev();
|
|
171
183
|
map2.triggerRepaint();
|
|
172
184
|
});
|
|
173
185
|
if (!rendererRef.current) {
|
|
@@ -180,9 +192,12 @@ const BimLayer = () => {
|
|
|
180
192
|
}
|
|
181
193
|
this.renderer = rendererRef.current;
|
|
182
194
|
onMapMove = () => {
|
|
195
|
+
lastMoveTime = performance.now();
|
|
183
196
|
};
|
|
184
197
|
onMapMoveEnd = () => {
|
|
198
|
+
lastMoveTime = performance.now();
|
|
185
199
|
if (model) fragments.core.update(true);
|
|
200
|
+
recomputeTerrainElev();
|
|
186
201
|
map2.triggerRepaint();
|
|
187
202
|
};
|
|
188
203
|
map2.on("move", onMapMove);
|
|
@@ -223,7 +238,7 @@ const BimLayer = () => {
|
|
|
223
238
|
if (te !== void 0) modelElevation = te;
|
|
224
239
|
}
|
|
225
240
|
const modelOrigin = [modelLongitude, modelLatitude];
|
|
226
|
-
const terrainElev = (_a = map.queryTerrainElevation([modelLongitude, modelLatitude])) != null ? _a :
|
|
241
|
+
const terrainElev = editingBimModelRef.current === bimFile.name ? (_a = map.queryTerrainElevation([modelLongitude, modelLatitude])) != null ? _a : cachedTerrainElev : cachedTerrainElev;
|
|
227
242
|
const modelAltitude = modelElevation + terrainElev;
|
|
228
243
|
const scaling = 1;
|
|
229
244
|
const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);
|
|
@@ -253,7 +268,9 @@ const BimLayer = () => {
|
|
|
253
268
|
lastLodUpdate = now;
|
|
254
269
|
fragments.core.update();
|
|
255
270
|
}
|
|
256
|
-
|
|
271
|
+
if (editingBimModelRef.current === bimFile.name || now - lastMoveTime < SETTLE_MS) {
|
|
272
|
+
map.triggerRepaint();
|
|
273
|
+
}
|
|
257
274
|
}
|
|
258
275
|
this.renderer.resetState();
|
|
259
276
|
this.renderer.render(this.scene, renderCamera);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\";\r\nimport { type CustomLayerInterface, type LngLatLike } from \"maplibre-gl\";\r\nimport * as OBC from \"@thatopen/components\";\r\nimport * as FRAGS from \"@thatopen/fragments\";\r\nimport * as THREE from \"three\";\r\nimport { BimContext, MapContext } from \"../../../../../../../store\";\r\nimport type { Building, DbFile } from \"../../../../../../../types/dbTypes\";\r\nimport { Map } from \"maplibre-gl\";\r\nimport { Marker } from \"react-map-gl/maplibre\";\r\nimport * as LR from \"lucide-react\";\r\nimport { EditPosition, extractPositionAndRotation } from \"../EditPosition\";\r\nimport { disposeThreeScene } from \"../disposeThreeScene\";\r\nimport type { FileAction } from \"../../../../../../../types/global\";\r\nimport { ViewerContextMenu } from '../../../../../../ui/FilesManager';\r\n\r\nexport const BimLayer = () => {\r\n\r\n const { state: mapState } = React.useContext(MapContext);\r\n const { map } = mapState.map;\r\n\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext);\r\n const { bimModelsAddedToMap, editingBimModel } = bimState.bim;\r\n\r\n const rendererRef = React.useRef<THREE.WebGLRenderer | null>(null);\r\n\r\n const addedLayersRef = React.useRef<Set<string>>(new Set());\r\n const prevModelsRef = React.useRef<Set<string>>(new Set());\r\n\r\n const sharedRef = React.useRef<{\r\n components: OBC.Components;\r\n fragments: OBC.FragmentsManager;\r\n } | null>(null);\r\n\r\n const [loadingBuildings, setLoadingBuildings] = React.useState<Set<number>>(new Set());\r\n const [contextMenu, setContextMenu] = React.useState<{\r\n x: number; y: number; bimFile: DbFile\r\n } | null>(null);\r\n\r\n const handleContextMenuAction = React.useCallback((action: FileAction, file: DbFile) => {\r\n if (action === 'view') {\r\n bimDispatch({ type: 'REMOVE_BIM_FROM_MAP', payload: { bimModelName: file.name } });\r\n } else if (action === 'move') {\r\n bimDispatch({ type: 'EDIT_BIM_MODEL_BY_NAME', payload: { editingBimModel: file.name } });\r\n }\r\n }, [bimDispatch]);\r\n\r\n const tempPositionsRef = React.useRef<Record<string, { lat: number; lng: number }>>({});\r\n const tempRotationsRef = React.useRef<Record<string, number>>({});\r\n const tempElevationsRef = React.useRef<Record<string, number>>({});\r\n\r\n const editingBimModelRef = React.useRef<string | null>(editingBimModel);\r\n React.useEffect(() => {\r\n editingBimModelRef.current = editingBimModel;\r\n }, [editingBimModel]);\r\n\r\n const handleExitEditMode = React.useCallback(() => {\r\n bimDispatch({ type: \"EDIT_BIM_MODEL_BY_NAME\", payload: { editingBimModel: null } });\r\n }, [bimDispatch]);\r\n\r\n const handleMapRepaint = React.useCallback(() => {\r\n if (map) map.triggerRepaint();\r\n }, [map]);\r\n const getOrCreateShared = React.useCallback(async () => {\r\n if (sharedRef.current) return sharedRef.current;\r\n\r\n const components = new OBC.Components();\r\n const worlds = components.get(OBC.Worlds);\r\n const world = worlds.create<OBC.SimpleScene, OBC.SimpleCamera, OBC.SimpleRenderer>();\r\n world.scene = new OBC.SimpleScene(components);\r\n world.renderer = new OBC.SimpleRenderer(components, document.createElement(\"div\"));\r\n world.camera = new OBC.SimpleCamera(components);\r\n components.init();\r\n world.scene.setup();\r\n\r\n const fragments = components.get(OBC.FragmentsManager);\r\n const fetchedUrl = await fetch(\"https://thatopen.github.io/engine_fragment/resources/worker.mjs\");\r\n const workerBlob = await fetchedUrl.blob();\r\n const workerUrl = URL.createObjectURL(\r\n new File([workerBlob], \"worker.mjs\", { type: \"text/javascript\" })\r\n );\r\n fragments.init(workerUrl);\r\n\r\n sharedRef.current = { components, fragments };\r\n return sharedRef.current;\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!map) return;\r\n\r\n const currentModelNames = new Set(bimModelsAddedToMap.map(bm => bm.bimFile.name));\r\n\r\n const modelsToRemove = Array.from(prevModelsRef.current).filter(\r\n name => !currentModelNames.has(name)\r\n );\r\n const modelsToAdd = bimModelsAddedToMap.filter(\r\n bm => !prevModelsRef.current.has(bm.bimFile.name)\r\n );\r\n\r\n modelsToRemove.forEach(layerName => {\r\n if (map.getLayer(layerName)) {\r\n map.removeLayer(layerName);\r\n addedLayersRef.current.delete(layerName);\r\n console.log(`Removed layer: ${layerName}`);\r\n }\r\n });\r\n\r\n prevModelsRef.current = currentModelNames;\r\n\r\n if (modelsToAdd.length === 0) return;\r\n\r\n // ─── Load a single BIM model ──────────────────────────────────────────\r\n const loadModel = async (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene,\r\n map: Map,\r\n lodCamera: THREE.PerspectiveCamera\r\n ): Promise<FRAGS.FragmentsModel | null> => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n if (!bimFile) return null;\r\n\r\n const buildingId = building?.id ?? bimFile.id;\r\n setLoadingBuildings(prev => new Set(prev).add(buildingId));\r\n\r\n try {\r\n const file = await fetch(bimFile.url);\r\n if (!file.ok) throw new Error(`Fetch failed: ${file.status} ${file.statusText}`);\r\n\r\n const buffer = await file.arrayBuffer();\r\n const model = await fragments.core.load(buffer, { modelId: bimFile.name });\r\n\r\n if (!model.box.isEmpty()) {\r\n const center = model.box.getCenter(new THREE.Vector3());\r\n const size = model.box.getSize(new THREE.Vector3());\r\n model.object.position.set(-center.x, 0, -center.z);\r\n\r\n // lodCamera: above the model's new IFC-space centre (XZ is now 0,0)\r\n lodCamera.position.set(0, center.y + Math.max(size.x, size.y, size.z) * 2, 0);\r\n lodCamera.lookAt(0, center.y, 0);\r\n } else {\r\n lodCamera.position.set(0, 100, 0);\r\n lodCamera.lookAt(0, 0, 0);\r\n }\r\n lodCamera.updateMatrixWorld();\r\n model.useCamera(lodCamera);\r\n\r\n model.graphicsQuality = 1;\r\n scene.add(model.object);\r\n fragments.core.update(true);\r\n map.triggerRepaint();\r\n\r\n return model;\r\n\r\n } catch (error) {\r\n console.error(\"Error loading BIM model:\", error);\r\n return null;\r\n } finally {\r\n setLoadingBuildings(prev => {\r\n const next = new Set(prev);\r\n next.delete(buildingId);\r\n return next;\r\n });\r\n }\r\n };\r\n\r\n // ─── Build a MapLibre custom layer for one model ──────────────────────\r\n const createCustomLayer = (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene\r\n ): CustomLayerInterface | undefined => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n const {\r\n lng: baseLng, lat: baseLat,\r\n rotation: originalRotation,\r\n } = extractPositionAndRotation(bimFile, building);\r\n if (baseLng === null || baseLat === null) return undefined;\r\n\r\n // Per-layer state kept in closure\r\n let model: FRAGS.FragmentsModel | null = null;\r\n let lastAppliedRotation = originalRotation;\r\n let lastLodUpdate = 0;\r\n\r\n let onMapMove: () => void;\r\n let onMapMoveEnd: () => void;\r\n const renderCamera = new THREE.PerspectiveCamera();\r\n const lodCamera = new THREE.PerspectiveCamera();\r\n // Reused per-frame matrices/vectors — render() must not allocate (audit B1).\r\n const _vp = new THREE.Matrix4();\r\n const _m = new THREE.Matrix4();\r\n const _p = new THREE.Matrix4();\r\n const _vm = new THREE.Matrix4();\r\n const _camPos = new THREE.Vector3();\r\n const _center = new THREE.Vector3();\r\n const _lookTarget = new THREE.Vector3();\r\n const _scaleVec = new THREE.Vector3(1, 1, 1);\r\n\r\n return {\r\n id: bimFile.name,\r\n type: \"custom\",\r\n renderingMode: \"3d\",\r\n\r\n onAdd(map, gl) {\r\n scene.rotateY(originalRotation * (Math.PI / 180));\r\n this.scene = scene;\r\n\r\n loadModel(buildingModel, fragments, scene, map, lodCamera).then(loaded => {\r\n model = loaded;\r\n map.triggerRepaint();\r\n });\r\n\r\n if (!rendererRef.current) {\r\n rendererRef.current = new THREE.WebGLRenderer({\r\n canvas: map.getCanvas(),\r\n context: gl,\r\n alpha: true,\r\n });\r\n rendererRef.current.autoClear = false;\r\n }\r\n this.renderer = rendererRef.current;\r\n onMapMove = () => { /* render() loop handles updates during movement */ };\r\n onMapMoveEnd = () => {\r\n if (model) fragments.core.update(true);\r\n map.triggerRepaint();\r\n };\r\n map.on(\"move\", onMapMove);\r\n map.on(\"moveend\", onMapMoveEnd);\r\n },\r\n\r\n render(_, args) {\r\n if (\r\n editingBimModelRef.current === bimFile.name &&\r\n tempRotationsRef.current[bimFile.name] !== undefined\r\n ) {\r\n const cur = tempRotationsRef.current[bimFile.name];\r\n if (cur !== lastAppliedRotation) {\r\n scene.rotateY((cur - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = cur;\r\n map.triggerRepaint();\r\n }\r\n } else {\r\n const { rotation: baseRot } = extractPositionAndRotation(bimFile, building);\r\n if (baseRot !== lastAppliedRotation) {\r\n scene.rotateY((baseRot - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = baseRot;\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n const {\r\n lng: baseLngNow, lat: baseLatNow,\r\n elevation: baseElevNow,\r\n } = extractPositionAndRotation(bimFile, building);\r\n\r\n let modelLongitude = baseLngNow;\r\n let modelLatitude = baseLatNow;\r\n let modelElevation = baseElevNow;\r\n\r\n if (editingBimModelRef.current === bimFile.name) {\r\n const tp = tempPositionsRef.current[bimFile.name];\r\n if (tp) { modelLongitude = tp.lng; modelLatitude = tp.lat; }\r\n const te = tempElevationsRef.current[bimFile.name];\r\n if (te !== undefined) modelElevation = te;\r\n }\r\n\r\n const modelOrigin = [modelLongitude, modelLatitude] as LngLatLike;\r\n const terrainElev = map.queryTerrainElevation([modelLongitude, modelLatitude]) ?? 0;\r\n const modelAltitude = modelElevation + terrainElev;\r\n const scaling = 1;\r\n\r\n // ── Build renderCamera (VP × M, for Three.js rendering) ───\r\n // Reused temps — render() allocates nothing (audit B1). Math is\r\n // identical to the prior allocate-every-frame version.\r\n const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);\r\n _scaleVec.set(scaling, scaling, scaling);\r\n _vp.fromArray(args.defaultProjectionData.mainMatrix);\r\n _m.fromArray(modelMatrix).scale(_scaleVec);\r\n renderCamera.projectionMatrix.multiplyMatrices(_vp, _m); // VP × M, into the camera's own matrix\r\n\r\n // camIFCPos = translation of (P⁻¹ · (VP×M))⁻¹\r\n _p.fromArray(args.projectionMatrix).invert(); // _p = P⁻¹\r\n _vm.multiplyMatrices(_p, renderCamera.projectionMatrix).invert();\r\n _camPos.setFromMatrixPosition(_vm);\r\n lodCamera.position.copy(_camPos);\r\n\r\n if (model) {\r\n model.box.getCenter(_center);\r\n _lookTarget.set(0, _center.y, 0);\r\n } else {\r\n _lookTarget.set(0, 0, 0);\r\n }\r\n lodCamera.lookAt(_lookTarget);\r\n lodCamera.fov = args.fov * (180 / Math.PI) + 40;\r\n lodCamera.aspect = map.getCanvas().width / map.getCanvas().height;\r\n lodCamera.updateProjectionMatrix(); // rebuilds projectionMatrix from fov/aspect\r\n lodCamera.updateMatrixWorld(); // rebuilds matrixWorld + matrixWorldInverse\r\n\r\n if (model) {\r\n model.useCamera(lodCamera);\r\n const now = performance.now();\r\n if (now - lastLodUpdate > 50) {\r\n lastLodUpdate = now;\r\n fragments.core.update();\r\n }\r\n map.triggerRepaint();\r\n }\r\n\r\n this.renderer.resetState();\r\n this.renderer.render(this.scene, renderCamera);\r\n },\r\n\r\n onRemove() {\r\n if (onMapMove) map.off(\"move\", onMapMove);\r\n if (onMapMoveEnd) map.off(\"moveend\", onMapMoveEnd);\r\n if (model) {\r\n model.dispose().catch(console.warn);\r\n model = null;\r\n }\r\n // Dispose all Three.js GPU resources (geometries, materials, textures)\r\n disposeThreeScene(scene);\r\n },\r\n };\r\n };\r\n\r\n modelsToAdd.forEach(async buildingModel => {\r\n try {\r\n const { fragments } = await getOrCreateShared();\r\n\r\n const layerName = buildingModel.bimFile.name;\r\n if (map.getLayer(layerName)) return;\r\n const scene = new THREE.Scene();\r\n scene.add(new THREE.AmbientLight(0xffffff, 0.8));\r\n const sun = new THREE.DirectionalLight(0xffffff, 1.0);\r\n sun.position.set(10, 20, 10);\r\n scene.add(sun);\r\n\r\n const customLayer = createCustomLayer(buildingModel, fragments, scene);\r\n if (!customLayer) return;\r\n\r\n map.addLayer(customLayer);\r\n addedLayersRef.current.add(layerName);\r\n console.log(`Added layer: ${layerName}`);\r\n\r\n } catch (err) {\r\n console.error(\"Error adding BIM layer:\", err);\r\n }\r\n });\r\n\r\n }, [map, bimModelsAddedToMap]);\r\n\r\n // Cleanup on unmount — dispose shared components and renderer\r\n React.useEffect(() => {\r\n return () => {\r\n if (map) {\r\n addedLayersRef.current.forEach(layerName => {\r\n if (map.getLayer(layerName)) map.removeLayer(layerName);\r\n });\r\n addedLayersRef.current.clear();\r\n }\r\n if (sharedRef.current) {\r\n sharedRef.current.components.dispose();\r\n sharedRef.current = null;\r\n }\r\n if (rendererRef.current) {\r\n rendererRef.current.dispose();\r\n rendererRef.current = null;\r\n }\r\n };\r\n }, [map]);\r\n\r\n return (\r\n <>\r\n {bimModelsAddedToMap.map((buildingModel, index) => {\r\n const { lng, lat } = extractPositionAndRotation(\r\n buildingModel.bimFile, buildingModel.building\r\n );\r\n const isLoading = loadingBuildings.has(\r\n buildingModel.building?.id ?? buildingModel.bimFile.id\r\n );\r\n if (lng === null || lat === null) return null;\r\n return (\r\n <React.Fragment key={buildingModel.bimFile.id + \"-fragment-\" + index}>\r\n {isLoading && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-loading-animation\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <LR.Loader className=\"animate-spin w-6 h-6 text-gray-700\" />\r\n </Marker>\r\n )}\r\n {/* Invisible hit-target for right-click context menu on WebGL-rendered BIM models */}\r\n {buildingModel.bimFile.name !== editingBimModel && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-ctx-target-\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <div\r\n className=\"w-10 h-10 opacity-0 cursor-context-menu\"\r\n onContextMenu={(e) => {\r\n e.preventDefault();\r\n setContextMenu({ x: e.clientX, y: e.clientY, bimFile: buildingModel.bimFile });\r\n }}\r\n />\r\n </Marker>\r\n )}\r\n </React.Fragment>\r\n );\r\n })}\r\n {editingBimModel && (() => {\r\n const currentModel = bimModelsAddedToMap.find(bm => bm.bimFile.name === editingBimModel);\r\n if (!currentModel) return null;\r\n const { lng, lat, rotation, elevation } = extractPositionAndRotation(\r\n currentModel.bimFile, currentModel.building\r\n );\r\n return (\r\n <EditPosition\r\n file={currentModel.bimFile}\r\n displayName={currentModel.building?.buildingName || currentModel.bimFile.name}\r\n mode=\"3d\"\r\n initialLat={lat}\r\n initialLng={lng}\r\n initialRotation={rotation}\r\n initialElevation={elevation}\r\n onExitEditMode={handleExitEditMode}\r\n tempPositionsRef={tempPositionsRef}\r\n tempRotationsRef={tempRotationsRef}\r\n tempElevationsRef={tempElevationsRef}\r\n onMapRepaint={handleMapRepaint}\r\n />\r\n );\r\n })()}\r\n\r\n {contextMenu && (\r\n <ViewerContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n file={{ ...contextMenu.bimFile, isVisible: true }}\r\n options={['view', 'move']}\r\n onAction={handleContextMenuAction}\r\n onClose={() => setContextMenu(null)}\r\n />\r\n )}\r\n </>\r\n );\r\n\r\n};\r\n"],"mappings":"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","names":["map"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\";\r\nimport { type CustomLayerInterface, type LngLatLike } from \"maplibre-gl\";\r\nimport * as OBC from \"@thatopen/components\";\r\nimport * as FRAGS from \"@thatopen/fragments\";\r\nimport * as THREE from \"three\";\r\nimport { BimContext, MapContext } from \"../../../../../../../store\";\r\nimport type { Building, DbFile } from \"../../../../../../../types/dbTypes\";\r\nimport { Map } from \"maplibre-gl\";\r\nimport { Marker } from \"react-map-gl/maplibre\";\r\nimport * as LR from \"lucide-react\";\r\nimport { EditPosition, extractPositionAndRotation } from \"../EditPosition\";\r\nimport { disposeThreeScene } from \"../disposeThreeScene\";\r\nimport type { FileAction } from \"../../../../../../../types/global\";\r\nimport { ViewerContextMenu } from '../../../../../../ui/FilesManager';\r\n\r\nexport const BimLayer = () => {\r\n\r\n const { state: mapState } = React.useContext(MapContext);\r\n const { map } = mapState.map;\r\n\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext);\r\n const { bimModelsAddedToMap, editingBimModel } = bimState.bim;\r\n\r\n const rendererRef = React.useRef<THREE.WebGLRenderer | null>(null);\r\n\r\n const addedLayersRef = React.useRef<Set<string>>(new Set());\r\n const prevModelsRef = React.useRef<Set<string>>(new Set());\r\n\r\n const sharedRef = React.useRef<{\r\n components: OBC.Components;\r\n fragments: OBC.FragmentsManager;\r\n } | null>(null);\r\n\r\n const [loadingBuildings, setLoadingBuildings] = React.useState<Set<number>>(new Set());\r\n const [contextMenu, setContextMenu] = React.useState<{\r\n x: number; y: number; bimFile: DbFile\r\n } | null>(null);\r\n\r\n const handleContextMenuAction = React.useCallback((action: FileAction, file: DbFile) => {\r\n if (action === 'view') {\r\n bimDispatch({ type: 'REMOVE_BIM_FROM_MAP', payload: { bimModelName: file.name } });\r\n } else if (action === 'move') {\r\n bimDispatch({ type: 'EDIT_BIM_MODEL_BY_NAME', payload: { editingBimModel: file.name } });\r\n }\r\n }, [bimDispatch]);\r\n\r\n const tempPositionsRef = React.useRef<Record<string, { lat: number; lng: number }>>({});\r\n const tempRotationsRef = React.useRef<Record<string, number>>({});\r\n const tempElevationsRef = React.useRef<Record<string, number>>({});\r\n\r\n const editingBimModelRef = React.useRef<string | null>(editingBimModel);\r\n React.useEffect(() => {\r\n editingBimModelRef.current = editingBimModel;\r\n }, [editingBimModel]);\r\n\r\n const handleExitEditMode = React.useCallback(() => {\r\n bimDispatch({ type: \"EDIT_BIM_MODEL_BY_NAME\", payload: { editingBimModel: null } });\r\n }, [bimDispatch]);\r\n\r\n const handleMapRepaint = React.useCallback(() => {\r\n if (map) map.triggerRepaint();\r\n }, [map]);\r\n const getOrCreateShared = React.useCallback(async () => {\r\n if (sharedRef.current) return sharedRef.current;\r\n\r\n const components = new OBC.Components();\r\n const worlds = components.get(OBC.Worlds);\r\n const world = worlds.create<OBC.SimpleScene, OBC.SimpleCamera, OBC.SimpleRenderer>();\r\n world.scene = new OBC.SimpleScene(components);\r\n world.renderer = new OBC.SimpleRenderer(components, document.createElement(\"div\"));\r\n world.camera = new OBC.SimpleCamera(components);\r\n components.init();\r\n world.scene.setup();\r\n\r\n const fragments = components.get(OBC.FragmentsManager);\r\n const fetchedUrl = await fetch(\"https://thatopen.github.io/engine_fragment/resources/worker.mjs\");\r\n const workerBlob = await fetchedUrl.blob();\r\n const workerUrl = URL.createObjectURL(\r\n new File([workerBlob], \"worker.mjs\", { type: \"text/javascript\" })\r\n );\r\n fragments.init(workerUrl);\r\n\r\n sharedRef.current = { components, fragments };\r\n return sharedRef.current;\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!map) return;\r\n\r\n const currentModelNames = new Set(bimModelsAddedToMap.map(bm => bm.bimFile.name));\r\n\r\n const modelsToRemove = Array.from(prevModelsRef.current).filter(\r\n name => !currentModelNames.has(name)\r\n );\r\n const modelsToAdd = bimModelsAddedToMap.filter(\r\n bm => !prevModelsRef.current.has(bm.bimFile.name)\r\n );\r\n\r\n modelsToRemove.forEach(layerName => {\r\n if (map.getLayer(layerName)) {\r\n map.removeLayer(layerName);\r\n addedLayersRef.current.delete(layerName);\r\n console.log(`Removed layer: ${layerName}`);\r\n }\r\n });\r\n\r\n prevModelsRef.current = currentModelNames;\r\n\r\n if (modelsToAdd.length === 0) return;\r\n\r\n // ─── Load a single BIM model ──────────────────────────────────────────\r\n const loadModel = async (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene,\r\n map: Map,\r\n lodCamera: THREE.PerspectiveCamera\r\n ): Promise<FRAGS.FragmentsModel | null> => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n if (!bimFile) return null;\r\n\r\n const buildingId = building?.id ?? bimFile.id;\r\n setLoadingBuildings(prev => new Set(prev).add(buildingId));\r\n\r\n try {\r\n const file = await fetch(bimFile.url);\r\n if (!file.ok) throw new Error(`Fetch failed: ${file.status} ${file.statusText}`);\r\n\r\n const buffer = await file.arrayBuffer();\r\n const model = await fragments.core.load(buffer, { modelId: bimFile.name });\r\n\r\n if (!model.box.isEmpty()) {\r\n const center = model.box.getCenter(new THREE.Vector3());\r\n const size = model.box.getSize(new THREE.Vector3());\r\n model.object.position.set(-center.x, 0, -center.z);\r\n\r\n // lodCamera: above the model's new IFC-space centre (XZ is now 0,0)\r\n lodCamera.position.set(0, center.y + Math.max(size.x, size.y, size.z) * 2, 0);\r\n lodCamera.lookAt(0, center.y, 0);\r\n } else {\r\n lodCamera.position.set(0, 100, 0);\r\n lodCamera.lookAt(0, 0, 0);\r\n }\r\n lodCamera.updateMatrixWorld();\r\n model.useCamera(lodCamera);\r\n\r\n model.graphicsQuality = 1;\r\n scene.add(model.object);\r\n fragments.core.update(true);\r\n map.triggerRepaint();\r\n\r\n return model;\r\n\r\n } catch (error) {\r\n console.error(\"Error loading BIM model:\", error);\r\n return null;\r\n } finally {\r\n setLoadingBuildings(prev => {\r\n const next = new Set(prev);\r\n next.delete(buildingId);\r\n return next;\r\n });\r\n }\r\n };\r\n\r\n // ─── Build a MapLibre custom layer for one model ──────────────────────\r\n const createCustomLayer = (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene\r\n ): CustomLayerInterface | undefined => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n const {\r\n lng: baseLng, lat: baseLat,\r\n rotation: originalRotation,\r\n } = extractPositionAndRotation(bimFile, building);\r\n if (baseLng === null || baseLat === null) return undefined;\r\n\r\n // Per-layer state kept in closure\r\n let model: FRAGS.FragmentsModel | null = null;\r\n let lastAppliedRotation = originalRotation;\r\n let lastLodUpdate = 0;\r\n // Render-on-demand: cache terrain elevation off the per-frame path and\r\n // only keep repainting while the camera recently moved, so an idle map\r\n // with a placed model stops re-rendering instead of pinning the main\r\n // thread (this was the freeze after a geocoder flyTo to high zoom).\r\n let cachedTerrainElev = 0;\r\n let lastMoveTime = performance.now();\r\n const SETTLE_MS = 1000;\r\n const recomputeTerrainElev = () => {\r\n const { lng, lat } = extractPositionAndRotation(bimFile, building);\r\n if (lng !== null && lat !== null) {\r\n const e = map.queryTerrainElevation([lng, lat]);\r\n if (e !== null && e !== undefined) cachedTerrainElev = e;\r\n }\r\n };\r\n\r\n let onMapMove: () => void;\r\n let onMapMoveEnd: () => void;\r\n const renderCamera = new THREE.PerspectiveCamera();\r\n const lodCamera = new THREE.PerspectiveCamera();\r\n // Reused per-frame matrices/vectors — render() must not allocate.\r\n const _vp = new THREE.Matrix4();\r\n const _m = new THREE.Matrix4();\r\n const _p = new THREE.Matrix4();\r\n const _vm = new THREE.Matrix4();\r\n const _camPos = new THREE.Vector3();\r\n const _center = new THREE.Vector3();\r\n const _lookTarget = new THREE.Vector3();\r\n const _scaleVec = new THREE.Vector3(1, 1, 1);\r\n\r\n return {\r\n id: bimFile.name,\r\n type: \"custom\",\r\n renderingMode: \"3d\",\r\n\r\n onAdd(map, gl) {\r\n scene.rotateY(originalRotation * (Math.PI / 180));\r\n this.scene = scene;\r\n\r\n loadModel(buildingModel, fragments, scene, map, lodCamera).then(loaded => {\r\n model = loaded;\r\n // Open the settle window so the just-loaded fragments stream\r\n // in and paint over the next frames, then idle.\r\n lastMoveTime = performance.now();\r\n recomputeTerrainElev();\r\n map.triggerRepaint();\r\n });\r\n\r\n if (!rendererRef.current) {\r\n rendererRef.current = new THREE.WebGLRenderer({\r\n canvas: map.getCanvas(),\r\n context: gl,\r\n alpha: true,\r\n });\r\n rendererRef.current.autoClear = false;\r\n }\r\n this.renderer = rendererRef.current;\r\n // Track movement so render() knows when it may stop repainting.\r\n onMapMove = () => { lastMoveTime = performance.now(); };\r\n onMapMoveEnd = () => {\r\n lastMoveTime = performance.now();\r\n if (model) fragments.core.update(true);\r\n // Terrain tiles for the new view are loaded once the camera\r\n // settles — refresh the cached elevation here, not per frame.\r\n recomputeTerrainElev();\r\n map.triggerRepaint();\r\n };\r\n map.on(\"move\", onMapMove);\r\n map.on(\"moveend\", onMapMoveEnd);\r\n },\r\n\r\n render(_, args) {\r\n if (\r\n editingBimModelRef.current === bimFile.name &&\r\n tempRotationsRef.current[bimFile.name] !== undefined\r\n ) {\r\n const cur = tempRotationsRef.current[bimFile.name];\r\n if (cur !== lastAppliedRotation) {\r\n scene.rotateY((cur - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = cur;\r\n map.triggerRepaint();\r\n }\r\n } else {\r\n const { rotation: baseRot } = extractPositionAndRotation(bimFile, building);\r\n if (baseRot !== lastAppliedRotation) {\r\n scene.rotateY((baseRot - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = baseRot;\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n const {\r\n lng: baseLngNow, lat: baseLatNow,\r\n elevation: baseElevNow,\r\n } = extractPositionAndRotation(bimFile, building);\r\n\r\n let modelLongitude = baseLngNow;\r\n let modelLatitude = baseLatNow;\r\n let modelElevation = baseElevNow;\r\n\r\n if (editingBimModelRef.current === bimFile.name) {\r\n const tp = tempPositionsRef.current[bimFile.name];\r\n if (tp) { modelLongitude = tp.lng; modelLatitude = tp.lat; }\r\n const te = tempElevationsRef.current[bimFile.name];\r\n if (te !== undefined) modelElevation = te;\r\n }\r\n\r\n const modelOrigin = [modelLongitude, modelLatitude] as LngLatLike;\r\n // Use the cached terrain elevation (refreshed on moveend); query\r\n // live only while actively editing this model's position. Keeps\r\n // the expensive queryTerrainElevation off the hot path — the\r\n // per-frame query was a main driver of the high-zoom freeze.\r\n const terrainElev = editingBimModelRef.current === bimFile.name\r\n ? (map.queryTerrainElevation([modelLongitude, modelLatitude]) ?? cachedTerrainElev)\r\n : cachedTerrainElev;\r\n const modelAltitude = modelElevation + terrainElev;\r\n const scaling = 1;\r\n\r\n // ── Build renderCamera (VP × M, for Three.js rendering) ───\r\n // Reused temps — render() allocates nothing. Math is identical\r\n // to the prior allocate-every-frame version.\r\n const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);\r\n _scaleVec.set(scaling, scaling, scaling);\r\n _vp.fromArray(args.defaultProjectionData.mainMatrix);\r\n _m.fromArray(modelMatrix).scale(_scaleVec);\r\n renderCamera.projectionMatrix.multiplyMatrices(_vp, _m); // VP × M, into the camera's own matrix\r\n\r\n // camIFCPos = translation of (P⁻¹ · (VP×M))⁻¹\r\n _p.fromArray(args.projectionMatrix).invert(); // _p = P⁻¹\r\n _vm.multiplyMatrices(_p, renderCamera.projectionMatrix).invert();\r\n _camPos.setFromMatrixPosition(_vm);\r\n lodCamera.position.copy(_camPos);\r\n\r\n if (model) {\r\n model.box.getCenter(_center);\r\n _lookTarget.set(0, _center.y, 0);\r\n } else {\r\n _lookTarget.set(0, 0, 0);\r\n }\r\n lodCamera.lookAt(_lookTarget);\r\n lodCamera.fov = args.fov * (180 / Math.PI) + 40;\r\n lodCamera.aspect = map.getCanvas().width / map.getCanvas().height;\r\n lodCamera.updateProjectionMatrix(); // rebuilds projectionMatrix from fov/aspect\r\n lodCamera.updateMatrixWorld(); // rebuilds matrixWorld + matrixWorldInverse\r\n\r\n if (model) {\r\n model.useCamera(lodCamera);\r\n const now = performance.now();\r\n if (now - lastLodUpdate > 50) {\r\n lastLodUpdate = now;\r\n fragments.core.update();\r\n }\r\n // Render-on-demand: only keep the frame loop alive while the\r\n // camera recently moved (settle window, for fragment\r\n // streaming) or this model is being edited. Idle map ⇒ no\r\n // self-scheduled repaints ⇒ main thread freed (no freeze).\r\n if (\r\n editingBimModelRef.current === bimFile.name ||\r\n now - lastMoveTime < SETTLE_MS\r\n ) {\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n this.renderer.resetState();\r\n this.renderer.render(this.scene, renderCamera);\r\n },\r\n\r\n onRemove() {\r\n if (onMapMove) map.off(\"move\", onMapMove);\r\n if (onMapMoveEnd) map.off(\"moveend\", onMapMoveEnd);\r\n if (model) {\r\n model.dispose().catch(console.warn);\r\n model = null;\r\n }\r\n // Dispose all Three.js GPU resources (geometries, materials, textures)\r\n disposeThreeScene(scene);\r\n },\r\n };\r\n };\r\n\r\n modelsToAdd.forEach(async buildingModel => {\r\n try {\r\n const { fragments } = await getOrCreateShared();\r\n\r\n const layerName = buildingModel.bimFile.name;\r\n if (map.getLayer(layerName)) return;\r\n const scene = new THREE.Scene();\r\n scene.add(new THREE.AmbientLight(0xffffff, 0.8));\r\n const sun = new THREE.DirectionalLight(0xffffff, 1.0);\r\n sun.position.set(10, 20, 10);\r\n scene.add(sun);\r\n\r\n const customLayer = createCustomLayer(buildingModel, fragments, scene);\r\n if (!customLayer) return;\r\n\r\n map.addLayer(customLayer);\r\n addedLayersRef.current.add(layerName);\r\n console.log(`Added layer: ${layerName}`);\r\n\r\n } catch (err) {\r\n console.error(\"Error adding BIM layer:\", err);\r\n }\r\n });\r\n\r\n }, [map, bimModelsAddedToMap]);\r\n\r\n // Cleanup on unmount — dispose shared components and renderer\r\n React.useEffect(() => {\r\n return () => {\r\n if (map) {\r\n addedLayersRef.current.forEach(layerName => {\r\n if (map.getLayer(layerName)) map.removeLayer(layerName);\r\n });\r\n addedLayersRef.current.clear();\r\n }\r\n if (sharedRef.current) {\r\n sharedRef.current.components.dispose();\r\n sharedRef.current = null;\r\n }\r\n if (rendererRef.current) {\r\n rendererRef.current.dispose();\r\n rendererRef.current = null;\r\n }\r\n };\r\n }, [map]);\r\n\r\n return (\r\n <>\r\n {bimModelsAddedToMap.map((buildingModel, index) => {\r\n const { lng, lat } = extractPositionAndRotation(\r\n buildingModel.bimFile, buildingModel.building\r\n );\r\n const isLoading = loadingBuildings.has(\r\n buildingModel.building?.id ?? buildingModel.bimFile.id\r\n );\r\n if (lng === null || lat === null) return null;\r\n return (\r\n <React.Fragment key={buildingModel.bimFile.id + \"-fragment-\" + index}>\r\n {isLoading && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-loading-animation\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <LR.Loader className=\"animate-spin w-6 h-6 text-gray-700\" />\r\n </Marker>\r\n )}\r\n {/* Invisible hit-target for right-click context menu on WebGL-rendered BIM models */}\r\n {buildingModel.bimFile.name !== editingBimModel && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-ctx-target-\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <div\r\n className=\"w-10 h-10 opacity-0 cursor-context-menu\"\r\n onContextMenu={(e) => {\r\n e.preventDefault();\r\n setContextMenu({ x: e.clientX, y: e.clientY, bimFile: buildingModel.bimFile });\r\n }}\r\n />\r\n </Marker>\r\n )}\r\n </React.Fragment>\r\n );\r\n })}\r\n {editingBimModel && (() => {\r\n const currentModel = bimModelsAddedToMap.find(bm => bm.bimFile.name === editingBimModel);\r\n if (!currentModel) return null;\r\n const { lng, lat, rotation, elevation } = extractPositionAndRotation(\r\n currentModel.bimFile, currentModel.building\r\n );\r\n return (\r\n <EditPosition\r\n file={currentModel.bimFile}\r\n displayName={currentModel.building?.buildingName || currentModel.bimFile.name}\r\n mode=\"3d\"\r\n initialLat={lat}\r\n initialLng={lng}\r\n initialRotation={rotation}\r\n initialElevation={elevation}\r\n onExitEditMode={handleExitEditMode}\r\n tempPositionsRef={tempPositionsRef}\r\n tempRotationsRef={tempRotationsRef}\r\n tempElevationsRef={tempElevationsRef}\r\n onMapRepaint={handleMapRepaint}\r\n />\r\n );\r\n })()}\r\n\r\n {contextMenu && (\r\n <ViewerContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n file={{ ...contextMenu.bimFile, isVisible: true }}\r\n options={['view', 'move']}\r\n onAction={handleContextMenuAction}\r\n onClose={() => setContextMenu(null)}\r\n />\r\n )}\r\n </>\r\n );\r\n\r\n};\r\n"],"mappings":"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","names":["map"]}
|