@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
|
@@ -20,16 +20,17 @@ const CANADA_DEFAULTS = {
|
|
|
20
20
|
long: -98.74
|
|
21
21
|
};
|
|
22
22
|
const DEFAULT_MAP_STYLE = { name: "Satellite", url: "mapStyles/satellite.json" };
|
|
23
|
+
const MAX_GLOBE_ZOOM = 5;
|
|
23
24
|
function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
24
|
-
var _a, _b;
|
|
25
|
+
var _a, _b, _c;
|
|
25
26
|
const searchParams = useSearchParams();
|
|
26
27
|
const [isMapLoaded, setIsMapLoaded] = React.useState(false);
|
|
27
28
|
const viewState = React.useMemo(() => {
|
|
28
|
-
var _a2, _b2,
|
|
29
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j;
|
|
29
30
|
return searchParams.size === 0 ? {
|
|
30
31
|
zoom: (_a2 = organization.zoom) != null ? _a2 : CANADA_DEFAULTS.zoom,
|
|
31
32
|
bearing: (_b2 = organization.bearing) != null ? _b2 : 0,
|
|
32
|
-
pitch: (
|
|
33
|
+
pitch: (_c2 = organization.pitch) != null ? _c2 : 0,
|
|
33
34
|
longitude: (_d = organization.long) != null ? _d : CANADA_DEFAULTS.long,
|
|
34
35
|
latitude: (_e = organization.lat) != null ? _e : CANADA_DEFAULTS.lat
|
|
35
36
|
} : {
|
|
@@ -40,6 +41,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
40
41
|
zoom: searchParams.has("zoom") ? Number.parseFloat(searchParams.get("zoom")) : (_j = organization.zoom) != null ? _j : CANADA_DEFAULTS.zoom
|
|
41
42
|
};
|
|
42
43
|
}, [searchParams, organization]);
|
|
44
|
+
const initialProjection = viewState.zoom > MAX_GLOBE_ZOOM ? "mercator" : "globe";
|
|
43
45
|
const mapContainerStyle = React.useMemo(
|
|
44
46
|
() => ({ width, height, backgroundColor: "black" }),
|
|
45
47
|
[width, height]
|
|
@@ -50,9 +52,30 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
50
52
|
);
|
|
51
53
|
const mapRef = React.useRef(null);
|
|
52
54
|
const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext);
|
|
55
|
+
const activeMap = (_a = mapState == null ? void 0 : mapState.map) == null ? void 0 : _a.map;
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
if (!activeMap) return;
|
|
58
|
+
const enforceProjectionForZoom = () => {
|
|
59
|
+
var _a2;
|
|
60
|
+
if (activeMap.getZoom() <= MAX_GLOBE_ZOOM) return;
|
|
61
|
+
const projection = activeMap.getProjection();
|
|
62
|
+
const currentType = typeof projection === "string" ? projection : (_a2 = projection == null ? void 0 : projection.type) != null ? _a2 : projection == null ? void 0 : projection.name;
|
|
63
|
+
if (currentType !== "mercator") {
|
|
64
|
+
activeMap.setProjection({ type: "mercator" });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
enforceProjectionForZoom();
|
|
68
|
+
activeMap.on("zoom", enforceProjectionForZoom);
|
|
69
|
+
return () => {
|
|
70
|
+
activeMap.off("zoom", enforceProjectionForZoom);
|
|
71
|
+
};
|
|
72
|
+
}, [activeMap]);
|
|
53
73
|
const handleMapLoad = () => {
|
|
54
|
-
var _a2, _b2,
|
|
74
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h;
|
|
55
75
|
const map = mapRef.current.getMap();
|
|
76
|
+
if (map.getZoom() > MAX_GLOBE_ZOOM) {
|
|
77
|
+
map.setProjection({ type: "mercator" });
|
|
78
|
+
}
|
|
56
79
|
if (mapRef.current) {
|
|
57
80
|
mapDispatch({
|
|
58
81
|
type: "SET_MAP",
|
|
@@ -73,7 +96,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
73
96
|
// Then override with URL params (this ensures URL params take precedence)
|
|
74
97
|
lat: searchParams.has("lat") ? Number.parseFloat(searchParams.get("lat")) : (_a2 = organization.lat) != null ? _a2 : CANADA_DEFAULTS.lat,
|
|
75
98
|
lng: searchParams.has("lng") ? Number.parseFloat(searchParams.get("lng")) : (_b2 = organization.long) != null ? _b2 : CANADA_DEFAULTS.long,
|
|
76
|
-
bearing: searchParams.has("bearing") ? Number.parseFloat(searchParams.get("bearing")) : (
|
|
99
|
+
bearing: searchParams.has("bearing") ? Number.parseFloat(searchParams.get("bearing")) : (_c2 = organization.bearing) != null ? _c2 : 0,
|
|
77
100
|
pitch: searchParams.has("pitch") ? Number.parseFloat(searchParams.get("pitch")) : (_d = organization.pitch) != null ? _d : 0,
|
|
78
101
|
zoom: searchParams.has("zoom") ? Number.parseFloat(searchParams.get("zoom")) : (_e = organization.zoom) != null ? _e : CANADA_DEFAULTS.zoom,
|
|
79
102
|
// Add location details from URL params if available
|
|
@@ -99,7 +122,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
99
122
|
const coordinates = { lng, lat, elevation, zoom: (_b2 = mapRef.current) == null ? void 0 : _b2.getZoom() };
|
|
100
123
|
console.log("\u{1F4CD} Map coordinates:", coordinates);
|
|
101
124
|
}, []);
|
|
102
|
-
const mapStyle = (
|
|
125
|
+
const mapStyle = (_b = mapState == null ? void 0 : mapState.map.mapStyle) != null ? _b : DEFAULT_MAP_STYLE;
|
|
103
126
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
104
127
|
/* @__PURE__ */ jsxs(
|
|
105
128
|
Map,
|
|
@@ -112,9 +135,9 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
112
135
|
style: mapContainerStyle,
|
|
113
136
|
initialViewState: viewState,
|
|
114
137
|
maxPitch: 60,
|
|
115
|
-
minZoom: (
|
|
138
|
+
minZoom: (_c = organization == null ? void 0 : organization.minZoom) != null ? _c : CANADA_DEFAULTS.zoom,
|
|
116
139
|
maxBounds: resolveBounds(organization == null ? void 0 : organization.maxBounds, CANADA_DEFAULTS.maxBounds),
|
|
117
|
-
projection:
|
|
140
|
+
projection: initialProjection,
|
|
118
141
|
doubleClickZoom: false,
|
|
119
142
|
onDblClick,
|
|
120
143
|
pixelRatio,
|
|
@@ -124,6 +147,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
124
147
|
isMapLoaded && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
125
148
|
/* @__PURE__ */ jsx(MapLayers, {}),
|
|
126
149
|
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none", children: [
|
|
150
|
+
/* @__PURE__ */ jsx("div", { id: "wms-time-slot", style: { display: "contents" } }),
|
|
127
151
|
/* @__PURE__ */ jsx(MapLegendHost, {}),
|
|
128
152
|
/* @__PURE__ */ jsx(DatasetManagerMenu, {})
|
|
129
153
|
] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\n// Audit Phase 1.D (F-4): hoist out of the component body so the object\r\n// identity is stable across renders. Was being recreated per render.\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n // Audit Phase 1.D (F-4): memoize viewState so the Map sees a stable\r\n // initialViewState prop across re-renders. Was recreated every render.\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n // Audit Phase 1.D (F-4): memoize the inline style object that gets passed to <Map>.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Audit Phase 1.D (F-8): adaptive pixel ratio. Was hardcoded `2` which on a\r\n // 1× DPR desktop monitor doubles the fragment-shader cost for zero visual\r\n // gain. On phones with DPR 3-4 the cap of 2 stays effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Audit Phase 0: enable the perf HUD by appending ?debug=1 to the URL.\r\n // Never reaches production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // Audit Phase 1.D (F-10): useCallback so the onDblClick prop identity is\r\n // stable across renders of MapViewer (was a new function each render,\r\n // causing react-map-gl to detach/re-attach the listener). Also gated the\r\n // console.log behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={ mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection=\"globe\"\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton /> \r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\nconst MAX_GLOBE_ZOOM = 5\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n const initialProjection = viewState.zoom > MAX_GLOBE_ZOOM ? 'mercator' : 'globe'\r\n\r\n // Memoize the inline style object that gets passed to <Map> for a stable prop identity.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Adaptive pixel ratio. A hardcoded 2 doubled fragment-shader cost on 1× DPR\r\n // desktops for zero visual gain; capping at 2 keeps phones (DPR 3-4) effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n // Keep the projection in sync with zoom at all times — not only while the\r\n // map-settings sidebar is mounted. The globe projection degrades past\r\n // MAX_GLOBE_ZOOM, so we force mercator regardless of which panels are open.\r\n const activeMap = mapState?.map?.map\r\n\r\n React.useEffect(() => {\r\n if (!activeMap) return\r\n\r\n const enforceProjectionForZoom = () => {\r\n if (activeMap.getZoom() <= MAX_GLOBE_ZOOM) return\r\n\r\n const projection = activeMap.getProjection()\r\n const currentType =\r\n typeof projection === 'string'\r\n ? projection\r\n : (projection as { type?: string; name?: string })?.type ?? (projection as { type?: string; name?: string })?.name\r\n\r\n if (currentType !== 'mercator') {\r\n activeMap.setProjection({ type: 'mercator' })\r\n }\r\n }\r\n\r\n enforceProjectionForZoom()\r\n activeMap.on('zoom', enforceProjectionForZoom)\r\n\r\n return () => {\r\n activeMap.off('zoom', enforceProjectionForZoom)\r\n }\r\n }, [activeMap])\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n if (map.getZoom() > MAX_GLOBE_ZOOM) {\r\n map.setProjection({ type: 'mercator' })\r\n }\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Enable the perf HUD by appending ?debug=1 to the URL. Never reaches\r\n // production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // useCallback so the onDblClick prop identity is stable across renders of\r\n // MapViewer; a new function each render caused react-map-gl to detach/re-attach\r\n // the listener. The console.log is gated behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection={initialProjection}\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton />\r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n {/* Portal slot for on-map WMS time controls; display:contents so an\r\n empty slot adds no flex item / gap, but a mounted control stacks\r\n above the legend + dataset-manager cards. */}\r\n <div id=\"wms-time-slot\" style={{ display: 'contents' }} />\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","_c"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAmI9B,MAAM,CAAC,OAAO,UAAU,kBAAkB,sBA+LzC"}
|
|
@@ -71,6 +71,7 @@ const SortableTableRow = ({
|
|
|
71
71
|
transition,
|
|
72
72
|
opacity: isDragging ? 0.5 : 1
|
|
73
73
|
};
|
|
74
|
+
const isRaster = dataset.datasetType === "WMS" || dataset.type === "WMS";
|
|
74
75
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
75
76
|
/* @__PURE__ */ jsxs(TableRow, { ref: setNodeRef, style, className: "hover:bg-muted/50", children: [
|
|
76
77
|
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -90,7 +91,7 @@ const SortableTableRow = ({
|
|
|
90
91
|
checked: dataset.visible !== false,
|
|
91
92
|
onCheckedChange: () => onToggleDataset(dataset),
|
|
92
93
|
className: "shrink-0",
|
|
93
|
-
style: dataset.visible === false ? {} : { backgroundColor: dataset.layerColor.color }
|
|
94
|
+
style: dataset.visible === false || isRaster ? {} : { backgroundColor: dataset.layerColor.color }
|
|
94
95
|
}
|
|
95
96
|
)
|
|
96
97
|
] }) }),
|
|
@@ -98,7 +99,7 @@ const SortableTableRow = ({
|
|
|
98
99
|
dataset.name.replaceAll("_", " "),
|
|
99
100
|
dataset.total && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "ml-2 text-xs", children: dataset.total })
|
|
100
101
|
] }),
|
|
101
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
|
|
102
|
+
/* @__PURE__ */ jsx(TableCell, { children: !isRaster && /* @__PURE__ */ jsx(
|
|
102
103
|
Button,
|
|
103
104
|
{
|
|
104
105
|
variant: "ghost",
|
|
@@ -114,7 +115,7 @@ const SortableTableRow = ({
|
|
|
114
115
|
}
|
|
115
116
|
) })
|
|
116
117
|
] }),
|
|
117
|
-
expandedDatasets.has(dataset.name) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "p-0 pb-1", children: /* @__PURE__ */ jsx(
|
|
118
|
+
!isRaster && expandedDatasets.has(dataset.name) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "p-0 pb-1", children: /* @__PURE__ */ jsx(
|
|
118
119
|
FieldsTable,
|
|
119
120
|
{
|
|
120
121
|
dataset
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { MapContext, DatasetsContext } from '../../../../../store'\r\nimport { Command, Menubar, Badge, Button, Switch } from '../../../../../components/ui/'\r\nimport {\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableRow,\r\n} from '../../../../../components/ui/Table'\r\nimport { FieldsTable } from './src/FieldsTable'\r\nimport * as LR from 'lucide-react'\r\nimport type { Dataset, BuildingDataset as RawBuildingDataset } from '../../../../../types/datasetTypes'\r\nimport { ClusterManager } from '../../utils/ClusterManager'\r\nimport {\r\n DndContext,\r\n closestCenter,\r\n KeyboardSensor,\r\n PointerSensor,\r\n useSensor,\r\n useSensors,\r\n DragEndEvent,\r\n} from '@dnd-kit/core'\r\nimport {\r\n arrayMove,\r\n SortableContext,\r\n sortableKeyboardCoordinates,\r\n verticalListSortingStrategy,\r\n} from '@dnd-kit/sortable'\r\nimport {\r\n useSortable,\r\n} from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { useSidebar } from '../../../../ui/Sidebar'\r\n\r\ntype BuildingDataset = RawBuildingDataset & Dataset\r\n\r\n// Type guard to check if dataset is a building dataset\r\nconst isBuildingDataset = (dataset: Dataset): dataset is BuildingDataset =>\r\n dataset.type === 'buildings' && 'data' in dataset\r\n\r\ninterface SortableTableRowProps {\r\n dataset: Dataset\r\n onToggleDataset: (dataset: Dataset) => void\r\n openDatasetDetails: (datasetName: string) => void\r\n expandedDatasets: Set<string>\r\n}\r\n\r\nconst SortableTableRow: React.FC<SortableTableRowProps> = ({\r\n dataset,\r\n onToggleDataset,\r\n openDatasetDetails,\r\n expandedDatasets,\r\n}) => {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n } = useSortable({ id: dataset.name })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.5 : 1,\r\n }\r\n\r\n return (\r\n <>\r\n <TableRow ref={setNodeRef} style={style} className=\"hover:bg-muted/50\">\r\n <TableCell>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"cursor-grab active:cursor-grabbing\"\r\n {...attributes}\r\n {...listeners}\r\n >\r\n <LR.GripVertical className=\"h-4 w-4\" />\r\n </Button>\r\n <Switch\r\n checked={dataset.visible !== false}\r\n onCheckedChange={() => onToggleDataset(dataset)}\r\n className=\"shrink-0\"\r\n style={dataset.visible === false ? {} : { backgroundColor: dataset.layerColor.color }}\r\n />\r\n </div>\r\n </TableCell>\r\n <TableCell className=\"font-medium\">\r\n {dataset.name.replaceAll('_', ' ')}\r\n {dataset.total && (\r\n <Badge variant=\"outline\" className=\"ml-2 text-xs\">\r\n {dataset.total}\r\n </Badge>\r\n )}\r\n </TableCell>\r\n <TableCell>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => openDatasetDetails(dataset.name)}\r\n className=\"shrink-0\"\r\n >\r\n <LR.ChevronDown\r\n className={`h-4 w-4 transition-transform duration-200 ${expandedDatasets.has(dataset.name) ? 'rotate-180' : ''}`}\r\n />\r\n </Button>\r\n </TableCell>\r\n </TableRow>\r\n {expandedDatasets.has(dataset.name) && (\r\n <TableRow>\r\n <TableCell colSpan={4} className=\"p-0 pb-1\">\r\n <FieldsTable\r\n dataset={dataset}\r\n />\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport default function DatasetManagerMenu() {\r\n // Translation\r\n const t = useTranslations('DatasetManagerMenu')\r\n\r\n const { state: mapState, dispatch: mapDispatch } = React.useContext(MapContext)\r\n const { map } = mapState.map\r\n\r\n const { state: datasetState, dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { addedDatasets } = datasetState.datasets\r\n\r\n const [open, setOpen] = React.useState(false)\r\n const [menuOpen, setMenuOpen] = React.useState(false)\r\n const [expandedDatasets, setExpandedDatasets] = React.useState<Set<string>>(new Set())\r\n\r\n const sensors = useSensors(\r\n useSensor(PointerSensor),\r\n useSensor(KeyboardSensor, {\r\n coordinateGetter: sortableKeyboardCoordinates,\r\n })\r\n )\r\n\r\n const sortedDatasets = React.useMemo(() => {\r\n const datasetsWithOrder = addedDatasets.map((dataset, index) => ({\r\n ...dataset,\r\n order: dataset.order !== undefined ? dataset.order : addedDatasets.length - 1 - index,\r\n }))\r\n\r\n return datasetsWithOrder.sort((a, b) => (b.order ?? 0) - (a.order ?? 0))\r\n }, [addedDatasets])\r\n\r\n React.useEffect(() => {\r\n if (!map || !addedDatasets) return\r\n\r\n const clusterManager = new ClusterManager(map)\r\n\r\n const sortedDatasets = [...addedDatasets].sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\r\n\r\n for (const dataset of sortedDatasets) {\r\n if (isBuildingDataset(dataset)) {\r\n if (dataset.visible === false) {\r\n clusterManager.remove(dataset.name)\r\n }\r\n else {\r\n clusterManager.create(dataset)\r\n clusterManager.toggleVisibility(dataset.name, true)\r\n }\r\n }\r\n }\r\n }, [map, addedDatasets])\r\n\r\n // Remove clusters for datasets no longer present\r\n const previousNamesRef = React.useRef<Set<string>>(new Set())\r\n\r\n React.useEffect(() => {\r\n if (!map) return\r\n const clusterManager = new ClusterManager(map)\r\n const currentNames = new Set(\r\n addedDatasets.filter(isBuildingDataset).map(ds => ds.name),\r\n )\r\n const removedNames = [...previousNamesRef.current].filter(\r\n name => !currentNames.has(name),\r\n )\r\n for (const datasetName of removedNames) {\r\n clusterManager.remove(datasetName)\r\n }\r\n previousNamesRef.current = currentNames\r\n }, [map, addedDatasets])\r\n\r\n const onToggle = () => setOpen(!open)\r\n\r\n const onToggleDataset = (dataset: Dataset) => {\r\n const datasetId = dataset.id;\r\n datasetDispatch({ type: 'TOGGLE_DATASET_VISIBILITY', payload: { datasetId } })\r\n }\r\n\r\n const toggleDatasetExpansion = (datasetName: string) => {\r\n setExpandedDatasets((prev) => {\r\n const newSet = new Set(prev)\r\n newSet.has(datasetName) ? newSet.delete(datasetName) : newSet.add(datasetName)\r\n return newSet\r\n })\r\n }\r\n\r\n const handleDragEnd = (event: DragEndEvent) => {\r\n const { active, over } = event\r\n\r\n if (over && active.id !== over.id) {\r\n const displayOrder = [...sortedDatasets]\r\n\r\n const oldIndex = displayOrder.findIndex(dataset => dataset.name === active.id)\r\n const newIndex = displayOrder.findIndex(dataset => dataset.name === over.id)\r\n\r\n const reorderedDisplay = arrayMove(displayOrder, oldIndex, newIndex)\r\n const maxOrder = reorderedDisplay.length - 1\r\n const reorderedDatasets = reorderedDisplay.map((dataset, index) => ({\r\n ...dataset,\r\n order: maxOrder - index,\r\n }))\r\n\r\n datasetDispatch({\r\n type: 'REORDER_DATASETS',\r\n payload: { reorderedDatasets }\r\n })\r\n }\r\n }\r\n\r\n const openAnimation = `\r\n pointer-events-auto \r\n transform \r\n transition-all \r\n duration-200\r\n data-[state=open]:animate-in \r\n data-[state=closed]:animate-out \r\n data-[state=closed]:fade-out-0 \r\n data-[state=open]:fade-in-0 \r\n data-[state=closed]:zoom-out-95 \r\n data-[state=open]:zoom-in-95\r\n `\r\n\r\n React.useEffect(() => {\r\n setMenuOpen(addedDatasets.length > 0)\r\n }, [addedDatasets.length])\r\n\r\n const openDatasetDetails = (datasetName: string) => {\r\n toggleDatasetExpansion(datasetName)\r\n }\r\n\r\n const {openInfo} = useSidebar()\r\n\r\n return (\r\n <>\r\n {!openInfo && addedDatasets.length > 0 && (\r\n <div data-state={menuOpen ? 'open' : 'closed'} className={openAnimation}>\r\n <Menubar className=\"pointer-events-auto w-96 h-auto\">\r\n <Command>\r\n <div>\r\n <div className={`flex items-center justify-between gap-3 ${open ? 'p-3' : 'pl-1 py-0'}`}>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge>{addedDatasets.length}</Badge>\r\n <div className=\"text-sm font-medium\">\r\n {t('appliedLayer')}\r\n {addedDatasets.length === 1 ? '' : 's'}\r\n </div>\r\n </div>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={onToggle}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <LR.ChevronUp\r\n size={14}\r\n className={`transition-transform duration-200 ${open ? 'rotate-180' : ''}`}\r\n />\r\n </Button>\r\n </div>\r\n {open && (\r\n <div className=\"max-h-[40vh] overflow-y-auto\">\r\n <DndContext\r\n sensors={sensors}\r\n collisionDetection={closestCenter}\r\n onDragEnd={handleDragEnd}\r\n >\r\n <SortableContext\r\n items={sortedDatasets.map(dataset => dataset.name)}\r\n strategy={verticalListSortingStrategy}\r\n >\r\n <Table>\r\n <TableBody>\r\n {sortedDatasets.map((dataset) => (\r\n <SortableTableRow\r\n key={dataset.name}\r\n dataset={dataset}\r\n onToggleDataset={onToggleDataset}\r\n openDatasetDetails={openDatasetDetails}\r\n expandedDatasets={expandedDatasets}\r\n />\r\n ))}\r\n </TableBody>\r\n </Table>\r\n </SortableContext>\r\n </DndContext>\r\n </div>\r\n )}\r\n </div>\r\n </Command>\r\n </Menubar>\r\n </div>\r\n )}\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["sortedDatasets"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { MapContext, DatasetsContext } from '../../../../../store'\r\nimport { Command, Menubar, Badge, Button, Switch } from '../../../../../components/ui/'\r\nimport {\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableRow,\r\n} from '../../../../../components/ui/Table'\r\nimport { FieldsTable } from './src/FieldsTable'\r\nimport * as LR from 'lucide-react'\r\nimport type { Dataset, BuildingDataset as RawBuildingDataset } from '../../../../../types/datasetTypes'\r\nimport { ClusterManager } from '../../utils/ClusterManager'\r\nimport {\r\n DndContext,\r\n closestCenter,\r\n KeyboardSensor,\r\n PointerSensor,\r\n useSensor,\r\n useSensors,\r\n DragEndEvent,\r\n} from '@dnd-kit/core'\r\nimport {\r\n arrayMove,\r\n SortableContext,\r\n sortableKeyboardCoordinates,\r\n verticalListSortingStrategy,\r\n} from '@dnd-kit/sortable'\r\nimport {\r\n useSortable,\r\n} from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { useSidebar } from '../../../../ui/Sidebar'\r\n\r\ntype BuildingDataset = RawBuildingDataset & Dataset\r\n\r\n// Type guard to check if dataset is a building dataset\r\nconst isBuildingDataset = (dataset: Dataset): dataset is BuildingDataset =>\r\n dataset.type === 'buildings' && 'data' in dataset\r\n\r\ninterface SortableTableRowProps {\r\n dataset: Dataset\r\n onToggleDataset: (dataset: Dataset) => void\r\n openDatasetDetails: (datasetName: string) => void\r\n expandedDatasets: Set<string>\r\n}\r\n\r\nconst SortableTableRow: React.FC<SortableTableRowProps> = ({\r\n dataset,\r\n onToggleDataset,\r\n openDatasetDetails,\r\n expandedDatasets,\r\n}) => {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n } = useSortable({ id: dataset.name })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.5 : 1,\r\n }\r\n\r\n // Raster (WMS) layers are server-rendered images with no fields and a server-fixed\r\n // colour ramp, so the field-styling table + colour swatch are meaningless — hide them.\r\n const isRaster = dataset.datasetType === 'WMS' || dataset.type === 'WMS'\r\n\r\n return (\r\n <>\r\n <TableRow ref={setNodeRef} style={style} className=\"hover:bg-muted/50\">\r\n <TableCell>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"cursor-grab active:cursor-grabbing\"\r\n {...attributes}\r\n {...listeners}\r\n >\r\n <LR.GripVertical className=\"h-4 w-4\" />\r\n </Button>\r\n <Switch\r\n checked={dataset.visible !== false}\r\n onCheckedChange={() => onToggleDataset(dataset)}\r\n className=\"shrink-0\"\r\n style={dataset.visible === false || isRaster ? {} : { backgroundColor: dataset.layerColor.color }}\r\n />\r\n </div>\r\n </TableCell>\r\n <TableCell className=\"font-medium\">\r\n {dataset.name.replaceAll('_', ' ')}\r\n {dataset.total && (\r\n <Badge variant=\"outline\" className=\"ml-2 text-xs\">\r\n {dataset.total}\r\n </Badge>\r\n )}\r\n </TableCell>\r\n <TableCell>\r\n {!isRaster && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => openDatasetDetails(dataset.name)}\r\n className=\"shrink-0\"\r\n >\r\n <LR.ChevronDown\r\n className={`h-4 w-4 transition-transform duration-200 ${expandedDatasets.has(dataset.name) ? 'rotate-180' : ''}`}\r\n />\r\n </Button>\r\n )}\r\n </TableCell>\r\n </TableRow>\r\n {!isRaster && expandedDatasets.has(dataset.name) && (\r\n <TableRow>\r\n <TableCell colSpan={4} className=\"p-0 pb-1\">\r\n <FieldsTable\r\n dataset={dataset}\r\n />\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport default function DatasetManagerMenu() {\r\n // Translation\r\n const t = useTranslations('DatasetManagerMenu')\r\n\r\n const { state: mapState, dispatch: mapDispatch } = React.useContext(MapContext)\r\n const { map } = mapState.map\r\n\r\n const { state: datasetState, dispatch: datasetDispatch } = React.useContext(DatasetsContext)\r\n const { addedDatasets } = datasetState.datasets\r\n\r\n const [open, setOpen] = React.useState(false)\r\n const [menuOpen, setMenuOpen] = React.useState(false)\r\n const [expandedDatasets, setExpandedDatasets] = React.useState<Set<string>>(new Set())\r\n\r\n const sensors = useSensors(\r\n useSensor(PointerSensor),\r\n useSensor(KeyboardSensor, {\r\n coordinateGetter: sortableKeyboardCoordinates,\r\n })\r\n )\r\n\r\n const sortedDatasets = React.useMemo(() => {\r\n const datasetsWithOrder = addedDatasets.map((dataset, index) => ({\r\n ...dataset,\r\n order: dataset.order !== undefined ? dataset.order : addedDatasets.length - 1 - index,\r\n }))\r\n\r\n return datasetsWithOrder.sort((a, b) => (b.order ?? 0) - (a.order ?? 0))\r\n }, [addedDatasets])\r\n\r\n React.useEffect(() => {\r\n if (!map || !addedDatasets) return\r\n\r\n const clusterManager = new ClusterManager(map)\r\n\r\n const sortedDatasets = [...addedDatasets].sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\r\n\r\n for (const dataset of sortedDatasets) {\r\n if (isBuildingDataset(dataset)) {\r\n if (dataset.visible === false) {\r\n clusterManager.remove(dataset.name)\r\n }\r\n else {\r\n clusterManager.create(dataset)\r\n clusterManager.toggleVisibility(dataset.name, true)\r\n }\r\n }\r\n }\r\n }, [map, addedDatasets])\r\n\r\n // Remove clusters for datasets no longer present\r\n const previousNamesRef = React.useRef<Set<string>>(new Set())\r\n\r\n React.useEffect(() => {\r\n if (!map) return\r\n const clusterManager = new ClusterManager(map)\r\n const currentNames = new Set(\r\n addedDatasets.filter(isBuildingDataset).map(ds => ds.name),\r\n )\r\n const removedNames = [...previousNamesRef.current].filter(\r\n name => !currentNames.has(name),\r\n )\r\n for (const datasetName of removedNames) {\r\n clusterManager.remove(datasetName)\r\n }\r\n previousNamesRef.current = currentNames\r\n }, [map, addedDatasets])\r\n\r\n const onToggle = () => setOpen(!open)\r\n\r\n const onToggleDataset = (dataset: Dataset) => {\r\n const datasetId = dataset.id;\r\n datasetDispatch({ type: 'TOGGLE_DATASET_VISIBILITY', payload: { datasetId } })\r\n }\r\n\r\n const toggleDatasetExpansion = (datasetName: string) => {\r\n setExpandedDatasets((prev) => {\r\n const newSet = new Set(prev)\r\n newSet.has(datasetName) ? newSet.delete(datasetName) : newSet.add(datasetName)\r\n return newSet\r\n })\r\n }\r\n\r\n const handleDragEnd = (event: DragEndEvent) => {\r\n const { active, over } = event\r\n\r\n if (over && active.id !== over.id) {\r\n const displayOrder = [...sortedDatasets]\r\n\r\n const oldIndex = displayOrder.findIndex(dataset => dataset.name === active.id)\r\n const newIndex = displayOrder.findIndex(dataset => dataset.name === over.id)\r\n\r\n const reorderedDisplay = arrayMove(displayOrder, oldIndex, newIndex)\r\n const maxOrder = reorderedDisplay.length - 1\r\n const reorderedDatasets = reorderedDisplay.map((dataset, index) => ({\r\n ...dataset,\r\n order: maxOrder - index,\r\n }))\r\n\r\n datasetDispatch({\r\n type: 'REORDER_DATASETS',\r\n payload: { reorderedDatasets }\r\n })\r\n }\r\n }\r\n\r\n const openAnimation = `\r\n pointer-events-auto \r\n transform \r\n transition-all \r\n duration-200\r\n data-[state=open]:animate-in \r\n data-[state=closed]:animate-out \r\n data-[state=closed]:fade-out-0 \r\n data-[state=open]:fade-in-0 \r\n data-[state=closed]:zoom-out-95 \r\n data-[state=open]:zoom-in-95\r\n `\r\n\r\n React.useEffect(() => {\r\n setMenuOpen(addedDatasets.length > 0)\r\n }, [addedDatasets.length])\r\n\r\n const openDatasetDetails = (datasetName: string) => {\r\n toggleDatasetExpansion(datasetName)\r\n }\r\n\r\n const {openInfo} = useSidebar()\r\n\r\n return (\r\n <>\r\n {!openInfo && addedDatasets.length > 0 && (\r\n <div data-state={menuOpen ? 'open' : 'closed'} className={openAnimation}>\r\n <Menubar className=\"pointer-events-auto w-96 h-auto\">\r\n <Command>\r\n <div>\r\n <div className={`flex items-center justify-between gap-3 ${open ? 'p-3' : 'pl-1 py-0'}`}>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge>{addedDatasets.length}</Badge>\r\n <div className=\"text-sm font-medium\">\r\n {t('appliedLayer')}\r\n {addedDatasets.length === 1 ? '' : 's'}\r\n </div>\r\n </div>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={onToggle}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <LR.ChevronUp\r\n size={14}\r\n className={`transition-transform duration-200 ${open ? 'rotate-180' : ''}`}\r\n />\r\n </Button>\r\n </div>\r\n {open && (\r\n <div className=\"max-h-[40vh] overflow-y-auto\">\r\n <DndContext\r\n sensors={sensors}\r\n collisionDetection={closestCenter}\r\n onDragEnd={handleDragEnd}\r\n >\r\n <SortableContext\r\n items={sortedDatasets.map(dataset => dataset.name)}\r\n strategy={verticalListSortingStrategy}\r\n >\r\n <Table>\r\n <TableBody>\r\n {sortedDatasets.map((dataset) => (\r\n <SortableTableRow\r\n key={dataset.name}\r\n dataset={dataset}\r\n onToggleDataset={onToggleDataset}\r\n openDatasetDetails={openDatasetDetails}\r\n expandedDatasets={expandedDatasets}\r\n />\r\n ))}\r\n </TableBody>\r\n </Table>\r\n </SortableContext>\r\n </DndContext>\r\n </div>\r\n )}\r\n </div>\r\n </Command>\r\n </Menubar>\r\n </div>\r\n )}\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":["sortedDatasets"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RowActions.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/datasets/RowActions.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;
|
|
1
|
+
{"version":3,"file":"RowActions.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/datasets/RowActions.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAG7D,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,OAAO,EAAE,CAAA;IAC5B,oBAAoB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;CACtE;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,OAAO,EACP,iBAAiB,EACjB,oBAAoB,GACrB,EAAE,eAAe,qBAoQjB"}
|
|
@@ -6,6 +6,7 @@ import { handleFavouriteDataset } from "./utils";
|
|
|
6
6
|
import { Checkbox, Button } from "../../../ui/";
|
|
7
7
|
import * as LR from "lucide-react";
|
|
8
8
|
import { DatasetsContext } from "../../../../store";
|
|
9
|
+
import { buildPublishedTileDatasets } from "./src/publishedTiles";
|
|
9
10
|
function RowActions({
|
|
10
11
|
dataset,
|
|
11
12
|
favouriteDatasets,
|
|
@@ -14,6 +15,7 @@ function RowActions({
|
|
|
14
15
|
const { ability } = usePermissions();
|
|
15
16
|
const { state: datasetsState, dispatch: datasetsDispatch } = React.useContext(DatasetsContext);
|
|
16
17
|
const { addedDatasets } = datasetsState.datasets;
|
|
18
|
+
const orgDatasets = datasetsState.datasets.datasets;
|
|
17
19
|
const isFavourite = favouriteDatasets.some((item) => item.name === dataset.name);
|
|
18
20
|
const checked = addedDatasets.some((d) => d.name === dataset.name);
|
|
19
21
|
const handleApplyDataset = () => {
|
|
@@ -35,6 +37,116 @@ function RowActions({
|
|
|
35
37
|
}
|
|
36
38
|
};
|
|
37
39
|
const handleFavourite = handleFavouriteDataset(dataset, favouriteDatasets, setFavouriteDatasets);
|
|
40
|
+
const [publishing, setPublishing] = React.useState(false);
|
|
41
|
+
const [published, setPublished] = React.useState(false);
|
|
42
|
+
const isOrgMinio = typeof dataset.id === "string" && dataset.id.startsWith("org-minio-");
|
|
43
|
+
const fileId = isOrgMinio ? Number(String(dataset.id).slice("org-minio-".length)) : null;
|
|
44
|
+
const tiledMatch = typeof dataset.id === "string" ? /^org_(\d+)_file_(\d+)$/.exec(dataset.id) : null;
|
|
45
|
+
const tiledFileId = tiledMatch ? Number(tiledMatch[2]) : typeof dataset.publishedFileId === "number" ? dataset.publishedFileId : null;
|
|
46
|
+
const [unpublishing, setUnpublishing] = React.useState(false);
|
|
47
|
+
const [unpublished, setUnpublished] = React.useState(false);
|
|
48
|
+
const onUnpublish = async () => {
|
|
49
|
+
var _a;
|
|
50
|
+
if (tiledFileId == null) return;
|
|
51
|
+
if (!window.confirm(`Un-publish "${dataset.name}"? The Martin table will be dropped; the original GeoJSON in MinIO is untouched.`)) return;
|
|
52
|
+
setUnpublishing(true);
|
|
53
|
+
try {
|
|
54
|
+
const res = await fetch("/api/datasets/publish-tiles", {
|
|
55
|
+
method: "DELETE",
|
|
56
|
+
headers: { "Content-Type": "application/json" },
|
|
57
|
+
body: JSON.stringify({ fileId: tiledFileId })
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
const body = await res.json().catch(() => ({}));
|
|
61
|
+
console.error("un-publish failed", res.status, body);
|
|
62
|
+
window.alert(`Un-publish failed: ${(_a = body == null ? void 0 : body.error) != null ? _a : res.status}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
setUnpublished(true);
|
|
66
|
+
datasetsDispatch({ type: "REFRESH_ORG_DATASETS" });
|
|
67
|
+
window.alert(`Un-published. The dataset list has been refreshed.`);
|
|
68
|
+
} finally {
|
|
69
|
+
setUnpublishing(false);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const onPublish = async () => {
|
|
73
|
+
var _a, _b, _c, _d;
|
|
74
|
+
if (fileId == null || Number.isNaN(fileId)) return;
|
|
75
|
+
setPublishing(true);
|
|
76
|
+
try {
|
|
77
|
+
const res = await fetch("/api/datasets/publish-tiles", {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: { "Content-Type": "application/json" },
|
|
80
|
+
body: JSON.stringify({ fileId })
|
|
81
|
+
});
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
const body = await res.json().catch(() => ({}));
|
|
84
|
+
console.error("publish-tiles failed", res.status, body);
|
|
85
|
+
window.alert(`Publish failed: ${(_a = body == null ? void 0 : body.error) != null ? _a : res.status}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const result = await res.json();
|
|
89
|
+
setPublished(true);
|
|
90
|
+
const tileBaseUrl = ((_b = process.env.NEXT_PUBLIC_MARTIN_SERVER_URL) != null ? _b : "").replace(/\/+$/, "");
|
|
91
|
+
const minioId = `org-minio-${fileId}`;
|
|
92
|
+
const [optimistic] = buildPublishedTileDatasets(
|
|
93
|
+
[{
|
|
94
|
+
name: dataset.name,
|
|
95
|
+
description: JSON.stringify({ tiledTable: result.table, geometryType: result.geometryType })
|
|
96
|
+
}],
|
|
97
|
+
tileBaseUrl,
|
|
98
|
+
{ countrySubdivision: (_c = dataset.countrySubdivision) != null ? _c : "", municipality: (_d = dataset.municipality) != null ? _d : "" }
|
|
99
|
+
);
|
|
100
|
+
if (optimistic) {
|
|
101
|
+
const current = orgDatasets != null ? orgDatasets : [];
|
|
102
|
+
const swapped = current.some((d) => d.id === minioId) ? current.map((d) => d.id === minioId ? optimistic : d) : [...current, optimistic];
|
|
103
|
+
datasetsDispatch({ type: "SET_DATASETS", payload: { datasets: swapped } });
|
|
104
|
+
if (addedDatasets.some((d) => d.id === minioId)) {
|
|
105
|
+
datasetsDispatch({ type: "REMOVE_DATASET_FROM_MAP", payload: { datasetId: minioId } });
|
|
106
|
+
datasetsDispatch({ type: "ADD_DATASET_TO_MAP", payload: { dataset: optimistic } });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
datasetsDispatch({ type: "REFRESH_ORG_DATASETS" });
|
|
110
|
+
window.alert(
|
|
111
|
+
`Tiled as ${result.table}. The dataset list has been refreshed.
|
|
112
|
+
|
|
113
|
+
Features ingested: ${result.featuresIngested}, skipped: ${result.featuresSkipped}.`
|
|
114
|
+
);
|
|
115
|
+
} finally {
|
|
116
|
+
setPublishing(false);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const isCatalogGeoJson = !isOrgMinio && tiledFileId == null && dataset.datasetType === "GeoJSON" && !!dataset.portal && dataset.id != null;
|
|
120
|
+
const [publishingCatalog, setPublishingCatalog] = React.useState(false);
|
|
121
|
+
const [publishedCatalog, setPublishedCatalog] = React.useState(false);
|
|
122
|
+
const onPublishCatalog = async () => {
|
|
123
|
+
var _a;
|
|
124
|
+
if (!dataset.portal || dataset.id == null) return;
|
|
125
|
+
setPublishingCatalog(true);
|
|
126
|
+
try {
|
|
127
|
+
const res = await fetch("/api/datasets/publish-catalog-tiles", {
|
|
128
|
+
method: "POST",
|
|
129
|
+
headers: { "Content-Type": "application/json" },
|
|
130
|
+
body: JSON.stringify({ portal: dataset.portal, datasetId: dataset.id })
|
|
131
|
+
});
|
|
132
|
+
if (!res.ok) {
|
|
133
|
+
const body = await res.json().catch(() => ({}));
|
|
134
|
+
console.error("publish-catalog-tiles failed", res.status, body);
|
|
135
|
+
window.alert(`Publish failed: ${(_a = body == null ? void 0 : body.error) != null ? _a : res.status}`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const result = await res.json();
|
|
139
|
+
setPublishedCatalog(true);
|
|
140
|
+
datasetsDispatch({ type: "REFRESH_ORG_DATASETS" });
|
|
141
|
+
window.alert(
|
|
142
|
+
`Tiled as ${result.table}. The dataset list has been refreshed.
|
|
143
|
+
|
|
144
|
+
Features ingested: ${result.featuresIngested}, skipped: ${result.featuresSkipped}.`
|
|
145
|
+
);
|
|
146
|
+
} finally {
|
|
147
|
+
setPublishingCatalog(false);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
38
150
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
39
151
|
/* @__PURE__ */ jsx(
|
|
40
152
|
Button,
|
|
@@ -71,6 +183,42 @@ function RowActions({
|
|
|
71
183
|
}
|
|
72
184
|
)
|
|
73
185
|
}
|
|
186
|
+
),
|
|
187
|
+
isOrgMinio && /* @__PURE__ */ jsx(
|
|
188
|
+
Button,
|
|
189
|
+
{
|
|
190
|
+
variant: "ghost",
|
|
191
|
+
size: "icon",
|
|
192
|
+
title: published ? "Tiled" : "Publish as vector tiles",
|
|
193
|
+
className: "opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent",
|
|
194
|
+
onClick: onPublish,
|
|
195
|
+
disabled: publishing || published || !ability.can("update", "File"),
|
|
196
|
+
children: /* @__PURE__ */ jsx(LR.UploadCloud, { color: published ? "hsl(var(--chart-2))" : "black" })
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
isCatalogGeoJson && /* @__PURE__ */ jsx(
|
|
200
|
+
Button,
|
|
201
|
+
{
|
|
202
|
+
variant: "ghost",
|
|
203
|
+
size: "icon",
|
|
204
|
+
title: publishedCatalog ? "Tiled" : "Publish open-data dataset as vector tiles",
|
|
205
|
+
className: "opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent",
|
|
206
|
+
onClick: onPublishCatalog,
|
|
207
|
+
disabled: publishingCatalog || publishedCatalog || !ability.can("update", "File"),
|
|
208
|
+
children: /* @__PURE__ */ jsx(LR.CloudDownload, { color: publishedCatalog ? "hsl(var(--chart-2))" : "black" })
|
|
209
|
+
}
|
|
210
|
+
),
|
|
211
|
+
tiledFileId != null && /* @__PURE__ */ jsx(
|
|
212
|
+
Button,
|
|
213
|
+
{
|
|
214
|
+
variant: "ghost",
|
|
215
|
+
size: "icon",
|
|
216
|
+
title: unpublished ? "Un-published" : "Un-publish vector tiles",
|
|
217
|
+
className: "opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent",
|
|
218
|
+
onClick: onUnpublish,
|
|
219
|
+
disabled: unpublishing || unpublished || !ability.can("update", "File"),
|
|
220
|
+
children: /* @__PURE__ */ jsx(LR.CloudOff, { color: unpublished ? "hsl(var(--chart-5))" : "black" })
|
|
221
|
+
}
|
|
74
222
|
)
|
|
75
223
|
] });
|
|
76
224
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/datasets/RowActions.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// Dependencies\r\nimport React from 'react'\r\nimport { usePermissions } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { handleFavouriteDataset } from './utils'\r\n\r\n// Shadcn Components\r\nimport { Checkbox, Button } from '../../../ui/'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\nimport { DatasetsContext } from '../../../../store'\r\nimport type { Dataset } from '../../../../types/datasetTypes'\r\n\r\ninterface RowActionsProps {\r\n dataset: Dataset\r\n favouriteDatasets: Dataset[]\r\n setFavouriteDatasets: React.Dispatch<React.SetStateAction<Dataset[]>>\r\n}\r\n\r\nexport default function RowActions({\r\n dataset,\r\n favouriteDatasets,\r\n setFavouriteDatasets,\r\n}: RowActionsProps) {\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n\r\n const { state: datasetsState, dispatch: datasetsDispatch } = React.useContext(DatasetsContext)\r\n const { addedDatasets } = datasetsState.datasets\r\n\r\n // const [checked, setChecked] = useState(false);\r\n\r\n // Check if this specific dataset is in favourites\r\n const isFavourite = favouriteDatasets.some(item => item.name === dataset.name)\r\n\r\n // \"Checked\" means the dataset is applied to the map. All dataset types —\r\n // including Organizational (MinIO/Martin-hydrated uploads) — toggle their\r\n // membership in addedDatasets, which is the only list OpenDataLayers renders.\r\n // (Previously Organizational datasets toggled a `visible` flag on the\r\n // available list, which nothing renders from, so they never appeared.)\r\n const checked = addedDatasets.some(d => d.name === dataset.name)\r\n\r\n const handleApplyDataset = () => {\r\n if (!dataset) {\r\n console.error('No dataset provided in RowActions')\r\n return\r\n }\r\n\r\n const isAdded = addedDatasets.some(d => d.name === dataset.name)\r\n\r\n if (isAdded) {\r\n datasetsDispatch({\r\n type: 'REMOVE_DATASET_FROM_MAP',\r\n payload: { datasetId: dataset.id },\r\n })\r\n }\r\n else {\r\n datasetsDispatch({\r\n type: 'ADD_DATASET_TO_MAP',\r\n payload: { dataset: dataset },\r\n })\r\n }\r\n }\r\n\r\n const handleFavourite = handleFavouriteDataset(dataset, favouriteDatasets, setFavouriteDatasets)\r\n\r\n return (\r\n <div className=\"flex items-center\">\r\n <Button\r\n size=\"icon\"\r\n variant=\"ghost\"\r\n // onClick={handleApplyDataset}\r\n className=\" hover:bg-transparent\"\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <Checkbox\r\n checked={checked}\r\n onCheckedChange={() => {\r\n handleApplyDataset()\r\n }}\r\n className=\"opacity-70 hover:opacity-100 data-[state=checked]:opacity-100 transition-opacity duration-200\"\r\n />\r\n </Button>\r\n\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className={`opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent ${isFavourite ? 'opacity-100' : ''}`}\r\n onClick={handleFavourite}\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <LR.Star\r\n color={`${isFavourite ? 'hsl(var(--chart-5))' : 'black'} `}\r\n fill={`${isFavourite ? 'hsl(var(--chart-5))' : 'none'} `}\r\n />\r\n </Button>\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAwEI,SAQI,KARJ;AArEJ,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAG/B,SAAS,8BAA8B;AAGvC,SAAS,UAAU,cAAc;AAGjC,YAAY,QAAQ;AACpB,SAAS,uBAAuB;AASjB,SAAR,WAA4B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAElB,QAAM,EAAE,QAAQ,IAAI,eAAe;AAGnC,QAAM,EAAE,OAAO,eAAe,UAAU,iBAAiB,IAAI,MAAM,WAAW,eAAe;AAC7F,QAAM,EAAE,cAAc,IAAI,cAAc;AAKxC,QAAM,cAAc,kBAAkB,KAAK,UAAQ,KAAK,SAAS,QAAQ,IAAI;AAO7E,QAAM,UAAU,cAAc,KAAK,OAAK,EAAE,SAAS,QAAQ,IAAI;AAE/D,QAAM,qBAAqB,MAAM;AAC/B,QAAI,CAAC,SAAS;AACZ,cAAQ,MAAM,mCAAmC;AACjD;AAAA,IACF;AAEA,UAAM,UAAU,cAAc,KAAK,OAAK,EAAE,SAAS,QAAQ,IAAI;AAE/D,QAAI,SAAS;AACX,uBAAiB;AAAA,QACf,MAAM;AAAA,QACN,SAAS,EAAE,WAAW,QAAQ,GAAG;AAAA,MACnC,CAAC;AAAA,IACH,OACK;AACH,uBAAiB;AAAA,QACf,MAAM;AAAA,QACN,SAAS,EAAE,QAAiB;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,kBAAkB,uBAAuB,SAAS,mBAAmB,oBAAoB;AAE/F,SACE,qBAAC,SAAI,WAAU,qBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QAER,WAAU;AAAA,QACV,UAAU,CAAC,QAAQ,IAAI,QAAQ,MAAM;AAAA,QAErC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,iBAAiB,MAAM;AACrB,iCAAmB;AAAA,YACrB;AAAA,YACA,WAAU;AAAA;AAAA,QACZ;AAAA;AAAA,IACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW,qFAAqF,cAAc,gBAAgB,EAAE;AAAA,QAChI,SAAS;AAAA,QACT,UAAU,CAAC,QAAQ,IAAI,QAAQ,MAAM;AAAA,QAErC;AAAA,UAAC,GAAG;AAAA,UAAH;AAAA,YACC,OAAO,GAAG,cAAc,wBAAwB,OAAO;AAAA,YACvD,MAAM,GAAG,cAAc,wBAAwB,MAAM;AAAA;AAAA,QACvD;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/datasets/RowActions.tsx"],"sourcesContent":["\"use client\"\r\n\r\n// Dependencies\r\nimport React from 'react'\r\nimport { usePermissions } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { handleFavouriteDataset } from './utils'\r\n\r\n// Shadcn Components\r\nimport { Checkbox, Button } from '../../../ui/'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\nimport { DatasetsContext } from '../../../../store'\r\nimport type { Dataset } from '../../../../types/datasetTypes'\r\nimport { buildPublishedTileDatasets } from './src/publishedTiles'\r\n\r\ninterface RowActionsProps {\r\n dataset: Dataset\r\n favouriteDatasets: Dataset[]\r\n setFavouriteDatasets: React.Dispatch<React.SetStateAction<Dataset[]>>\r\n}\r\n\r\nexport default function RowActions({\r\n dataset,\r\n favouriteDatasets,\r\n setFavouriteDatasets,\r\n}: RowActionsProps) {\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n\r\n const { state: datasetsState, dispatch: datasetsDispatch } = React.useContext(DatasetsContext)\r\n const { addedDatasets } = datasetsState.datasets\r\n const orgDatasets = datasetsState.datasets.datasets\r\n\r\n // const [checked, setChecked] = useState(false);\r\n\r\n // Check if this specific dataset is in favourites\r\n const isFavourite = favouriteDatasets.some(item => item.name === dataset.name)\r\n\r\n // \"Checked\" means the dataset is applied to the map. All dataset types —\r\n // including Organizational (MinIO/Martin-hydrated uploads) — toggle their\r\n // membership in addedDatasets, which is the only list OpenDataLayers renders.\r\n // (Previously Organizational datasets toggled a `visible` flag on the\r\n // available list, which nothing renders from, so they never appeared.)\r\n const checked = addedDatasets.some(d => d.name === dataset.name)\r\n\r\n const handleApplyDataset = () => {\r\n if (!dataset) {\r\n console.error('No dataset provided in RowActions')\r\n return\r\n }\r\n\r\n const isAdded = addedDatasets.some(d => d.name === dataset.name)\r\n\r\n if (isAdded) {\r\n datasetsDispatch({\r\n type: 'REMOVE_DATASET_FROM_MAP',\r\n payload: { datasetId: dataset.id },\r\n })\r\n }\r\n else {\r\n datasetsDispatch({\r\n type: 'ADD_DATASET_TO_MAP',\r\n payload: { dataset: dataset },\r\n })\r\n }\r\n }\r\n\r\n const handleFavourite = handleFavouriteDataset(dataset, favouriteDatasets, setFavouriteDatasets)\r\n\r\n const [publishing, setPublishing] = React.useState(false)\r\n const [published, setPublished] = React.useState(false)\r\n\r\n const isOrgMinio = typeof dataset.id === 'string' && dataset.id.startsWith('org-minio-')\r\n const fileId = isOrgMinio\r\n ? Number(String(dataset.id).slice('org-minio-'.length))\r\n : null\r\n\r\n const tiledMatch = typeof dataset.id === 'string'\r\n ? /^org_(\\d+)_file_(\\d+)$/.exec(dataset.id)\r\n : null\r\n // A row is \"converted\" either because it IS the org_<orgId>_file_<fileId> tile\r\n // entry (organizational tab), or because it's the original open-data dataset\r\n // stamped with the published File it resolves to (every other tab). Either way\r\n // we show the un-publish action and drive it with this fileId.\r\n const tiledFileId = tiledMatch\r\n ? Number(tiledMatch[2])\r\n : (typeof dataset.publishedFileId === 'number' ? dataset.publishedFileId : null)\r\n\r\n const [unpublishing, setUnpublishing] = React.useState(false)\r\n const [unpublished, setUnpublished] = React.useState(false)\r\n\r\n const onUnpublish = async () => {\r\n if (tiledFileId == null) return\r\n if (!window.confirm(`Un-publish \"${dataset.name}\"? The Martin table will be dropped; the original GeoJSON in MinIO is untouched.`)) return\r\n setUnpublishing(true)\r\n try {\r\n const res = await fetch('/api/datasets/publish-tiles', {\r\n method: 'DELETE',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ fileId: tiledFileId }),\r\n })\r\n if (!res.ok) {\r\n const body = await res.json().catch(() => ({}))\r\n console.error('un-publish failed', res.status, body)\r\n window.alert(`Un-publish failed: ${body?.error ?? res.status}`)\r\n return\r\n }\r\n setUnpublished(true)\r\n datasetsDispatch({ type: 'REFRESH_ORG_DATASETS' })\r\n window.alert(`Un-published. The dataset list has been refreshed.`)\r\n }\r\n finally {\r\n setUnpublishing(false)\r\n }\r\n }\r\n\r\n const onPublish = async () => {\r\n if (fileId == null || Number.isNaN(fileId)) return\r\n setPublishing(true)\r\n try {\r\n const res = await fetch('/api/datasets/publish-tiles', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ fileId }),\r\n })\r\n if (!res.ok) {\r\n const body = await res.json().catch(() => ({}))\r\n console.error('publish-tiles failed', res.status, body)\r\n window.alert(`Publish failed: ${body?.error ?? res.status}`)\r\n return\r\n }\r\n const result = await res.json()\r\n setPublished(true)\r\n\r\n // Optimistically swap the MinIO upload row for its published-tile form so the\r\n // un-publish (CloudOff) icon shows immediately. The full org refetch below\r\n // (REFRESH_ORG_DATASETS) re-samples a vector tile per dataset to detect geometry,\r\n // which can take several seconds; without this the row only flips after that lands\r\n // (or after the dialog is reopened). The refetch reconciles this swap when it finishes.\r\n const tileBaseUrl = (process.env.NEXT_PUBLIC_MARTIN_SERVER_URL ?? '').replace(/\\/+$/, '')\r\n const minioId = `org-minio-${fileId}`\r\n const [optimistic] = buildPublishedTileDatasets(\r\n [{\r\n name: dataset.name,\r\n description: JSON.stringify({ tiledTable: result.table, geometryType: result.geometryType }),\r\n }],\r\n tileBaseUrl,\r\n { countrySubdivision: dataset.countrySubdivision ?? '', municipality: dataset.municipality ?? '' } as any,\r\n )\r\n if (optimistic) {\r\n const current = orgDatasets ?? []\r\n const swapped = current.some(d => d.id === minioId)\r\n ? current.map(d => (d.id === minioId ? optimistic : d))\r\n : [...current, optimistic]\r\n datasetsDispatch({ type: 'SET_DATASETS', payload: { datasets: swapped } })\r\n // Keep the map layer in sync if this dataset was already applied.\r\n if (addedDatasets.some(d => d.id === minioId)) {\r\n datasetsDispatch({ type: 'REMOVE_DATASET_FROM_MAP', payload: { datasetId: minioId } })\r\n datasetsDispatch({ type: 'ADD_DATASET_TO_MAP', payload: { dataset: optimistic } })\r\n }\r\n }\r\n\r\n datasetsDispatch({ type: 'REFRESH_ORG_DATASETS' })\r\n window.alert(\r\n `Tiled as ${result.table}. The dataset list has been refreshed.\\n\\n`\r\n + `Features ingested: ${result.featuresIngested}, skipped: ${result.featuresSkipped}.`,\r\n )\r\n }\r\n finally {\r\n setPublishing(false)\r\n }\r\n }\r\n\r\n // Catalog (open-data-portal) GeoJSON datasets: not a MinIO upload, not an already-tiled\r\n // table, carry a portal + are typed GeoJSON. MVT catalog datasets are already tiles.\r\n const isCatalogGeoJson =\r\n !isOrgMinio\r\n && tiledFileId == null\r\n && dataset.datasetType === 'GeoJSON'\r\n && !!dataset.portal\r\n && dataset.id != null\r\n\r\n const [publishingCatalog, setPublishingCatalog] = React.useState(false)\r\n const [publishedCatalog, setPublishedCatalog] = React.useState(false)\r\n\r\n const onPublishCatalog = async () => {\r\n if (!dataset.portal || dataset.id == null) return\r\n setPublishingCatalog(true)\r\n try {\r\n const res = await fetch('/api/datasets/publish-catalog-tiles', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ portal: dataset.portal, datasetId: dataset.id }),\r\n })\r\n if (!res.ok) {\r\n const body = await res.json().catch(() => ({}))\r\n console.error('publish-catalog-tiles failed', res.status, body)\r\n window.alert(`Publish failed: ${body?.error ?? res.status}`)\r\n return\r\n }\r\n const result = await res.json()\r\n setPublishedCatalog(true)\r\n datasetsDispatch({ type: 'REFRESH_ORG_DATASETS' })\r\n window.alert(\r\n `Tiled as ${result.table}. The dataset list has been refreshed.\\n\\n`\r\n + `Features ingested: ${result.featuresIngested}, skipped: ${result.featuresSkipped}.`,\r\n )\r\n }\r\n finally {\r\n setPublishingCatalog(false)\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"flex items-center\">\r\n <Button\r\n size=\"icon\"\r\n variant=\"ghost\"\r\n // onClick={handleApplyDataset}\r\n className=\" hover:bg-transparent\"\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <Checkbox\r\n checked={checked}\r\n onCheckedChange={() => {\r\n handleApplyDataset()\r\n }}\r\n className=\"opacity-70 hover:opacity-100 data-[state=checked]:opacity-100 transition-opacity duration-200\"\r\n />\r\n </Button>\r\n\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className={`opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent ${isFavourite ? 'opacity-100' : ''}`}\r\n onClick={handleFavourite}\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <LR.Star\r\n color={`${isFavourite ? 'hsl(var(--chart-5))' : 'black'} `}\r\n fill={`${isFavourite ? 'hsl(var(--chart-5))' : 'none'} `}\r\n />\r\n </Button>\r\n\r\n {isOrgMinio && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title={published ? 'Tiled' : 'Publish as vector tiles'}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n onClick={onPublish}\r\n disabled={publishing || published || !ability.can('update', 'File')}\r\n >\r\n <LR.UploadCloud color={published ? 'hsl(var(--chart-2))' : 'black'} />\r\n </Button>\r\n )}\r\n\r\n {isCatalogGeoJson && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title={publishedCatalog ? 'Tiled' : 'Publish open-data dataset as vector tiles'}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n onClick={onPublishCatalog}\r\n disabled={publishingCatalog || publishedCatalog || !ability.can('update', 'File')}\r\n >\r\n <LR.CloudDownload color={publishedCatalog ? 'hsl(var(--chart-2))' : 'black'} />\r\n </Button>\r\n )}\r\n\r\n {tiledFileId != null && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title={unpublished ? 'Un-published' : 'Un-publish vector tiles'}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n onClick={onUnpublish}\r\n disabled={unpublishing || unpublished || !ability.can('update', 'File')}\r\n >\r\n <LR.CloudOff color={unpublished ? 'hsl(var(--chart-5))' : 'black'} />\r\n </Button>\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/datasets/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAM,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/datasets/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAM,KAAK,MAAM,OAAO,CAAA;AAsG/B,KAAK,aAAa,GAAG;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACzC,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,aAAa,qBAkkB1E"}
|