@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/datasets/src/localDatasets.ts"],"sourcesContent":["import type { Dataset, FieldType, LayerGeometryType } from '../../../../../types/datasetTypes'\r\nimport { formatName } from '../utils'\r\nimport { DatasetGroup, type OpenDataPortal } from '../../../../../types/dbTypes'\r\nimport type { AllGeoJSON } from '@turf/turf'\r\nimport { layerColorByName } from '../../utils/stringToColour'\r\nimport Pbf from 'pbf'\r\nimport { VectorTile } from '@mapbox/vector-tile'\r\nimport { getCache, setCache } from './cache'\r\n\r\n\r\n// Define the structure of local dataset items\r\ninterface LocalDatasetItem {\r\n name: string\r\n organization: number\r\n featuresUrl: string\r\n tileName: string\r\n sourceLayer: string\r\n layer: {\r\n type: string\r\n properties: Record<string, string>\r\n }\r\n visible: boolean\r\n clickable: boolean\r\n url: string\r\n description: string\r\n publisher: string\r\n countrySubdivision?: string\r\n municipality?: string\r\n}\r\n\r\ninterface MartinCatalogTile {\r\n content_type: string\r\n description: string\r\n}\r\n\r\ninterface MartinCatalog {\r\n tiles: Record<string, MartinCatalogTile>\r\n}\r\n\r\ninterface MartinTileStatsAttribute {\r\n attribute: string\r\n values?: Array<string | number>\r\n min?: number | string\r\n max?: number | string\r\n}\r\n\r\ninterface MartinTileStatsLayer {\r\n layer: string\r\n attributes?: MartinTileStatsAttribute[]\r\n}\r\n\r\ninterface MartinTileStats {\r\n layers?: MartinTileStatsLayer[]\r\n}\r\n\r\ninterface MartinTileJson {\r\n id?: string\r\n name?: string\r\n description?: string\r\n tiles?: string[]\r\n vector_layers?: Array<{\r\n id: string\r\n description?: string\r\n minzoom?: number\r\n maxzoom?: number\r\n fields?: Record<string, string>\r\n }>\r\n tilestats?: MartinTileStats\r\n minzoom?: number\r\n maxzoom?: number\r\n}\r\n\r\ntype MartinIndexResponse =\r\n | MartinCatalog\r\n | MartinTileJson[]\r\n | { tiles: Record<string, MartinTileJson> }\r\n | { tilesets: MartinTileJson[] }\r\n\r\ninterface NormalizedMartinTile {\r\n tileName: string\r\n tileUrl: string\r\n description?: string\r\n vectorLayerId: string\r\n tilestats?: MartinTileStats\r\n minzoom?: number\r\n}\r\n\r\nconst ORGANIZATION_FIELD = 'organization'\r\n\r\nfunction normalizeMartinBaseUrl(apiUrl: string) {\r\n return apiUrl.replace(/\\/+$/, '')\r\n}\r\n\r\nfunction resolveMartinUrls(apiUrl: string) {\r\n const trimmed = normalizeMartinBaseUrl(apiUrl)\r\n\r\n if (trimmed.endsWith('/tiles/index.json')) {\r\n const tileBaseUrl = trimmed.replace(/\\/tiles\\/index\\.json$/, '')\r\n return {\r\n indexUrl: trimmed,\r\n tileBaseUrl,\r\n fallbackCatalogUrl: `${tileBaseUrl}/catalog`,\r\n }\r\n }\r\n\r\n if (trimmed.endsWith('/catalog')) {\r\n const tileBaseUrl = trimmed.replace(/\\/catalog$/, '')\r\n return {\r\n indexUrl: `${tileBaseUrl}/tiles/index.json`,\r\n tileBaseUrl,\r\n fallbackCatalogUrl: trimmed,\r\n }\r\n }\r\n\r\n return {\r\n indexUrl: `${trimmed}/tiles/index.json`,\r\n tileBaseUrl: trimmed,\r\n fallbackCatalogUrl: `${trimmed}/catalog`,\r\n }\r\n}\r\n\r\nfunction ensureAbsoluteTileUrl(tileUrl: string, tileBaseUrl: string) {\r\n if (/^https?:\\/\\//i.test(tileUrl)) {\r\n return tileUrl\r\n }\r\n\r\n const cleanedBase = tileBaseUrl.replace(/\\/+$/, '')\r\n const cleanedPath = tileUrl.replace(/^\\/+/, '')\r\n return `${cleanedBase}/${cleanedPath}`\r\n}\r\n\r\nfunction normalizeTileInfo(tileInfo: MartinTileJson, fallbackName: string | null, tileBaseUrl: string): NormalizedMartinTile | null {\r\n const tileName = tileInfo.id || tileInfo.name || fallbackName\r\n if (!tileName) return null\r\n\r\n const vectorLayerId = tileInfo.vector_layers?.[0]?.id || tileName\r\n const tileUrlFromInfo = Array.isArray(tileInfo.tiles) && tileInfo.tiles.length > 0\r\n ? tileInfo.tiles[0]\r\n : `${tileBaseUrl}/${tileName}/{z}/{x}/{y}`\r\n\r\n return {\r\n tileName,\r\n tileUrl: ensureAbsoluteTileUrl(tileUrlFromInfo, tileBaseUrl),\r\n description: tileInfo.description || tileInfo.vector_layers?.[0]?.description,\r\n vectorLayerId,\r\n tilestats: tileInfo.tilestats,\r\n minzoom: tileInfo.minzoom || tileInfo.vector_layers?.[0]?.minzoom,\r\n }\r\n}\r\n\r\nfunction normalizeMartinCatalog(response: MartinIndexResponse, tileBaseUrl: string): NormalizedMartinTile[] {\r\n if (Array.isArray(response)) {\r\n return response\r\n .map(tile => normalizeTileInfo(tile, null, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n if ('tilesets' in response && Array.isArray(response.tilesets)) {\r\n return response.tilesets\r\n .map(tile => normalizeTileInfo(tile, null, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n if ('tiles' in response && response.tiles) {\r\n return Object.entries(response.tiles)\r\n .map(([tileName, tileInfo]) => normalizeTileInfo(tileInfo as MartinTileJson, tileName, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n return []\r\n}\r\n\r\nfunction parseOrganizationValue(value: unknown): number | undefined {\r\n if (value == null) return undefined\r\n if (typeof value === 'number' && Number.isFinite(value)) return value\r\n\r\n const parsed = Number.parseInt(String(value), 10)\r\n return Number.isFinite(parsed) ? parsed : undefined\r\n}\r\n\r\nfunction extractOrganizationFromTilestats(tilestats?: MartinTileStats): number | undefined {\r\n if (!tilestats?.layers) return undefined\r\n\r\n for (const layer of tilestats.layers) {\r\n const orgAttribute = layer.attributes?.find(attr =>\r\n attr.attribute?.toLowerCase() === ORGANIZATION_FIELD,\r\n )\r\n\r\n if (!orgAttribute) continue\r\n\r\n if (orgAttribute.values && orgAttribute.values.length > 0) {\r\n const value = parseOrganizationValue(orgAttribute.values[0])\r\n if (value !== undefined) return value\r\n }\r\n\r\n if (orgAttribute.min !== undefined && orgAttribute.max !== undefined) {\r\n const min = parseOrganizationValue(orgAttribute.min)\r\n const max = parseOrganizationValue(orgAttribute.max)\r\n if (min !== undefined && max !== undefined && min === max) {\r\n return min\r\n }\r\n }\r\n }\r\n\r\n return undefined\r\n}\r\n\r\nasync function fetchOrganizationFromTile(tileUrlTemplate: string, vectorLayerId: string, preferredZoom?: number) {\r\n try {\r\n const z = typeof preferredZoom === 'number' ? Math.max(0, Math.round(preferredZoom)) : 0\r\n const sampleUrl = tileUrlTemplate\r\n .replace('{z}', String(z))\r\n .replace('{x}', '0')\r\n .replace('{y}', '0')\r\n .replace('{Z}', String(z))\r\n .replace('{X}', '0')\r\n .replace('{Y}', '0')\r\n\r\n const response = await fetch(sampleUrl)\r\n if (!response.ok) return undefined\r\n\r\n const buffer = await response.arrayBuffer()\r\n const vectorTile = new VectorTile(new Pbf(buffer))\r\n const layer = vectorTile.layers[vectorLayerId] || Object.values(vectorTile.layers)[0]\r\n\r\n if (!layer || layer.length === 0) return undefined\r\n\r\n const feature = layer.feature(0)\r\n const { properties } = feature.toGeoJSON(0, 0, z)\r\n \r\n // Determine geometry type\r\n let geometryType: LayerGeometryType | undefined\r\n if (feature.type === 1) { // Point\r\n geometryType = 'circle'\r\n } else if (feature.type === 2) { // LineString\r\n geometryType = 'line'\r\n } else if (feature.type === 3) { // Polygon\r\n geometryType = 'fill'\r\n }\r\n\r\n return {\r\n organization: parseOrganizationValue(properties?.[ORGANIZATION_FIELD]),\r\n geometryType\r\n }\r\n } catch (error) {\r\n console.warn('Failed to read organization from tile', error)\r\n return undefined\r\n }\r\n}\r\n\r\nasync function resolveDatasetOrganization(tile: NormalizedMartinTile) {\r\n const fromTilestats = extractOrganizationFromTilestats(tile.tilestats)\r\n \r\n // Always fetch from tile to get geometry type, even if we have organization from tilestats\r\n const fromTile = await fetchOrganizationFromTile(tile.tileUrl, tile.vectorLayerId, tile.minzoom)\r\n \r\n return {\r\n organization: fromTilestats !== undefined ? fromTilestats : fromTile?.organization,\r\n geometryType: fromTile?.geometryType\r\n }\r\n}\r\n\r\nasync function fetchMartinServerDatasets(\r\n portal: OpenDataPortal,\r\n): Promise<Dataset[]> {\r\n const { countrySubdivision, municipality } = portal\r\n const martinServerUrl = portal.apiUrl\r\n\r\n if (!martinServerUrl) {\r\n console.warn('No Martin server URL configured for portal', portal.name)\r\n return []\r\n }\r\n\r\n try {\r\n console.log('Fetching Martin server catalog from:', martinServerUrl)\r\n\r\n const { indexUrl, tileBaseUrl, fallbackCatalogUrl } = resolveMartinUrls(martinServerUrl)\r\n\r\n let response = await fetch(indexUrl)\r\n if (!response.ok && fallbackCatalogUrl && fallbackCatalogUrl !== indexUrl) {\r\n console.warn(`Failed to fetch Martin index (${indexUrl}), falling back to catalog...`)\r\n response = await fetch(fallbackCatalogUrl)\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch Martin catalog: ${response.status}`)\r\n }\r\n\r\n const catalog: MartinIndexResponse = await response.json()\r\n const tiles = normalizeMartinCatalog(catalog, tileBaseUrl)\r\n\r\n console.log('Martin catalog received:', tiles.length, 'tiles')\r\n\r\n const datasets: Dataset[] = await Promise.all(tiles.map(async (tileInfo) => {\r\n const cleanName = formatName(\r\n tileInfo.tileName\r\n .replace(/_\\d{8}$/, '')\r\n .replace(/__\\d+_\\d+$/, ''),\r\n )\r\n\r\n const { organization, geometryType } = await resolveDatasetOrganization(tileInfo)\r\n\r\n const getFields = async () => {\r\n return []\r\n }\r\n\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n return {\r\n type: 'FeatureCollection',\r\n features: [],\r\n } as AllGeoJSON\r\n }\r\n\r\n const getFeaturesData = async () => {\r\n return {\r\n id: tileInfo.tileName,\r\n name: cleanName,\r\n type: 'MVT',\r\n visible: true,\r\n clickable: true,\r\n fields: [],\r\n source: {\r\n url: tileInfo.tileUrl,\r\n description: tileInfo.description,\r\n publisher: 'Martin Server',\r\n },\r\n serviceInfo: {\r\n tileName: tileInfo.tileName,\r\n sourceLayer: tileInfo.vectorLayerId,\r\n type: 'Martin',\r\n tileUrl: tileInfo.tileUrl,\r\n },\r\n }\r\n }\r\n\r\n const dataset: Dataset = {\r\n id: tileInfo.tileName,\r\n name: cleanName,\r\n organization,\r\n publisher: 'Martin Server',\r\n dataManagementSystem: 'other',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n keywords: [],\r\n description: tileInfo.description || `Vector tile layer from Martin server: ${tileInfo.tileName}`,\r\n dateReleased: '',\r\n dateUpdated: '',\r\n information: tileInfo.tileUrl,\r\n url: tileInfo.tileUrl,\r\n countrySubdivision: countrySubdivision,\r\n municipality: municipality,\r\n type: 'MVT',\r\n datasetType: 'MVT' as any,\r\n portal,\r\n getFields,\r\n getFeatures,\r\n getFeaturesData,\r\n group: DatasetGroup.Organizational,\r\n layerColor: layerColorByName(cleanName),\r\n layerType: geometryType,\r\n }\r\n\r\n return dataset\r\n }))\r\n\r\n console.log(`Transformed ${datasets.length} Martin datasets`)\r\n return datasets\r\n } catch (error) {\r\n console.error('Error fetching Martin server datasets:', error)\r\n return []\r\n }\r\n}\r\n\r\n// Fetch Local datasets from localDatasetsJson array and transform to Dataset array\r\nexport async function fetchLocalDatasets(\r\n portal: OpenDataPortal,\r\n): Promise<Dataset[]> {\r\n const { countrySubdivision, municipality } = portal\r\n const apiUrl = portal.apiUrl || ''\r\n const trimmedApiUrl = apiUrl.replace(/\\/+$/, '')\r\n\r\n if (!apiUrl) {\r\n console.warn('No apiUrl provided for portal', portal.name)\r\n return []\r\n }\r\n\r\n // Skip legacy portals with non-absolute URLs (e.g. ./localDatasets/index.json)\r\n if (!apiUrl.startsWith('http://') && !apiUrl.startsWith('https://')) {\r\n return []\r\n }\r\n\r\n if (trimmedApiUrl.includes('/catalog') || trimmedApiUrl.includes('/tiles/index')) {\r\n return fetchMartinServerDatasets(portal)\r\n }\r\n\r\n try {\r\n // Fetch the localDatasets.json file\r\n const response = await fetch(apiUrl)\r\n if (!response.ok) {\r\n const shouldTryMartinFallback =\r\n !trimmedApiUrl.endsWith('.json')\r\n && !trimmedApiUrl.includes('/catalog')\r\n && !trimmedApiUrl.includes('/tiles/index')\r\n\r\n if (response.status === 404 && shouldTryMartinFallback) {\r\n console.warn(\r\n `Local dataset URL returned 404 (${apiUrl}); retrying as a Martin server base URL`,\r\n )\r\n return fetchMartinServerDatasets({\r\n ...portal,\r\n apiUrl: trimmedApiUrl,\r\n })\r\n }\r\n\r\n throw new Error(`Failed to fetch local datasets from ${apiUrl}: ${response.status}`)\r\n }\r\n\r\n const localDatasetsJson: LocalDatasetItem[] = await response.json()\r\n\r\n const transformedDatasets: Dataset[] = localDatasetsJson.map((datasetItem: LocalDatasetItem) => {\r\n // Simple getFields function that returns fields from layer properties\r\n const getFields = async () => {\r\n if (datasetItem.layer?.properties) {\r\n return Object.entries(datasetItem.layer.properties).map(([name, type]) => ({\r\n name,\r\n label: formatName(name),\r\n type: type as string,\r\n description: `${formatName(name)} field`,\r\n }))\r\n }\r\n return []\r\n }\r\n\r\n // Fetch GeoJSON data from the featuresUrl\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n // Create a cache key based on the dataset name and features URL\r\n const featuresKey = `features:local:${datasetItem.name}:${datasetItem.featuresUrl}`\r\n \r\n // Check cache first\r\n const cachedFeatures = getCache<AllGeoJSON>(featuresKey)\r\n if (cachedFeatures) {\r\n return cachedFeatures\r\n }\r\n \r\n try {\r\n // Use the featuresUrl from the dataset item\r\n let geojsonUrl: string\r\n if (datasetItem.featuresUrl.startsWith('http://') || datasetItem.featuresUrl.startsWith('https://')) {\r\n geojsonUrl = datasetItem.featuresUrl\r\n } else {\r\n const baseUrl = apiUrl.endsWith('.json') \r\n ? apiUrl.substring(0, apiUrl.lastIndexOf('/'))\r\n : apiUrl\r\n geojsonUrl = `${baseUrl}/${datasetItem.featuresUrl}`\r\n }\r\n\r\n const response = await fetch(geojsonUrl)\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch GeoJSON: ${response.status}`)\r\n }\r\n\r\n const geojsonData = await response.json() as AllGeoJSON\r\n \r\n // Cache for 1 hour\r\n setCache(featuresKey, geojsonData, 60 * 60 * 1000)\r\n \r\n return geojsonData\r\n } catch (error) {\r\n console.error(`Error loading GeoJSON for ${datasetItem.name}:`, error)\r\n return {\r\n type: 'FeatureCollection',\r\n features: [],\r\n } as AllGeoJSON\r\n }\r\n }\r\n\r\n const name = formatName(datasetItem.name)\r\n\r\n const getFeaturesData = async () => {\r\n try {\r\n return {\r\n // Basic layer information\r\n id: datasetItem.tileName || datasetItem.name.toLowerCase().replace(/\\s+/g, '-'),\r\n name: datasetItem.name,\r\n type: datasetItem.layer?.type || 'GeoJSON',\r\n\r\n // Layer configuration\r\n visible: datasetItem.visible,\r\n clickable: datasetItem.clickable,\r\n\r\n // Field information (similar to ArcGIS fields structure)\r\n fields: datasetItem.layer?.properties\r\n ? Object.entries(datasetItem.layer.properties).map(([name, type]) => ({\r\n name,\r\n type: type as FieldType,\r\n alias: formatName(name),\r\n description: `${formatName(name)} field`,\r\n }))\r\n : [],\r\n\r\n // Source information\r\n source: {\r\n url: datasetItem.url,\r\n description: datasetItem.description,\r\n publisher: datasetItem.publisher,\r\n featuresUrl: datasetItem.featuresUrl,\r\n },\r\n\r\n // Additional metadata that DatasetDetails.tsx might use\r\n editingInfo: {\r\n lastEditDate: new Date().toISOString(), // Current date as placeholder\r\n dataLastEditDate: new Date().toISOString(),\r\n },\r\n\r\n // Layer properties summary\r\n properties: datasetItem.layer?.properties || {},\r\n fieldCount: datasetItem.layer?.properties ? Object.keys(datasetItem.layer.properties).length : 0,\r\n\r\n // Geometry information\r\n geometryType: 'Unknown', // You could infer this from the actual GeoJSON if needed\r\n\r\n // Service information (for compatibility)\r\n serviceInfo: {\r\n tileName: datasetItem.tileName,\r\n sourceLayer: datasetItem.sourceLayer,\r\n type: 'Local',\r\n },\r\n }\r\n } catch (error) {\r\n console.error('Error getting features data for dataset:', datasetItem.name, error)\r\n return null\r\n }\r\n }\r\n\r\n return {\r\n id: datasetItem.tileName || datasetItem.name.toLowerCase().replace(/\\s+/g, '-'),\r\n name,\r\n organization: datasetItem.organization || 0,\r\n publisher: datasetItem.publisher || 'Unknown',\r\n dataManagementSystem: 'other',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n keywords: [],\r\n description: datasetItem.description || 'No description available',\r\n dateReleased: '',\r\n dateUpdated: '',\r\n information: datasetItem.url || '',\r\n url: datasetItem.url || '#', // Ensure there's always a valid URL for the Link component\r\n countrySubdivision: datasetItem.countrySubdivision || countrySubdivision,\r\n municipality: datasetItem.municipality || municipality,\r\n type: datasetItem.layer?.type || 'GeoJSON',\r\n datasetType: 'GeoJSON' as const,\r\n portal,\r\n getFields,\r\n getFeatures,\r\n getFeaturesData,\r\n group: 'Organizational',\r\n layerColor: layerColorByName(name),\r\n }\r\n })\r\n\r\n return transformedDatasets\r\n } catch (error) {\r\n console.error('Error fetching local datasets:', error)\r\n return []\r\n }\r\n}\r\n"],"mappings":"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","names":["_a","name","response"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/src/localDatasets.ts"],"sourcesContent":["import type { Dataset, FieldType, LayerGeometryType } from '../../../../../types/datasetTypes'\r\nimport { formatName } from '../utils'\r\nimport { DatasetGroup, type OpenDataPortal } from '../../../../../types/dbTypes'\r\nimport type { AllGeoJSON } from '@turf/turf'\r\nimport { layerColorByName } from '../../utils/stringToColour'\r\nimport Pbf from 'pbf'\r\nimport { VectorTile } from '@mapbox/vector-tile'\r\nimport { getCache, setCache } from './cache'\r\nimport { isPublishedOrgTable, buildPublishedTileDatasets, type PublishedFileRow } from './publishedTiles'\r\n\r\n\r\n// Define the structure of local dataset items\r\ninterface LocalDatasetItem {\r\n name: string\r\n organization: number\r\n featuresUrl: string\r\n tileName: string\r\n sourceLayer: string\r\n layer: {\r\n type: string\r\n properties: Record<string, string>\r\n }\r\n visible: boolean\r\n clickable: boolean\r\n url: string\r\n description: string\r\n publisher: string\r\n countrySubdivision?: string\r\n municipality?: string\r\n}\r\n\r\ninterface MartinCatalogTile {\r\n content_type: string\r\n description: string\r\n}\r\n\r\ninterface MartinCatalog {\r\n tiles: Record<string, MartinCatalogTile>\r\n}\r\n\r\ninterface MartinTileStatsAttribute {\r\n attribute: string\r\n values?: Array<string | number>\r\n min?: number | string\r\n max?: number | string\r\n}\r\n\r\ninterface MartinTileStatsLayer {\r\n layer: string\r\n attributes?: MartinTileStatsAttribute[]\r\n}\r\n\r\ninterface MartinTileStats {\r\n layers?: MartinTileStatsLayer[]\r\n}\r\n\r\ninterface MartinTileJson {\r\n id?: string\r\n name?: string\r\n description?: string\r\n tiles?: string[]\r\n vector_layers?: Array<{\r\n id: string\r\n description?: string\r\n minzoom?: number\r\n maxzoom?: number\r\n fields?: Record<string, string>\r\n }>\r\n tilestats?: MartinTileStats\r\n minzoom?: number\r\n maxzoom?: number\r\n}\r\n\r\ntype MartinIndexResponse =\r\n | MartinCatalog\r\n | MartinTileJson[]\r\n | { tiles: Record<string, MartinTileJson> }\r\n | { tilesets: MartinTileJson[] }\r\n\r\ninterface NormalizedMartinTile {\r\n tileName: string\r\n tileUrl: string\r\n description?: string\r\n vectorLayerId: string\r\n tilestats?: MartinTileStats\r\n minzoom?: number\r\n}\r\n\r\nconst ORGANIZATION_FIELD = 'organization'\r\n\r\nfunction normalizeMartinBaseUrl(apiUrl: string) {\r\n return apiUrl.replace(/\\/+$/, '')\r\n}\r\n\r\nfunction resolveMartinUrls(apiUrl: string) {\r\n const trimmed = normalizeMartinBaseUrl(apiUrl)\r\n\r\n if (trimmed.endsWith('/tiles/index.json')) {\r\n const tileBaseUrl = trimmed.replace(/\\/tiles\\/index\\.json$/, '')\r\n return {\r\n indexUrl: trimmed,\r\n tileBaseUrl,\r\n fallbackCatalogUrl: `${tileBaseUrl}/catalog`,\r\n }\r\n }\r\n\r\n if (trimmed.endsWith('/catalog')) {\r\n const tileBaseUrl = trimmed.replace(/\\/catalog$/, '')\r\n return {\r\n indexUrl: `${tileBaseUrl}/tiles/index.json`,\r\n tileBaseUrl,\r\n fallbackCatalogUrl: trimmed,\r\n }\r\n }\r\n\r\n return {\r\n indexUrl: `${trimmed}/tiles/index.json`,\r\n tileBaseUrl: trimmed,\r\n fallbackCatalogUrl: `${trimmed}/catalog`,\r\n }\r\n}\r\n\r\nfunction ensureAbsoluteTileUrl(tileUrl: string, tileBaseUrl: string) {\r\n if (/^https?:\\/\\//i.test(tileUrl)) {\r\n return tileUrl\r\n }\r\n\r\n const cleanedBase = tileBaseUrl.replace(/\\/+$/, '')\r\n const cleanedPath = tileUrl.replace(/^\\/+/, '')\r\n return `${cleanedBase}/${cleanedPath}`\r\n}\r\n\r\nfunction normalizeTileInfo(tileInfo: MartinTileJson, fallbackName: string | null, tileBaseUrl: string): NormalizedMartinTile | null {\r\n const tileName = tileInfo.id || tileInfo.name || fallbackName\r\n if (!tileName) return null\r\n\r\n const vectorLayerId = tileInfo.vector_layers?.[0]?.id || tileName\r\n const tileUrlFromInfo = Array.isArray(tileInfo.tiles) && tileInfo.tiles.length > 0\r\n ? tileInfo.tiles[0]\r\n : `${tileBaseUrl}/${tileName}/{z}/{x}/{y}`\r\n\r\n return {\r\n tileName,\r\n tileUrl: ensureAbsoluteTileUrl(tileUrlFromInfo, tileBaseUrl),\r\n description: tileInfo.description || tileInfo.vector_layers?.[0]?.description,\r\n vectorLayerId,\r\n tilestats: tileInfo.tilestats,\r\n minzoom: tileInfo.minzoom || tileInfo.vector_layers?.[0]?.minzoom,\r\n }\r\n}\r\n\r\nfunction normalizeMartinCatalog(response: MartinIndexResponse, tileBaseUrl: string): NormalizedMartinTile[] {\r\n if (Array.isArray(response)) {\r\n return response\r\n .map(tile => normalizeTileInfo(tile, null, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n if ('tilesets' in response && Array.isArray(response.tilesets)) {\r\n return response.tilesets\r\n .map(tile => normalizeTileInfo(tile, null, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n if ('tiles' in response && response.tiles) {\r\n return Object.entries(response.tiles)\r\n .map(([tileName, tileInfo]) => normalizeTileInfo(tileInfo as MartinTileJson, tileName, tileBaseUrl))\r\n .filter((t): t is NormalizedMartinTile => Boolean(t))\r\n }\r\n\r\n return []\r\n}\r\n\r\nfunction parseOrganizationValue(value: unknown): number | undefined {\r\n if (value == null) return undefined\r\n if (typeof value === 'number' && Number.isFinite(value)) return value\r\n\r\n const parsed = Number.parseInt(String(value), 10)\r\n return Number.isFinite(parsed) ? parsed : undefined\r\n}\r\n\r\nfunction extractOrganizationFromTilestats(tilestats?: MartinTileStats): number | undefined {\r\n if (!tilestats?.layers) return undefined\r\n\r\n for (const layer of tilestats.layers) {\r\n const orgAttribute = layer.attributes?.find(attr =>\r\n attr.attribute?.toLowerCase() === ORGANIZATION_FIELD,\r\n )\r\n\r\n if (!orgAttribute) continue\r\n\r\n if (orgAttribute.values && orgAttribute.values.length > 0) {\r\n const value = parseOrganizationValue(orgAttribute.values[0])\r\n if (value !== undefined) return value\r\n }\r\n\r\n if (orgAttribute.min !== undefined && orgAttribute.max !== undefined) {\r\n const min = parseOrganizationValue(orgAttribute.min)\r\n const max = parseOrganizationValue(orgAttribute.max)\r\n if (min !== undefined && max !== undefined && min === max) {\r\n return min\r\n }\r\n }\r\n }\r\n\r\n return undefined\r\n}\r\n\r\nasync function fetchOrganizationFromTile(tileUrlTemplate: string, vectorLayerId: string, preferredZoom?: number) {\r\n try {\r\n const z = typeof preferredZoom === 'number' ? Math.max(0, Math.round(preferredZoom)) : 0\r\n const sampleUrl = tileUrlTemplate\r\n .replace('{z}', String(z))\r\n .replace('{x}', '0')\r\n .replace('{y}', '0')\r\n .replace('{Z}', String(z))\r\n .replace('{X}', '0')\r\n .replace('{Y}', '0')\r\n\r\n const response = await fetch(sampleUrl)\r\n if (!response.ok) return undefined\r\n\r\n const buffer = await response.arrayBuffer()\r\n const vectorTile = new VectorTile(new Pbf(buffer))\r\n const layer = vectorTile.layers[vectorLayerId] || Object.values(vectorTile.layers)[0]\r\n\r\n if (!layer || layer.length === 0) return undefined\r\n\r\n const feature = layer.feature(0)\r\n const { properties } = feature.toGeoJSON(0, 0, z)\r\n \r\n // Determine geometry type\r\n let geometryType: LayerGeometryType | undefined\r\n if (feature.type === 1) { // Point\r\n geometryType = 'circle'\r\n } else if (feature.type === 2) { // LineString\r\n geometryType = 'line'\r\n } else if (feature.type === 3) { // Polygon\r\n geometryType = 'fill'\r\n }\r\n\r\n return {\r\n organization: parseOrganizationValue(properties?.[ORGANIZATION_FIELD]),\r\n geometryType\r\n }\r\n } catch (error) {\r\n console.warn('Failed to read organization from tile', error)\r\n return undefined\r\n }\r\n}\r\n\r\nasync function resolveDatasetOrganization(tile: NormalizedMartinTile) {\r\n const fromTilestats = extractOrganizationFromTilestats(tile.tilestats)\r\n \r\n // Always fetch from tile to get geometry type, even if we have organization from tilestats\r\n const fromTile = await fetchOrganizationFromTile(tile.tileUrl, tile.vectorLayerId, tile.minzoom)\r\n \r\n return {\r\n organization: fromTilestats !== undefined ? fromTilestats : fromTile?.organization,\r\n geometryType: fromTile?.geometryType\r\n }\r\n}\r\n\r\nasync function fetchPublishedTileLabels(): Promise<Map<string, string>> {\r\n try {\r\n const res = await fetch('/api/files')\r\n if (!res.ok) return new Map()\r\n const body = await res.json()\r\n const rows: Array<{ name?: string | null, description?: string | null }> =\r\n Array.isArray(body?.files) ? body.files : []\r\n const map = new Map<string, string>()\r\n for (const row of rows) {\r\n if (!row?.description || !row?.name) continue\r\n try {\r\n const desc = JSON.parse(row.description) as { tiledTable?: unknown }\r\n if (typeof desc?.tiledTable === 'string') {\r\n map.set(desc.tiledTable, row.name.replace(/\\.geojson$/i, ''))\r\n }\r\n }\r\n catch { /* skip malformed */ }\r\n }\r\n return map\r\n }\r\n catch {\r\n return new Map()\r\n }\r\n}\r\n\r\nasync function fetchMartinServerDatasets(\r\n portal: OpenDataPortal,\r\n): Promise<Dataset[]> {\r\n const { countrySubdivision, municipality } = portal\r\n const martinServerUrl = portal.apiUrl\r\n\r\n if (!martinServerUrl) {\r\n console.warn('No Martin server URL configured for portal', portal.name)\r\n return []\r\n }\r\n\r\n try {\r\n console.log('Fetching Martin server catalog from:', martinServerUrl)\r\n\r\n const { indexUrl, tileBaseUrl, fallbackCatalogUrl } = resolveMartinUrls(martinServerUrl)\r\n\r\n const publishedLabels = await fetchPublishedTileLabels()\r\n\r\n let response = await fetch(indexUrl)\r\n if (!response.ok && fallbackCatalogUrl && fallbackCatalogUrl !== indexUrl) {\r\n console.warn(`Failed to fetch Martin index (${indexUrl}), falling back to catalog...`)\r\n response = await fetch(fallbackCatalogUrl)\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch Martin catalog: ${response.status}`)\r\n }\r\n\r\n const catalog: MartinIndexResponse = await response.json()\r\n const tiles = normalizeMartinCatalog(catalog, tileBaseUrl)\r\n // Drop our published org tables (served via the cdt_tiles function + discovered\r\n // from File metadata) and the cdt_tiles function source itself (no ?source= → empty).\r\n .filter(t => !isPublishedOrgTable(t.tileName) && t.tileName !== 'cdt_tiles')\r\n\r\n console.log('Martin catalog received:', tiles.length, 'tiles')\r\n\r\n const datasets: Dataset[] = await Promise.all(tiles.map(async (tileInfo) => {\r\n const publishedLabel = publishedLabels.get(tileInfo.tileName)\r\n const cleanName = publishedLabel ?? formatName(\r\n tileInfo.tileName\r\n .replace(/_\\d{8}$/, '')\r\n .replace(/__\\d+_\\d+$/, ''),\r\n )\r\n\r\n const { organization, geometryType } = await resolveDatasetOrganization(tileInfo)\r\n\r\n const getFields = async () => {\r\n return []\r\n }\r\n\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n return {\r\n type: 'FeatureCollection',\r\n features: [],\r\n } as AllGeoJSON\r\n }\r\n\r\n const getFeaturesData = async () => {\r\n return {\r\n id: tileInfo.tileName,\r\n name: cleanName,\r\n type: 'MVT',\r\n visible: true,\r\n clickable: true,\r\n fields: [],\r\n source: {\r\n url: tileInfo.tileUrl,\r\n description: tileInfo.description,\r\n publisher: 'Martin Server',\r\n },\r\n serviceInfo: {\r\n tileName: tileInfo.tileName,\r\n sourceLayer: tileInfo.vectorLayerId,\r\n type: 'Martin',\r\n tileUrl: tileInfo.tileUrl,\r\n },\r\n }\r\n }\r\n\r\n const dataset: Dataset = {\r\n id: tileInfo.tileName,\r\n name: cleanName,\r\n organization,\r\n publisher: 'Martin Server',\r\n dataManagementSystem: 'other',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n keywords: [],\r\n description: tileInfo.description || `Vector tile layer from Martin server: ${tileInfo.tileName}`,\r\n dateReleased: '',\r\n dateUpdated: '',\r\n information: tileInfo.tileUrl,\r\n url: tileInfo.tileUrl,\r\n countrySubdivision: countrySubdivision,\r\n municipality: municipality,\r\n type: 'MVT',\r\n datasetType: 'MVT' as any,\r\n portal,\r\n getFields,\r\n getFeatures,\r\n getFeaturesData,\r\n group: DatasetGroup.Organizational,\r\n layerColor: layerColorByName(cleanName),\r\n layerType: geometryType,\r\n }\r\n\r\n return dataset\r\n }))\r\n\r\n console.log(`Transformed ${datasets.length} Martin datasets`)\r\n\r\n let publishedDatasets: Dataset[] = []\r\n try {\r\n const fileRes = await fetch('/api/files')\r\n if (fileRes.ok) {\r\n const fileBody = await fileRes.json()\r\n const fileRows: PublishedFileRow[] = Array.isArray(fileBody?.files) ? fileBody.files : []\r\n publishedDatasets = buildPublishedTileDatasets(fileRows, tileBaseUrl, portal)\r\n }\r\n }\r\n catch (err) {\r\n console.warn('Failed to build published-tile datasets from /api/files', err)\r\n }\r\n\r\n return [...datasets, ...publishedDatasets]\r\n } catch (error) {\r\n console.error('Error fetching Martin server datasets:', error)\r\n return []\r\n }\r\n}\r\n\r\n// Fetch Local datasets from localDatasetsJson array and transform to Dataset array\r\nexport async function fetchLocalDatasets(\r\n portal: OpenDataPortal,\r\n): Promise<Dataset[]> {\r\n const { countrySubdivision, municipality } = portal\r\n const apiUrl = portal.apiUrl || ''\r\n const trimmedApiUrl = apiUrl.replace(/\\/+$/, '')\r\n\r\n if (!apiUrl) {\r\n console.warn('No apiUrl provided for portal', portal.name)\r\n return []\r\n }\r\n\r\n // Skip legacy portals with non-absolute URLs (e.g. ./localDatasets/index.json)\r\n if (!apiUrl.startsWith('http://') && !apiUrl.startsWith('https://')) {\r\n return []\r\n }\r\n\r\n if (trimmedApiUrl.includes('/catalog') || trimmedApiUrl.includes('/tiles/index')) {\r\n return fetchMartinServerDatasets(portal)\r\n }\r\n\r\n try {\r\n // Fetch the localDatasets.json file\r\n const response = await fetch(apiUrl)\r\n if (!response.ok) {\r\n const shouldTryMartinFallback =\r\n !trimmedApiUrl.endsWith('.json')\r\n && !trimmedApiUrl.includes('/catalog')\r\n && !trimmedApiUrl.includes('/tiles/index')\r\n\r\n if (response.status === 404 && shouldTryMartinFallback) {\r\n console.warn(\r\n `Local dataset URL returned 404 (${apiUrl}); retrying as a Martin server base URL`,\r\n )\r\n return fetchMartinServerDatasets({\r\n ...portal,\r\n apiUrl: trimmedApiUrl,\r\n })\r\n }\r\n\r\n throw new Error(`Failed to fetch local datasets from ${apiUrl}: ${response.status}`)\r\n }\r\n\r\n const localDatasetsJson: LocalDatasetItem[] = await response.json()\r\n\r\n const transformedDatasets: Dataset[] = localDatasetsJson.map((datasetItem: LocalDatasetItem) => {\r\n // Simple getFields function that returns fields from layer properties\r\n const getFields = async () => {\r\n if (datasetItem.layer?.properties) {\r\n return Object.entries(datasetItem.layer.properties).map(([name, type]) => ({\r\n name,\r\n label: formatName(name),\r\n type: type as string,\r\n description: `${formatName(name)} field`,\r\n }))\r\n }\r\n return []\r\n }\r\n\r\n // Fetch GeoJSON data from the featuresUrl\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n // Create a cache key based on the dataset name and features URL\r\n const featuresKey = `features:local:${datasetItem.name}:${datasetItem.featuresUrl}`\r\n \r\n // Check cache first\r\n const cachedFeatures = getCache<AllGeoJSON>(featuresKey)\r\n if (cachedFeatures) {\r\n return cachedFeatures\r\n }\r\n \r\n try {\r\n // Use the featuresUrl from the dataset item\r\n let geojsonUrl: string\r\n if (datasetItem.featuresUrl.startsWith('http://') || datasetItem.featuresUrl.startsWith('https://')) {\r\n geojsonUrl = datasetItem.featuresUrl\r\n } else {\r\n const baseUrl = apiUrl.endsWith('.json') \r\n ? apiUrl.substring(0, apiUrl.lastIndexOf('/'))\r\n : apiUrl\r\n geojsonUrl = `${baseUrl}/${datasetItem.featuresUrl}`\r\n }\r\n\r\n const response = await fetch(geojsonUrl)\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch GeoJSON: ${response.status}`)\r\n }\r\n\r\n const geojsonData = await response.json() as AllGeoJSON\r\n \r\n // Cache for 1 hour\r\n setCache(featuresKey, geojsonData, 60 * 60 * 1000)\r\n \r\n return geojsonData\r\n } catch (error) {\r\n console.error(`Error loading GeoJSON for ${datasetItem.name}:`, error)\r\n return {\r\n type: 'FeatureCollection',\r\n features: [],\r\n } as AllGeoJSON\r\n }\r\n }\r\n\r\n const name = formatName(datasetItem.name)\r\n\r\n const getFeaturesData = async () => {\r\n try {\r\n return {\r\n // Basic layer information\r\n id: datasetItem.tileName || datasetItem.name.toLowerCase().replace(/\\s+/g, '-'),\r\n name: datasetItem.name,\r\n type: datasetItem.layer?.type || 'GeoJSON',\r\n\r\n // Layer configuration\r\n visible: datasetItem.visible,\r\n clickable: datasetItem.clickable,\r\n\r\n // Field information (similar to ArcGIS fields structure)\r\n fields: datasetItem.layer?.properties\r\n ? Object.entries(datasetItem.layer.properties).map(([name, type]) => ({\r\n name,\r\n type: type as FieldType,\r\n alias: formatName(name),\r\n description: `${formatName(name)} field`,\r\n }))\r\n : [],\r\n\r\n // Source information\r\n source: {\r\n url: datasetItem.url,\r\n description: datasetItem.description,\r\n publisher: datasetItem.publisher,\r\n featuresUrl: datasetItem.featuresUrl,\r\n },\r\n\r\n // Additional metadata that DatasetDetails.tsx might use\r\n editingInfo: {\r\n lastEditDate: new Date().toISOString(), // Current date as placeholder\r\n dataLastEditDate: new Date().toISOString(),\r\n },\r\n\r\n // Layer properties summary\r\n properties: datasetItem.layer?.properties || {},\r\n fieldCount: datasetItem.layer?.properties ? Object.keys(datasetItem.layer.properties).length : 0,\r\n\r\n // Geometry information\r\n geometryType: 'Unknown', // You could infer this from the actual GeoJSON if needed\r\n\r\n // Service information (for compatibility)\r\n serviceInfo: {\r\n tileName: datasetItem.tileName,\r\n sourceLayer: datasetItem.sourceLayer,\r\n type: 'Local',\r\n },\r\n }\r\n } catch (error) {\r\n console.error('Error getting features data for dataset:', datasetItem.name, error)\r\n return null\r\n }\r\n }\r\n\r\n return {\r\n id: datasetItem.tileName || datasetItem.name.toLowerCase().replace(/\\s+/g, '-'),\r\n name,\r\n organization: datasetItem.organization || 0,\r\n publisher: datasetItem.publisher || 'Unknown',\r\n dataManagementSystem: 'other',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n keywords: [],\r\n description: datasetItem.description || 'No description available',\r\n dateReleased: '',\r\n dateUpdated: '',\r\n information: datasetItem.url || '',\r\n url: datasetItem.url || '#', // Ensure there's always a valid URL for the Link component\r\n countrySubdivision: datasetItem.countrySubdivision || countrySubdivision,\r\n municipality: datasetItem.municipality || municipality,\r\n type: datasetItem.layer?.type || 'GeoJSON',\r\n datasetType: 'GeoJSON' as const,\r\n portal,\r\n getFields,\r\n getFeatures,\r\n getFeaturesData,\r\n group: 'Organizational',\r\n layerColor: layerColorByName(name),\r\n }\r\n })\r\n\r\n return transformedDatasets\r\n } catch (error) {\r\n console.error('Error fetching local datasets:', error)\r\n return []\r\n }\r\n}\r\n"],"mappings":"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","names":["_a","name","response"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Dataset } from '../../../../../types/datasetTypes';
|
|
2
|
-
export declare function fetchOrganizationalMinioDatasets(organizationId: number): Promise<Dataset[]>;
|
|
2
|
+
export declare function fetchOrganizationalMinioDatasets(organizationId: number, publishedTilesInCatalog?: ReadonlySet<string>): Promise<Dataset[]>;
|
|
3
3
|
//# sourceMappingURL=minioDatasets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"minioDatasets.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/src/minioDatasets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"minioDatasets.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/src/minioDatasets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAmDhE,wBAAsB,gCAAgC,CACpD,cAAc,EAAE,MAAM,EACtB,uBAAuB,GAAE,WAAW,CAAC,MAAM,CAAa,GACvD,OAAO,CAAC,OAAO,EAAE,CAAC,CAmFpB"}
|
|
@@ -15,7 +15,7 @@ function buildMinioUrl(bucket, organizationId, assetId) {
|
|
|
15
15
|
if (!base) return null;
|
|
16
16
|
return `${base.replace(/\/+$/, "")}/${bucket}/${organizationId}/${assetId}`;
|
|
17
17
|
}
|
|
18
|
-
async function fetchOrganizationalMinioDatasets(organizationId) {
|
|
18
|
+
async function fetchOrganizationalMinioDatasets(organizationId, publishedTilesInCatalog = /* @__PURE__ */ new Set()) {
|
|
19
19
|
var _a, _b;
|
|
20
20
|
let rows = [];
|
|
21
21
|
try {
|
|
@@ -36,6 +36,7 @@ async function fetchOrganizationalMinioDatasets(organizationId) {
|
|
|
36
36
|
if (row.tag !== TAG) continue;
|
|
37
37
|
if (!row.assetId) continue;
|
|
38
38
|
const meta = parseDescription(row.description);
|
|
39
|
+
if ((meta == null ? void 0 : meta.tiledTable) && publishedTilesInCatalog.has(meta.tiledTable)) continue;
|
|
39
40
|
const bucket = meta == null ? void 0 : meta.bucket;
|
|
40
41
|
if (!bucket) continue;
|
|
41
42
|
const sourceUrl = buildMinioUrl(bucket, organizationId, row.assetId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/src/minioDatasets.ts"],"sourcesContent":["import type { Dataset } from '../../../../../types/datasetTypes'\r\nimport { DatasetGroup } from '../../../../../types/dbTypes'\r\nimport { layerColorByName } from '../../utils/stringToColour'\r\nimport type { AllGeoJSON } from '@turf/turf'\r\n\r\n/**\r\n * Hydrates uploaded GeoJSON datasets persisted via \"Add Dataset\". Looks up\r\n * File rows tagged `organizational-dataset`, reads the bucket from each row's\r\n * description JSON, and builds Dataset entries whose `getFeatures` lazy-loads\r\n * the GeoJSON from MinIO on first render.\r\n */\r\n\r\ninterface OrgDatasetDescription {\r\n bucket?: string\r\n geometryType?: 'points' | 'lines' | 'polygons'\r\n layerStyles?: Record<string, Record<string, string | number>>\r\n}\r\n\r\ninterface RawFileRow {\r\n id: number\r\n type?: string | null\r\n tag?: string | null\r\n name?: string | null\r\n assetId?: string | null\r\n description?: string | null\r\n uploadedAt?: string | Date | null\r\n}\r\n\r\nconst TAG = 'organizational-dataset'\r\n\r\nfunction parseDescription(value: string | null | undefined): OrgDatasetDescription | null {\r\n if (!value) return null\r\n try {\r\n const parsed = JSON.parse(value)\r\n return typeof parsed === 'object' && parsed !== null ? parsed as OrgDatasetDescription : null\r\n }\r\n catch {\r\n return null\r\n }\r\n}\r\n\r\nfunction buildMinioUrl(bucket: string, organizationId: number, assetId: string): string | null {\r\n const base = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL\r\n if (!base) return null\r\n return `${base.replace(/\\/+$/, '')}/${bucket}/${organizationId}/${assetId}`\r\n}\r\n\r\nexport async function fetchOrganizationalMinioDatasets(\r\n organizationId: number,\r\n): Promise<Dataset[]> {\r\n let rows: RawFileRow[] = []\r\n try {\r\n const res = await fetch('/api/files')\r\n if (!res.ok) {\r\n console.warn(`fetchOrganizationalMinioDatasets: /api/files returned ${res.status}`)\r\n return []\r\n }\r\n const body = await res.json()\r\n rows = Array.isArray(body?.files) ? body.files : []\r\n }\r\n catch (err) {\r\n console.warn('fetchOrganizationalMinioDatasets: /api/files request failed', err)\r\n return []\r\n }\r\n\r\n const datasets: Dataset[] = []\r\n for (const row of rows) {\r\n if (row.type !== 'map-file') continue\r\n if (row.tag !== TAG) continue\r\n if (!row.assetId) continue\r\n\r\n const meta = parseDescription(row.description)\r\n const bucket = meta?.bucket\r\n if (!bucket) continue\r\n\r\n const sourceUrl = buildMinioUrl(bucket, organizationId, row.assetId)\r\n if (!sourceUrl) continue\r\n\r\n const name = row.name?.replace(/\\.geojson$/i, '') || `Dataset ${row.id}`\r\n const id = `org-minio-${row.id}`\r\n let cached: AllGeoJSON | null = null\r\n\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n if (cached) return cached\r\n const response = await fetch(sourceUrl)\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch GeoJSON from ${sourceUrl}: ${response.status}`)\r\n }\r\n cached = await response.json() as AllGeoJSON\r\n return cached\r\n }\r\n\r\n const getFields = async () => []\r\n\r\n datasets.push({\r\n id,\r\n name,\r\n type: 'Organizational',\r\n publisher: 'Organizational',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n description: `Uploaded ${row.uploadedAt ?? ''}`.trim(),\r\n dateReleased: typeof row.uploadedAt === 'string' ? row.uploadedAt : '',\r\n dateUpdated: typeof row.uploadedAt === 'string' ? row.uploadedAt : '',\r\n countrySubdivision: '',\r\n municipality: '',\r\n sourceUrl,\r\n url: sourceUrl,\r\n clickable: true,\r\n properties: {},\r\n getFeatures,\r\n getFields,\r\n dataManagementSystem: 'other',\r\n datasetType: 'GeoJSON',\r\n group: DatasetGroup.Organizational,\r\n layerColor: layerColorByName(id),\r\n layerType: meta?.geometryType === 'lines'\r\n ? 'line'\r\n : meta?.geometryType === 'points'\r\n ? 'circle'\r\n : meta?.geometryType === 'polygons'\r\n ? 'fill'\r\n : undefined,\r\n })\r\n }\r\n\r\n return datasets\r\n}\r\n"],"mappings":"AACA,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/src/minioDatasets.ts"],"sourcesContent":["import type { Dataset } from '../../../../../types/datasetTypes'\r\nimport { DatasetGroup } from '../../../../../types/dbTypes'\r\nimport { layerColorByName } from '../../utils/stringToColour'\r\nimport type { AllGeoJSON } from '@turf/turf'\r\n\r\n/**\r\n * Hydrates uploaded GeoJSON datasets persisted via \"Add Dataset\". Looks up\r\n * File rows tagged `organizational-dataset`, reads the bucket from each row's\r\n * description JSON, and builds Dataset entries whose `getFeatures` lazy-loads\r\n * the GeoJSON from MinIO on first render.\r\n */\r\n\r\ninterface OrgDatasetDescription {\r\n bucket?: string\r\n geometryType?: 'points' | 'lines' | 'polygons'\r\n layerStyles?: Record<string, Record<string, string | number>>\r\n tiledTable?: string\r\n tiledAt?: string\r\n featuresIngested?: number\r\n featuresSkipped?: number\r\n}\r\n\r\ninterface RawFileRow {\r\n id: number\r\n type?: string | null\r\n tag?: string | null\r\n name?: string | null\r\n assetId?: string | null\r\n description?: string | null\r\n uploadedAt?: string | Date | null\r\n}\r\n\r\nconst TAG = 'organizational-dataset'\r\n\r\nfunction parseDescription(value: string | null | undefined): OrgDatasetDescription | null {\r\n if (!value) return null\r\n try {\r\n const parsed = JSON.parse(value)\r\n return typeof parsed === 'object' && parsed !== null ? parsed as OrgDatasetDescription : null\r\n }\r\n catch {\r\n return null\r\n }\r\n}\r\n\r\nfunction buildMinioUrl(bucket: string, organizationId: number, assetId: string): string | null {\r\n const base = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL\r\n if (!base) return null\r\n return `${base.replace(/\\/+$/, '')}/${bucket}/${organizationId}/${assetId}`\r\n}\r\n\r\nexport async function fetchOrganizationalMinioDatasets(\r\n organizationId: number,\r\n publishedTilesInCatalog: ReadonlySet<string> = new Set(),\r\n): Promise<Dataset[]> {\r\n let rows: RawFileRow[] = []\r\n try {\r\n const res = await fetch('/api/files')\r\n if (!res.ok) {\r\n console.warn(`fetchOrganizationalMinioDatasets: /api/files returned ${res.status}`)\r\n return []\r\n }\r\n const body = await res.json()\r\n rows = Array.isArray(body?.files) ? body.files : []\r\n }\r\n catch (err) {\r\n console.warn('fetchOrganizationalMinioDatasets: /api/files request failed', err)\r\n return []\r\n }\r\n\r\n const datasets: Dataset[] = []\r\n for (const row of rows) {\r\n if (row.type !== 'map-file') continue\r\n if (row.tag !== TAG) continue\r\n if (!row.assetId) continue\r\n\r\n const meta = parseDescription(row.description)\r\n // Suppress the MinIO entry only once Martin actually serves the published\r\n // table — otherwise the file appears to vanish during the publish→restart\r\n // gap. Un-publish drops the table immediately, so the MinIO row reappears\r\n // on next reload with no extra plumbing.\r\n if (meta?.tiledTable && publishedTilesInCatalog.has(meta.tiledTable)) continue\r\n const bucket = meta?.bucket\r\n if (!bucket) continue\r\n\r\n const sourceUrl = buildMinioUrl(bucket, organizationId, row.assetId)\r\n if (!sourceUrl) continue\r\n\r\n const name = row.name?.replace(/\\.geojson$/i, '') || `Dataset ${row.id}`\r\n const id = `org-minio-${row.id}`\r\n let cached: AllGeoJSON | null = null\r\n\r\n const getFeatures = async (): Promise<AllGeoJSON> => {\r\n if (cached) return cached\r\n const response = await fetch(sourceUrl)\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch GeoJSON from ${sourceUrl}: ${response.status}`)\r\n }\r\n cached = await response.json() as AllGeoJSON\r\n return cached\r\n }\r\n\r\n const getFields = async () => []\r\n\r\n datasets.push({\r\n id,\r\n name,\r\n type: 'Organizational',\r\n publisher: 'Organizational',\r\n license: 'Unknown',\r\n contact: 'Unknown',\r\n description: `Uploaded ${row.uploadedAt ?? ''}`.trim(),\r\n dateReleased: typeof row.uploadedAt === 'string' ? row.uploadedAt : '',\r\n dateUpdated: typeof row.uploadedAt === 'string' ? row.uploadedAt : '',\r\n countrySubdivision: '',\r\n municipality: '',\r\n sourceUrl,\r\n url: sourceUrl,\r\n clickable: true,\r\n properties: {},\r\n getFeatures,\r\n getFields,\r\n dataManagementSystem: 'other',\r\n datasetType: 'GeoJSON',\r\n group: DatasetGroup.Organizational,\r\n layerColor: layerColorByName(id),\r\n layerType: meta?.geometryType === 'lines'\r\n ? 'line'\r\n : meta?.geometryType === 'points'\r\n ? 'circle'\r\n : meta?.geometryType === 'polygons'\r\n ? 'fill'\r\n : undefined,\r\n })\r\n }\r\n\r\n return datasets\r\n}\r\n"],"mappings":"AACA,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AA8BjC,MAAM,MAAM;AAEZ,SAAS,iBAAiB,OAAgE;AACxF,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,WAAO,OAAO,WAAW,YAAY,WAAW,OAAO,SAAkC;AAAA,EAC3F,SACM;AACJ,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,QAAgB,gBAAwB,SAAgC;AAC7F,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,GAAG,KAAK,QAAQ,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,cAAc,IAAI,OAAO;AAC3E;AAEA,eAAsB,iCACpB,gBACA,0BAA+C,oBAAI,IAAI,GACnC;AAtDtB;AAuDE,MAAI,OAAqB,CAAC;AAC1B,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,YAAY;AACpC,QAAI,CAAC,IAAI,IAAI;AACX,cAAQ,KAAK,yDAAyD,IAAI,MAAM,EAAE;AAClF,aAAO,CAAC;AAAA,IACV;AACA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,MAAM,QAAQ,6BAAM,KAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,EACpD,SACO,KAAK;AACV,YAAQ,KAAK,+DAA+D,GAAG;AAC/E,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAsB,CAAC;AAC7B,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,SAAS,WAAY;AAC7B,QAAI,IAAI,QAAQ,IAAK;AACrB,QAAI,CAAC,IAAI,QAAS;AAElB,UAAM,OAAO,iBAAiB,IAAI,WAAW;AAK7C,SAAI,6BAAM,eAAc,wBAAwB,IAAI,KAAK,UAAU,EAAG;AACtE,UAAM,SAAS,6BAAM;AACrB,QAAI,CAAC,OAAQ;AAEb,UAAM,YAAY,cAAc,QAAQ,gBAAgB,IAAI,OAAO;AACnE,QAAI,CAAC,UAAW;AAEhB,UAAM,SAAO,SAAI,SAAJ,mBAAU,QAAQ,eAAe,QAAO,WAAW,IAAI,EAAE;AACtE,UAAM,KAAK,aAAa,IAAI,EAAE;AAC9B,QAAI,SAA4B;AAEhC,UAAM,cAAc,YAAiC;AACnD,UAAI,OAAQ,QAAO;AACnB,YAAM,WAAW,MAAM,MAAM,SAAS;AACtC,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,gCAAgC,SAAS,KAAK,SAAS,MAAM,EAAE;AAAA,MACjF;AACA,eAAS,MAAM,SAAS,KAAK;AAC7B,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,YAAY,CAAC;AAE/B,aAAS,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,WAAW;AAAA,MACX,SAAS;AAAA,MACT,SAAS;AAAA,MACT,aAAa,aAAY,SAAI,eAAJ,YAAkB,EAAE,GAAG,KAAK;AAAA,MACrD,cAAc,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,MACpE,aAAa,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,MACnE,oBAAoB;AAAA,MACpB,cAAc;AAAA,MACd;AAAA,MACA,KAAK;AAAA,MACL,WAAW;AAAA,MACX,YAAY,CAAC;AAAA,MACb;AAAA,MACA;AAAA,MACA,sBAAsB;AAAA,MACtB,aAAa;AAAA,MACb,OAAO,aAAa;AAAA,MACpB,YAAY,iBAAiB,EAAE;AAAA,MAC/B,YAAW,6BAAM,kBAAiB,UAC9B,UACA,6BAAM,kBAAiB,WACrB,YACA,6BAAM,kBAAiB,aACrB,SACA;AAAA,IACV,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Dataset } from '../../../../../types/datasetTypes';
|
|
2
|
+
import { type OpenDataPortal } from '../../../../../types/dbTypes';
|
|
3
|
+
/** Tables our publish pipeline creates; served via the cdt_tiles function source. */
|
|
4
|
+
export declare function isPublishedOrgTable(name: string): boolean;
|
|
5
|
+
/** What a published open-data dataset resolves to: its Martin table + backing File row. */
|
|
6
|
+
export interface PublishedCatalogEntry {
|
|
7
|
+
fileId: number;
|
|
8
|
+
table: string;
|
|
9
|
+
geometryType?: string;
|
|
10
|
+
}
|
|
11
|
+
interface CatalogFileRow {
|
|
12
|
+
id?: number | null;
|
|
13
|
+
assetId?: string | null;
|
|
14
|
+
description?: string | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a lookup from `/api/files` of open-data datasets that have already been
|
|
18
|
+
* published to Martin tiles, keyed by `"{portalId}:{datasetId}"` — the identity
|
|
19
|
+
* of the *original* portal dataset.
|
|
20
|
+
*
|
|
21
|
+
* Catalog publishes mint a File whose `assetId` is `odp:{portalId}:{datasetId}`
|
|
22
|
+
* and whose description carries `portalId`/`datasetId` + `tiledTable`. The
|
|
23
|
+
* original portal entry (shown on the National/Applied/All tabs) keeps its own
|
|
24
|
+
* id, so without this map those tabs cannot tell the dataset is already tiled.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildPublishedCatalogMap(rows: CatalogFileRow[]): Map<string, PublishedCatalogEntry>;
|
|
27
|
+
/**
|
|
28
|
+
* Tag any dataset whose `portal.id:id` is in the published-catalog map with the
|
|
29
|
+
* `publishedTable`/`publishedFileId` it resolves to, so RowActions renders it as
|
|
30
|
+
* converted (and can un-publish it) wherever it appears — not only on the
|
|
31
|
+
* organizational tab, which is the one place that holds the tiled representation.
|
|
32
|
+
* Datasets that aren't published, or have no portal/id, are returned unchanged.
|
|
33
|
+
*/
|
|
34
|
+
export declare function stampPublished(datasets: Dataset[], map: Map<string, PublishedCatalogEntry>): Dataset[];
|
|
35
|
+
export interface PublishedFileRow {
|
|
36
|
+
name?: string | null;
|
|
37
|
+
description?: string | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build MVT Dataset entries for published tiles from File-row metadata (/api/files),
|
|
41
|
+
* pointing each at the cdt_tiles function source. The renderer derives source-layer from
|
|
42
|
+
* dataset.id (= the table name = the MVT layer name the function emits), so no serviceInfo
|
|
43
|
+
* is needed. layerType comes from the geometryType stamped at publish time.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildPublishedTileDatasets(rows: PublishedFileRow[], tileBaseUrl: string, portal: OpenDataPortal): Dataset[];
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=publishedTiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publishedTiles.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/src/publishedTiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,mCAAmC,CAAA;AACnF,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAIhF,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,UAAU,cAAc;IACtB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CA2BnG;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,GAAG,OAAO,EAAE,CAStG;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,gBAAgB,EAAE,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,GACrB,OAAO,EAAE,CAwCX"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
import { DatasetGroup } from "../../../../../types/dbTypes";
|
|
21
|
+
import { layerColorByName } from "../../utils/stringToColour";
|
|
22
|
+
function isPublishedOrgTable(name) {
|
|
23
|
+
return /^org_\d+_file_\d+$/.test(name);
|
|
24
|
+
}
|
|
25
|
+
function buildPublishedCatalogMap(rows) {
|
|
26
|
+
const map = /* @__PURE__ */ new Map();
|
|
27
|
+
for (const row of rows) {
|
|
28
|
+
if (typeof (row == null ? void 0 : row.id) !== "number" || !row.description) continue;
|
|
29
|
+
let desc;
|
|
30
|
+
try {
|
|
31
|
+
desc = JSON.parse(row.description);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (desc.source !== "open-data-portal") continue;
|
|
36
|
+
const table = typeof desc.tiledTable === "string" ? desc.tiledTable : null;
|
|
37
|
+
if (!table) continue;
|
|
38
|
+
let portalId = typeof desc.portalId === "number" ? String(desc.portalId) : null;
|
|
39
|
+
let datasetId = typeof desc.datasetId === "string" ? desc.datasetId : null;
|
|
40
|
+
if ((!portalId || !datasetId) && typeof row.assetId === "string") {
|
|
41
|
+
const m = /^odp:([^:]+):(.+)$/.exec(row.assetId);
|
|
42
|
+
if (m) {
|
|
43
|
+
portalId = portalId != null ? portalId : m[1];
|
|
44
|
+
datasetId = datasetId != null ? datasetId : m[2];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!portalId || !datasetId) continue;
|
|
48
|
+
map.set(`${portalId}:${datasetId}`, {
|
|
49
|
+
fileId: row.id,
|
|
50
|
+
table,
|
|
51
|
+
geometryType: typeof desc.geometryType === "string" ? desc.geometryType : void 0
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return map;
|
|
55
|
+
}
|
|
56
|
+
function stampPublished(datasets, map) {
|
|
57
|
+
if (map.size === 0) return datasets;
|
|
58
|
+
return datasets.map((d) => {
|
|
59
|
+
var _a;
|
|
60
|
+
const portalId = (_a = d.portal) == null ? void 0 : _a.id;
|
|
61
|
+
if (portalId == null || d.id == null) return d;
|
|
62
|
+
const entry = map.get(`${portalId}:${d.id}`);
|
|
63
|
+
if (!entry) return d;
|
|
64
|
+
return __spreadProps(__spreadValues({}, d), { publishedTable: entry.table, publishedFileId: entry.fileId });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function buildPublishedTileDatasets(rows, tileBaseUrl, portal) {
|
|
68
|
+
var _a, _b, _c;
|
|
69
|
+
const base = tileBaseUrl.replace(/\/+$/, "");
|
|
70
|
+
const out = [];
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
if (!(row == null ? void 0 : row.description)) continue;
|
|
73
|
+
let desc;
|
|
74
|
+
try {
|
|
75
|
+
desc = JSON.parse(row.description);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const table = typeof desc.tiledTable === "string" ? desc.tiledTable : null;
|
|
80
|
+
if (!table) continue;
|
|
81
|
+
const name = ((_a = row.name) != null ? _a : table).replace(/\.geojson$/i, "");
|
|
82
|
+
const layerType = typeof desc.geometryType === "string" ? desc.geometryType : void 0;
|
|
83
|
+
const tileUrl = `${base}/cdt_tiles/{z}/{x}/{y}?source=${table}`;
|
|
84
|
+
const getFields = async () => [];
|
|
85
|
+
const getFeatures = async () => ({ type: "FeatureCollection", features: [] });
|
|
86
|
+
out.push({
|
|
87
|
+
id: table,
|
|
88
|
+
name,
|
|
89
|
+
publisher: "Martin Server",
|
|
90
|
+
dataManagementSystem: "other",
|
|
91
|
+
description: `Published vector tile layer: ${table}`,
|
|
92
|
+
countrySubdivision: (_b = portal.countrySubdivision) != null ? _b : "",
|
|
93
|
+
municipality: (_c = portal.municipality) != null ? _c : "",
|
|
94
|
+
type: "MVT",
|
|
95
|
+
datasetType: "MVT",
|
|
96
|
+
url: tileUrl,
|
|
97
|
+
information: tileUrl,
|
|
98
|
+
portal,
|
|
99
|
+
group: DatasetGroup.Organizational,
|
|
100
|
+
layerColor: layerColorByName(name),
|
|
101
|
+
layerType,
|
|
102
|
+
getFields,
|
|
103
|
+
getFeatures
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
buildPublishedCatalogMap,
|
|
110
|
+
buildPublishedTileDatasets,
|
|
111
|
+
isPublishedOrgTable,
|
|
112
|
+
stampPublished
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=publishedTiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/src/publishedTiles.ts"],"sourcesContent":["import type { Dataset, LayerGeometryType } from '../../../../../types/datasetTypes'\r\nimport { DatasetGroup, type OpenDataPortal } from '../../../../../types/dbTypes'\r\nimport type { AllGeoJSON } from '@turf/turf'\r\nimport { layerColorByName } from '../../utils/stringToColour'\r\n\r\n/** Tables our publish pipeline creates; served via the cdt_tiles function source. */\r\nexport function isPublishedOrgTable(name: string): boolean {\r\n return /^org_\\d+_file_\\d+$/.test(name)\r\n}\r\n\r\n/** What a published open-data dataset resolves to: its Martin table + backing File row. */\r\nexport interface PublishedCatalogEntry {\r\n fileId: number\r\n table: string\r\n geometryType?: string\r\n}\r\n\r\ninterface CatalogFileRow {\r\n id?: number | null\r\n assetId?: string | null\r\n description?: string | null\r\n}\r\n\r\n/**\r\n * Build a lookup from `/api/files` of open-data datasets that have already been\r\n * published to Martin tiles, keyed by `\"{portalId}:{datasetId}\"` — the identity\r\n * of the *original* portal dataset.\r\n *\r\n * Catalog publishes mint a File whose `assetId` is `odp:{portalId}:{datasetId}`\r\n * and whose description carries `portalId`/`datasetId` + `tiledTable`. The\r\n * original portal entry (shown on the National/Applied/All tabs) keeps its own\r\n * id, so without this map those tabs cannot tell the dataset is already tiled.\r\n */\r\nexport function buildPublishedCatalogMap(rows: CatalogFileRow[]): Map<string, PublishedCatalogEntry> {\r\n const map = new Map<string, PublishedCatalogEntry>()\r\n for (const row of rows) {\r\n if (typeof row?.id !== 'number' || !row.description) continue\r\n let desc: { source?: unknown, portalId?: unknown, datasetId?: unknown, tiledTable?: unknown, geometryType?: unknown }\r\n try { desc = JSON.parse(row.description) }\r\n catch { continue }\r\n if (desc.source !== 'open-data-portal') continue\r\n const table = typeof desc.tiledTable === 'string' ? desc.tiledTable : null\r\n if (!table) continue\r\n\r\n // Prefer the structured fields; fall back to parsing the synthetic assetId.\r\n let portalId = typeof desc.portalId === 'number' ? String(desc.portalId) : null\r\n let datasetId = typeof desc.datasetId === 'string' ? desc.datasetId : null\r\n if ((!portalId || !datasetId) && typeof row.assetId === 'string') {\r\n const m = /^odp:([^:]+):(.+)$/.exec(row.assetId)\r\n if (m) { portalId = portalId ?? m[1]; datasetId = datasetId ?? m[2] }\r\n }\r\n if (!portalId || !datasetId) continue\r\n\r\n map.set(`${portalId}:${datasetId}`, {\r\n fileId: row.id,\r\n table,\r\n geometryType: typeof desc.geometryType === 'string' ? desc.geometryType : undefined,\r\n })\r\n }\r\n return map\r\n}\r\n\r\n/**\r\n * Tag any dataset whose `portal.id:id` is in the published-catalog map with the\r\n * `publishedTable`/`publishedFileId` it resolves to, so RowActions renders it as\r\n * converted (and can un-publish it) wherever it appears — not only on the\r\n * organizational tab, which is the one place that holds the tiled representation.\r\n * Datasets that aren't published, or have no portal/id, are returned unchanged.\r\n */\r\nexport function stampPublished(datasets: Dataset[], map: Map<string, PublishedCatalogEntry>): Dataset[] {\r\n if (map.size === 0) return datasets\r\n return datasets.map((d) => {\r\n const portalId = d.portal?.id\r\n if (portalId == null || d.id == null) return d\r\n const entry = map.get(`${portalId}:${d.id}`)\r\n if (!entry) return d\r\n return { ...d, publishedTable: entry.table, publishedFileId: entry.fileId }\r\n })\r\n}\r\n\r\nexport interface PublishedFileRow {\r\n name?: string | null\r\n description?: string | null\r\n}\r\n\r\n/**\r\n * Build MVT Dataset entries for published tiles from File-row metadata (/api/files),\r\n * pointing each at the cdt_tiles function source. The renderer derives source-layer from\r\n * dataset.id (= the table name = the MVT layer name the function emits), so no serviceInfo\r\n * is needed. layerType comes from the geometryType stamped at publish time.\r\n */\r\nexport function buildPublishedTileDatasets(\r\n rows: PublishedFileRow[],\r\n tileBaseUrl: string,\r\n portal: OpenDataPortal,\r\n): Dataset[] {\r\n const base = tileBaseUrl.replace(/\\/+$/, '')\r\n const out: Dataset[] = []\r\n for (const row of rows) {\r\n if (!row?.description) continue\r\n let desc: { tiledTable?: unknown, geometryType?: unknown }\r\n try { desc = JSON.parse(row.description) }\r\n catch { continue }\r\n const table = typeof desc.tiledTable === 'string' ? desc.tiledTable : null\r\n if (!table) continue\r\n\r\n const name = (row.name ?? table).replace(/\\.geojson$/i, '')\r\n const layerType = (typeof desc.geometryType === 'string' ? desc.geometryType : undefined) as LayerGeometryType | undefined\r\n const tileUrl = `${base}/cdt_tiles/{z}/{x}/{y}?source=${table}`\r\n\r\n const getFields = async () => []\r\n const getFeatures = async (): Promise<AllGeoJSON> =>\r\n ({ type: 'FeatureCollection', features: [] } as AllGeoJSON)\r\n\r\n out.push({\r\n id: table,\r\n name,\r\n publisher: 'Martin Server',\r\n dataManagementSystem: 'other',\r\n description: `Published vector tile layer: ${table}`,\r\n countrySubdivision: portal.countrySubdivision ?? '',\r\n municipality: portal.municipality ?? '',\r\n type: 'MVT',\r\n datasetType: 'MVT',\r\n url: tileUrl,\r\n information: tileUrl,\r\n portal,\r\n group: DatasetGroup.Organizational,\r\n layerColor: layerColorByName(name),\r\n layerType,\r\n getFields,\r\n getFeatures,\r\n } as Dataset)\r\n }\r\n return out\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic WMS-T (time dimension) helpers for animating WMS raster overlays.
|
|
3
|
+
*
|
|
4
|
+
* Generalized from the radar-specific helpers (RadarLayer/geomet.ts): any WMS
|
|
5
|
+
* layer with an ISO8601 TIME dimension can be expanded into frames and animated
|
|
6
|
+
* by swapping the GetMap TIME param. Data stays federated — the browser fetches
|
|
7
|
+
* raster tiles directly; nothing is ingested or stored here.
|
|
8
|
+
*/
|
|
9
|
+
/** Parse an ISO8601 duration (`PT6M`, `PT1H30M`, `P1DT12H`) into ms. 0 if unparseable. */
|
|
10
|
+
export declare function parseIso8601DurationMs(iso: string): number;
|
|
11
|
+
/**
|
|
12
|
+
* Expand a WMS-T `start/end/interval` extent into ascending frame timestamps
|
|
13
|
+
* (oldest → newest). Falls back to `[start]` if the interval can't be parsed,
|
|
14
|
+
* `[]` if start itself is invalid. Capped at `maxFrames` (keeps the newest).
|
|
15
|
+
*/
|
|
16
|
+
export declare function expandTimeRange(startIso: string, endIso: string, intervalIso: string, maxFrames?: number): string[];
|
|
17
|
+
export interface WmsTimeExtent {
|
|
18
|
+
/** Ascending frame timestamps (oldest → newest). Empty when no time dimension found. */
|
|
19
|
+
frames: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pull the `<Dimension name="time">` out of a (layer-scoped) WMS GetCapabilities
|
|
23
|
+
* document and expand it to frame timestamps. Handles the `start/end/interval`
|
|
24
|
+
* form and a bare comma-separated list as a fallback.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseTimeExtent(xml: string, maxFrames?: number): WmsTimeExtent;
|
|
27
|
+
/** Short local-time label for a frame timestamp (e.g. "3:42 PM"). */
|
|
28
|
+
export declare function formatFrameTime(iso: string): string;
|
|
29
|
+
/** Layer-scoped GetCapabilities URL — returns a small XML payload with the live time extent. */
|
|
30
|
+
export declare function wmsCapabilitiesUrl(baseUrl: string, layers: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Build a WMS GetLegendGraphic URL — the server-rendered legend image (colour
|
|
33
|
+
* ramp + labels) for the layer's default style. No STYLE param, so it matches
|
|
34
|
+
* the default-style tiles `buildWmsTimeUrl` requests (STYLES='').
|
|
35
|
+
*/
|
|
36
|
+
export declare function wmsLegendUrl(baseUrl: string, layers: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Build a MapLibre raster tile-URL template for a WMS GetMap request at a given
|
|
39
|
+
* TIME. `{bbox-epsg-3857}` must stay literal — MapLibre substitutes it per tile.
|
|
40
|
+
* Mirrors `buildWmsTileUrl` (WMS 1.1.1 + SRS=EPSG:3857) with TIME added.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildWmsTimeUrl(baseUrl: string, layers: string, time: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Fetch a layer-scoped GetCapabilities document and return its time frames.
|
|
45
|
+
* Thin network wrapper — returns `[]` on any failure so callers can simply
|
|
46
|
+
* render no control (the static latest-frame raster keeps working).
|
|
47
|
+
*/
|
|
48
|
+
export declare function fetchWmsFrames(baseUrl: string, layers: string): Promise<string[]>;
|
|
49
|
+
//# sourceMappingURL=wmsTime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wmsTime.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/src/wmsTime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,0FAA0F;AAC1F,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAmB,GAC7B,MAAM,EAAE,CAgBV;AAED,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,GAAE,MAAmB,GAAG,aAAa,CAmB1F;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAInD;AAED,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAWpE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBrF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQvF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const MAX_FRAMES = 60;
|
|
2
|
+
function toWmsTime(ms) {
|
|
3
|
+
return new Date(ms).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
4
|
+
}
|
|
5
|
+
function parseIso8601DurationMs(iso) {
|
|
6
|
+
const m = iso.trim().match(/^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/i);
|
|
7
|
+
if (!m) return 0;
|
|
8
|
+
const [, d, h, min, s] = m;
|
|
9
|
+
const seconds = Number(d || 0) * 86400 + Number(h || 0) * 3600 + Number(min || 0) * 60 + Number(s || 0);
|
|
10
|
+
return seconds * 1e3;
|
|
11
|
+
}
|
|
12
|
+
function expandTimeRange(startIso, endIso, intervalIso, maxFrames = MAX_FRAMES) {
|
|
13
|
+
const start = Date.parse(startIso);
|
|
14
|
+
const end = Date.parse(endIso);
|
|
15
|
+
const stepMs = parseIso8601DurationMs(intervalIso);
|
|
16
|
+
if (!Number.isFinite(start)) return [];
|
|
17
|
+
if (!Number.isFinite(end) || stepMs <= 0 || end < start) return [toWmsTime(start)];
|
|
18
|
+
const out = [];
|
|
19
|
+
for (let t = start; t <= end; t += stepMs) {
|
|
20
|
+
out.push(toWmsTime(t));
|
|
21
|
+
}
|
|
22
|
+
const endStr = toWmsTime(end);
|
|
23
|
+
if (out[out.length - 1] !== endStr) out.push(endStr);
|
|
24
|
+
return out.length > maxFrames ? out.slice(out.length - maxFrames) : out;
|
|
25
|
+
}
|
|
26
|
+
function parseTimeExtent(xml, maxFrames = MAX_FRAMES) {
|
|
27
|
+
const dim = xml.match(/<Dimension\b[^>]*\bname="time"[^>]*>([\s\S]*?)<\/Dimension>/i);
|
|
28
|
+
if (!dim) return { frames: [] };
|
|
29
|
+
const body = dim[1].trim();
|
|
30
|
+
if (!body) return { frames: [] };
|
|
31
|
+
let frames;
|
|
32
|
+
if (body.includes("/")) {
|
|
33
|
+
const [start, end, interval] = body.split("/");
|
|
34
|
+
frames = expandTimeRange(start, end, interval, maxFrames);
|
|
35
|
+
} else if (body.includes(",")) {
|
|
36
|
+
frames = body.split(",").map((s) => s.trim()).filter(Boolean);
|
|
37
|
+
if (frames.length > maxFrames) frames = frames.slice(frames.length - maxFrames);
|
|
38
|
+
} else {
|
|
39
|
+
frames = [body];
|
|
40
|
+
}
|
|
41
|
+
return { frames };
|
|
42
|
+
}
|
|
43
|
+
function formatFrameTime(iso) {
|
|
44
|
+
const d = new Date(iso);
|
|
45
|
+
if (Number.isNaN(d.getTime())) return iso;
|
|
46
|
+
return d.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
|
|
47
|
+
}
|
|
48
|
+
function wmsCapabilitiesUrl(baseUrl, layers) {
|
|
49
|
+
const base = baseUrl.split("?")[0];
|
|
50
|
+
return `${base}?service=WMS&version=1.3.0&request=GetCapabilities&layer=${encodeURIComponent(layers)}`;
|
|
51
|
+
}
|
|
52
|
+
function wmsLegendUrl(baseUrl, layers) {
|
|
53
|
+
const base = baseUrl.split("?")[0];
|
|
54
|
+
const params = new URLSearchParams({
|
|
55
|
+
SERVICE: "WMS",
|
|
56
|
+
VERSION: "1.3.0",
|
|
57
|
+
REQUEST: "GetLegendGraphic",
|
|
58
|
+
LAYER: layers,
|
|
59
|
+
FORMAT: "image/png",
|
|
60
|
+
SLD_VERSION: "1.1.0"
|
|
61
|
+
});
|
|
62
|
+
return `${base}?${params.toString()}`;
|
|
63
|
+
}
|
|
64
|
+
function buildWmsTimeUrl(baseUrl, layers, time) {
|
|
65
|
+
const base = baseUrl.split("?")[0];
|
|
66
|
+
const params = new URLSearchParams({
|
|
67
|
+
SERVICE: "WMS",
|
|
68
|
+
VERSION: "1.1.1",
|
|
69
|
+
REQUEST: "GetMap",
|
|
70
|
+
FORMAT: "image/png",
|
|
71
|
+
TRANSPARENT: "true",
|
|
72
|
+
LAYERS: layers,
|
|
73
|
+
STYLES: "",
|
|
74
|
+
SRS: "EPSG:3857",
|
|
75
|
+
WIDTH: "256",
|
|
76
|
+
HEIGHT: "256",
|
|
77
|
+
TIME: time
|
|
78
|
+
});
|
|
79
|
+
return `${base}?${params.toString()}&BBOX={bbox-epsg-3857}`;
|
|
80
|
+
}
|
|
81
|
+
async function fetchWmsFrames(baseUrl, layers) {
|
|
82
|
+
try {
|
|
83
|
+
const res = await fetch(wmsCapabilitiesUrl(baseUrl, layers));
|
|
84
|
+
if (!res.ok) return [];
|
|
85
|
+
return parseTimeExtent(await res.text()).frames;
|
|
86
|
+
} catch (e) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
buildWmsTimeUrl,
|
|
92
|
+
expandTimeRange,
|
|
93
|
+
fetchWmsFrames,
|
|
94
|
+
formatFrameTime,
|
|
95
|
+
parseIso8601DurationMs,
|
|
96
|
+
parseTimeExtent,
|
|
97
|
+
wmsCapabilitiesUrl,
|
|
98
|
+
wmsLegendUrl
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=wmsTime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/datasets/src/wmsTime.ts"],"sourcesContent":["/**\r\n * Generic WMS-T (time dimension) helpers for animating WMS raster overlays.\r\n *\r\n * Generalized from the radar-specific helpers (RadarLayer/geomet.ts): any WMS\r\n * layer with an ISO8601 TIME dimension can be expanded into frames and animated\r\n * by swapping the GetMap TIME param. Data stays federated — the browser fetches\r\n * raster tiles directly; nothing is ingested or stored here.\r\n */\r\n\r\n/** Cap on expanded frames — guards against a pathological extent string. */\r\nconst MAX_FRAMES = 60\r\n\r\n/** Strip the millisecond component toISOString adds; WMS TIME wants `...:00Z`. */\r\nfunction toWmsTime(ms: number): string {\r\n return new Date(ms).toISOString().replace(/\\.\\d{3}Z$/, 'Z')\r\n}\r\n\r\n/** Parse an ISO8601 duration (`PT6M`, `PT1H30M`, `P1DT12H`) into ms. 0 if unparseable. */\r\nexport function parseIso8601DurationMs(iso: string): number {\r\n const m = iso.trim().match(/^P(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+(?:\\.\\d+)?)S)?)?$/i)\r\n if (!m) return 0\r\n const [, d, h, min, s] = m\r\n const seconds =\r\n Number(d || 0) * 86400 + Number(h || 0) * 3600 + Number(min || 0) * 60 + Number(s || 0)\r\n return seconds * 1000\r\n}\r\n\r\n/**\r\n * Expand a WMS-T `start/end/interval` extent into ascending frame timestamps\r\n * (oldest → newest). Falls back to `[start]` if the interval can't be parsed,\r\n * `[]` if start itself is invalid. Capped at `maxFrames` (keeps the newest).\r\n */\r\nexport function expandTimeRange(\r\n startIso: string,\r\n endIso: string,\r\n intervalIso: string,\r\n maxFrames: number = MAX_FRAMES,\r\n): string[] {\r\n const start = Date.parse(startIso)\r\n const end = Date.parse(endIso)\r\n const stepMs = parseIso8601DurationMs(intervalIso)\r\n\r\n if (!Number.isFinite(start)) return []\r\n if (!Number.isFinite(end) || stepMs <= 0 || end < start) return [toWmsTime(start)]\r\n\r\n const out: string[] = []\r\n for (let t = start; t <= end; t += stepMs) {\r\n out.push(toWmsTime(t))\r\n }\r\n const endStr = toWmsTime(end)\r\n if (out[out.length - 1] !== endStr) out.push(endStr)\r\n\r\n return out.length > maxFrames ? out.slice(out.length - maxFrames) : out\r\n}\r\n\r\nexport interface WmsTimeExtent {\r\n /** Ascending frame timestamps (oldest → newest). Empty when no time dimension found. */\r\n frames: string[]\r\n}\r\n\r\n/**\r\n * Pull the `<Dimension name=\"time\">` out of a (layer-scoped) WMS GetCapabilities\r\n * document and expand it to frame timestamps. Handles the `start/end/interval`\r\n * form and a bare comma-separated list as a fallback.\r\n */\r\nexport function parseTimeExtent(xml: string, maxFrames: number = MAX_FRAMES): WmsTimeExtent {\r\n const dim = xml.match(/<Dimension\\b[^>]*\\bname=\"time\"[^>]*>([\\s\\S]*?)<\\/Dimension>/i)\r\n if (!dim) return { frames: [] }\r\n\r\n const body = dim[1].trim()\r\n if (!body) return { frames: [] }\r\n\r\n let frames: string[]\r\n if (body.includes('/')) {\r\n const [start, end, interval] = body.split('/')\r\n frames = expandTimeRange(start, end, interval, maxFrames)\r\n } else if (body.includes(',')) {\r\n frames = body.split(',').map(s => s.trim()).filter(Boolean)\r\n if (frames.length > maxFrames) frames = frames.slice(frames.length - maxFrames)\r\n } else {\r\n frames = [body]\r\n }\r\n\r\n return { frames }\r\n}\r\n\r\n/** Short local-time label for a frame timestamp (e.g. \"3:42 PM\"). */\r\nexport function formatFrameTime(iso: string): string {\r\n const d = new Date(iso)\r\n if (Number.isNaN(d.getTime())) return iso\r\n return d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })\r\n}\r\n\r\n/** Layer-scoped GetCapabilities URL — returns a small XML payload with the live time extent. */\r\nexport function wmsCapabilitiesUrl(baseUrl: string, layers: string): string {\r\n const base = baseUrl.split('?')[0]\r\n return `${base}?service=WMS&version=1.3.0&request=GetCapabilities&layer=${encodeURIComponent(layers)}`\r\n}\r\n\r\n/**\r\n * Build a WMS GetLegendGraphic URL — the server-rendered legend image (colour\r\n * ramp + labels) for the layer's default style. No STYLE param, so it matches\r\n * the default-style tiles `buildWmsTimeUrl` requests (STYLES='').\r\n */\r\nexport function wmsLegendUrl(baseUrl: string, layers: string): string {\r\n const base = baseUrl.split('?')[0]\r\n const params = new URLSearchParams({\r\n SERVICE: 'WMS',\r\n VERSION: '1.3.0',\r\n REQUEST: 'GetLegendGraphic',\r\n LAYER: layers,\r\n FORMAT: 'image/png',\r\n SLD_VERSION: '1.1.0',\r\n })\r\n return `${base}?${params.toString()}`\r\n}\r\n\r\n/**\r\n * Build a MapLibre raster tile-URL template for a WMS GetMap request at a given\r\n * TIME. `{bbox-epsg-3857}` must stay literal — MapLibre substitutes it per tile.\r\n * Mirrors `buildWmsTileUrl` (WMS 1.1.1 + SRS=EPSG:3857) with TIME added.\r\n */\r\nexport function buildWmsTimeUrl(baseUrl: string, layers: string, time: string): string {\r\n const base = baseUrl.split('?')[0]\r\n const params = new URLSearchParams({\r\n SERVICE: 'WMS',\r\n VERSION: '1.1.1',\r\n REQUEST: 'GetMap',\r\n FORMAT: 'image/png',\r\n TRANSPARENT: 'true',\r\n LAYERS: layers,\r\n STYLES: '',\r\n SRS: 'EPSG:3857',\r\n WIDTH: '256',\r\n HEIGHT: '256',\r\n TIME: time,\r\n })\r\n return `${base}?${params.toString()}&BBOX={bbox-epsg-3857}`\r\n}\r\n\r\n/**\r\n * Fetch a layer-scoped GetCapabilities document and return its time frames.\r\n * Thin network wrapper — returns `[]` on any failure so callers can simply\r\n * render no control (the static latest-frame raster keeps working).\r\n */\r\nexport async function fetchWmsFrames(baseUrl: string, layers: string): Promise<string[]> {\r\n try {\r\n const res = await fetch(wmsCapabilitiesUrl(baseUrl, layers))\r\n if (!res.ok) return []\r\n return parseTimeExtent(await res.text()).frames\r\n } catch {\r\n return []\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Geocoder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyB9B,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAA;IACrC,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,QAAQ,EACR,qBAA4B,EAC5B,cAAsB,GACvB,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"Geocoder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyB9B,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAA;IACrC,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,QAAQ,EACR,qBAA4B,EAC5B,cAAsB,GACvB,EAAE,aAAa,qBA0Rf"}
|
|
@@ -114,7 +114,7 @@ function Geocoder({
|
|
|
114
114
|
};
|
|
115
115
|
}, [alwaysExpanded]);
|
|
116
116
|
const handleSelectSuggestion = (feature, type = "") => {
|
|
117
|
-
var _a
|
|
117
|
+
var _a;
|
|
118
118
|
setQuery("");
|
|
119
119
|
setSuggestions([]);
|
|
120
120
|
setBuildingResults([]);
|
|
@@ -128,18 +128,18 @@ function Geocoder({
|
|
|
128
128
|
if (onSelect) onSelect(addressData);
|
|
129
129
|
if (mapDispatch && currentLocation) {
|
|
130
130
|
const [lng, lat] = addressData.coordinates;
|
|
131
|
-
const
|
|
131
|
+
const props = addressData.properties || {};
|
|
132
132
|
const parts = address2.split(",").map((p) => p.trim());
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
let municipality = "";
|
|
136
|
-
if (partsReverse[1] === countrySubdivision) municipality = partsReverse[2] || "";
|
|
133
|
+
const countrySubdivision = props.region_a || props.region || "";
|
|
134
|
+
const municipality = props.locality || props.neighbourhood || props.county || "";
|
|
137
135
|
const newCurrentLocation = __spreadProps(__spreadValues({}, currentLocation), { municipality, countrySubdivision, longitude: lng, latitude: lat, address: parts[0] });
|
|
138
136
|
mapDispatch({ type: "UPDATE_LOCATION", payload: { currentLocation: newCurrentLocation } });
|
|
139
|
-
if (municipality
|
|
137
|
+
if (municipality || countrySubdivision) {
|
|
140
138
|
const url = new URL(window.location.href);
|
|
141
|
-
url.searchParams.set("municipality", municipality);
|
|
142
|
-
url.searchParams.
|
|
139
|
+
if (municipality) url.searchParams.set("municipality", municipality);
|
|
140
|
+
else url.searchParams.delete("municipality");
|
|
141
|
+
if (countrySubdivision) url.searchParams.set("countrySubdivision", countrySubdivision);
|
|
142
|
+
else url.searchParams.delete("countrySubdivision");
|
|
143
143
|
url.searchParams.set("address", parts[0]);
|
|
144
144
|
url.searchParams.set("lng", lng.toString());
|
|
145
145
|
url.searchParams.set("lat", lat.toString());
|