Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions apps/geolibre-desktop/src/components/layout/TopToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
setBasemapControlLabels,
setGraticuleLabels,
setMapillaryLabels,
setEarthdataGisLabels,
setOpenAerialMapLabels,
setHuggingFaceLabels,
setSourceCoopLabels,
Expand Down Expand Up @@ -274,6 +275,79 @@ export function TopToolbar({
metaSource: t("openAerialMap.metaSource"),
metaRaw: t("openAerialMap.metaRaw"),
});
setEarthdataGisLabels({
hint: t("earthdataGis.hint"),
searchPlaceholder: t("earthdataGis.searchPlaceholder"),
search: t("earthdataGis.search"),
searching: t("earthdataGis.searching"),
loadingMore: t("earthdataGis.loadingMore"),
loadMore: t("earthdataGis.loadMore"),
noResults: t("earthdataGis.noResults"),
showing: (shown, total) => t("earthdataGis.showing", { shown, total }),
searchError: (message) => t("earthdataGis.searchError", { message }),
limitToView: t("earthdataGis.limitToView"),
limitToViewTitle: t("earthdataGis.limitToViewTitle"),
filterAll: t("earthdataGis.filterAll"),
filterImage: t("earthdataGis.filterImage"),
filterMap: t("earthdataGis.filterMap"),
filterFeature: t("earthdataGis.filterFeature"),
kindImage: t("earthdataGis.kindImage"),
kindMap: t("earthdataGis.kindMap"),
kindFeature: t("earthdataGis.kindFeature"),
kindWebMap: t("earthdataGis.kindWebMap"),
filterWebMap: t("earthdataGis.filterWebMap"),
webMapAdded: (added, total) =>
added === total
? t("earthdataGis.webMapAdded", { count: added })
: t("earthdataGis.webMapAddedPartial", { added, total }),
webMapEmpty: t("earthdataGis.webMapEmpty"),
add: t("earthdataGis.add"),
adding: t("earthdataGis.adding"),
remove: t("earthdataGis.remove"),
zoom: t("earthdataGis.zoom"),
details: t("earthdataGis.details"),
portal: t("earthdataGis.portal"),
portalTitle: t("earthdataGis.portalTitle"),
cog: t("earthdataGis.cog"),
cogTitle: t("earthdataGis.cogTitle"),
cogHeading: t("earthdataGis.cogHeading"),
cogAreaView: t("earthdataGis.cogAreaView"),
cogAreaExtent: t("earthdataGis.cogAreaExtent"),
cogSize: (width, height) => t("earthdataGis.cogSize", { width, height }),
cogResolution: (metres) => t("earthdataGis.cogResolution", { metres }),
cogNote: t("earthdataGis.cogNote"),
cogDownload: t("earthdataGis.cogDownload"),
cogDownloading: t("earthdataGis.cogDownloading"),
cogRetrying: (width, height) => t("earthdataGis.cogRetrying", { width, height }),
cogConverting: t("earthdataGis.cogConverting"),
cogDone: (width, height) => t("earthdataGis.cogDone", { width, height }),
cogFailed: (message) => t("earthdataGis.cogFailed", { message }),
cogUnavailable: t("earthdataGis.cogUnavailable"),
cancel: t("earthdataGis.cancel"),
addTitle: t("earthdataGis.addTitle"),
removeTitle: t("earthdataGis.removeTitle"),
zoomTitle: t("earthdataGis.zoomTitle"),
zoomUnavailableTitle: t("earthdataGis.zoomUnavailableTitle"),
detailsTitle: t("earthdataGis.detailsTitle"),
addError: (message) => t("earthdataGis.addError", { message }),
addTimeout: t("earthdataGis.addTimeout"),
zoomedToData: t("earthdataGis.zoomedToData"),
detailsHeading: t("earthdataGis.detailsHeading"),
close: t("earthdataGis.close"),
metaTitle: t("earthdataGis.metaTitle"),
metaType: t("earthdataGis.metaType"),
metaSummary: t("earthdataGis.metaSummary"),
metaDescription: t("earthdataGis.metaDescription"),
metaOwner: t("earthdataGis.metaOwner"),
metaModified: t("earthdataGis.metaModified"),
metaTags: t("earthdataGis.metaTags"),
metaExtent: t("earthdataGis.metaExtent"),
metaCredits: t("earthdataGis.metaCredits"),
metaLicense: t("earthdataGis.metaLicense"),
metaService: t("earthdataGis.metaService"),
metaPortalItem: t("earthdataGis.metaPortalItem"),
metaRaw: t("earthdataGis.metaRaw"),
});
setSourceCoopLabels({
hint: t("sourceCoop.hint"),
searchPlaceholder: t("sourceCoop.searchPlaceholder"),
Expand Down
22 changes: 22 additions & 0 deletions apps/geolibre-desktop/src/hooks/usePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
getEffectsSettings,
setEffectsSettings,
type EffectsSettings,
maplibreEarthdataGisPlugin,
setEarthdataCogSaver,
maplibreEnviroAtlasPlugin,
maplibreEsriWaybackPlugin,
maplibreFemaWmsPlugin,
Expand Down Expand Up @@ -160,6 +162,7 @@ manager.registerAll([
maplibreNasaEarthdataPlugin,
maplibreEnviroAtlasPlugin,
maplibreNationalMapPlugin,
maplibreEarthdataGisPlugin,
maplibreOpenAerialMapPlugin,
maplibreSourceCoopPlugin,
maplibreNaturalEarthPlugin,
Expand Down Expand Up @@ -204,6 +207,25 @@ setTimelapseVideoSaver((blob, { defaultName, extension, mimeType }) =>
}),
);

// The Earthdata GIS plugin exports an ArcGIS service as a plain GeoTIFF but
// cannot re-encode it: ArcGIS has no COG output (`format=cog` falls back to
// PNG, and `format=tiff` returns a tiled file with no overviews), and the
// plugins package owns neither the COG encoder nor the app's file dialogs. Both
// are injected here once at startup, mirroring setTimelapseVideoSaver.
setEarthdataCogSaver(async (geoTiffBytes, defaultName) => {
// Imported on demand so the COG encoder's WASM is only fetched when a user
// actually downloads one.
const { convertGeoTiffToCog } = await import("@geolibre/processing");
const cogBytes = await convertGeoTiffToCog(geoTiffBytes);
const saved = await saveBinaryFileWithFallback(cogBytes, {
defaultName,
filters: [{ name: "Cloud Optimized GeoTIFF", extensions: ["tif"] }],
browserTypes: [{ description: "Cloud Optimized GeoTIFF", accept: { "image/tiff": [".tif"] } }],
mimeType: "image/tiff",
});
return saved !== null;
});

// The Zarr panel can open a store from a folder on disk, but reading a folder
// needs a filesystem API the plugins package does not have, so the picker is
// injected here the same way. Registered only where a folder dialog exists (the
Expand Down
72 changes: 72 additions & 0 deletions apps/geolibre-desktop/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,78 @@
"metaSource": "Source GeoTIFF",
"metaRaw": "Raw metadata"
},
"earthdataGis": {
"hint": "Search NASA Earthdata GIS for imagery, map, and feature services.",
"searchPlaceholder": "Search Earthdata GIS…",
"search": "Search",
"searching": "Searching…",
"loadingMore": "Loading more…",
"loadMore": "Load more",
"noResults": "No services matched this search.",
"showing": "Showing {{shown}} of {{total}} services.",
"searchError": "Could not reach Earthdata GIS: {{message}}. Please try again.",
"limitToView": "Limit to map view",
"limitToViewTitle": "Only return services that intersect the current map view",
"filterAll": "All",
"filterImage": "Imagery",
"filterMap": "Maps",
"filterFeature": "Features",
"kindImage": "Image service",
"kindMap": "Map service",
"kindFeature": "Feature service",
"kindWebMap": "Web map",
"filterWebMap": "Web maps",
"webMapAdded_one": "Added {{count}} layer from this web map.",
"webMapAdded_other": "Added {{count}} layers from this web map.",
"webMapAddedPartial": "Added {{added}} of {{total}} layers from this web map; the rest could not be reached.",
"webMapEmpty": "this web map has no layers GeoLibre can render.",
"add": "Add",
"adding": "Adding…",
"remove": "Remove",
"zoom": "Zoom",
"details": "Details",
"portal": "Portal",
"portalTitle": "Open this item on the Earthdata GIS portal",
"cog": "COG",
"cogTitle": "Download this service as a Cloud Optimized GeoTIFF",
"cogHeading": "Download as COG",
"cogAreaView": "Current view",
"cogAreaExtent": "Full extent",
"cogSize": "Export size: {{width}} x {{height}} px",
"cogResolution": "Ground resolution: {{metres}} m/px",
"cogNote": "The service is re-exported at this size and re-encoded as a COG, so this is a resampled view of the area, not the source raster at native resolution.",
"cogDownload": "Download",
"cogDownloading": "Exporting and converting…",
"cogRetrying": "The service refused that size; retrying at {{width}} x {{height}} px…",
"cogConverting": "Converting to a COG…",
"cogDone": "Saved the COG at {{width}} x {{height}} px.",
"cogFailed": "Could not download the COG: {{message}}",
"cogUnavailable": "Downloading requires the desktop app or a browser save dialog.",
"cancel": "Cancel",
"addTitle": "Add this service to the map",
"removeTitle": "Remove this service from the map",
"zoomTitle": "Zoom to this service",
"zoomUnavailableTitle": "This service does not publish an extent",
"detailsTitle": "View this service's metadata",
"addError": "Could not add the service: {{message}}",
"addTimeout": "it did not respond within a minute. The layer will still appear if it finishes.",
"zoomedToData": "Zoomed in past this layer's full extent: the service only renders at higher zoom levels.",
"detailsHeading": "Service details",
"close": "Close",
"metaTitle": "Title",
"metaType": "Type",
"metaSummary": "Summary",
"metaDescription": "Description",
"metaOwner": "Published by",
"metaModified": "Last modified",
"metaTags": "Tags",
"metaExtent": "Extent (W, S, E, N)",
"metaCredits": "Credits",
"metaLicense": "Use constraints",
"metaService": "Service URL",
"metaPortalItem": "Portal item",
"metaRaw": "Raw metadata"
},
"sourceCoop": {
"hint": "Search Source Cooperative for open geospatial data, or enter an account/product id.",
"searchPlaceholder": "Search data, or account/product",
Expand Down
18 changes: 18 additions & 0 deletions packages/plugins/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,24 @@ export {
export { maplibreGeoAgentPlugin } from "./plugins/maplibre-geoagent";
export { maplibreUsgsLidarPlugin } from "./plugins/maplibre-usgs-lidar";
export { maplibreNasaEarthdataPlugin } from "./plugins/maplibre-nasa-earthdata";
export {
DEFAULT_EARTHDATA_GIS_LABELS,
EARTHDATA_GIS_PLUGIN_ID,
maplibreEarthdataGisPlugin,
setEarthdataCogSaver,
setEarthdataGisLabels,
type EarthdataCogSaver,
type EarthdataGisLabels,
} from "./plugins/maplibre-earthdata-gis";
// The catalog client's helpers (buildSearchUrl, parseSearchResponse, …) are
// deliberately not re-exported here: those names are already taken by the
// OpenAerialMap client below. Import them from the module path instead.
export {
EARTHDATA_GIS_PORTAL_URL,
type EarthdataGisItem,
type EarthdataGisSearchResult,
type EarthdataServiceKind,
} from "./plugins/earthdata-gis-api";
export {
DEFAULT_OPENAERIALMAP_LABELS,
maplibreOpenAerialMapPlugin,
Expand Down
Loading
Loading