forked from MapComplete/MapComplete
Download button: take advantage of MVT server, download button will now attempt to download everything
This commit is contained in:
parent
bccda67e1c
commit
e4eb8d6b52
21 changed files with 453 additions and 353 deletions
|
|
@ -3,10 +3,8 @@
|
|||
import { ArrowDownTrayIcon } from "@babeard/svelte-heroicons/mini"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import type { FeatureCollection } from "geojson"
|
||||
import Loading from "../Base/Loading.svelte"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import DownloadHelper from "./DownloadHelper"
|
||||
import { Utils } from "../../Utils"
|
||||
import type { PriviligedLayerType } from "../../Models/Constants"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
|
|
@ -16,14 +14,11 @@
|
|||
export let extension: string
|
||||
export let mimetype: string
|
||||
export let construct: (
|
||||
geojsonCleaned: FeatureCollection,
|
||||
title: string,
|
||||
status?: UIEventSource<string>
|
||||
) => (Blob | string) | Promise<void>
|
||||
) => Promise<Blob | string>
|
||||
export let mainText: Translation
|
||||
export let helperText: Translation
|
||||
export let metaIsIncluded: boolean
|
||||
let downloadHelper: DownloadHelper = new DownloadHelper(state)
|
||||
|
||||
const t = Translations.t.general.download
|
||||
|
||||
|
|
@ -31,30 +26,21 @@
|
|||
let isError = false
|
||||
|
||||
let status: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
|
||||
async function clicked() {
|
||||
isExporting = true
|
||||
|
||||
const gpsLayer = state.layerState.filteredLayers.get(<PriviligedLayerType>"gps_location")
|
||||
state.userRelatedState.preferencesAsTags.data["__showTimeSensitiveIcons"] = "no"
|
||||
state.userRelatedState.preferencesAsTags.ping()
|
||||
const gpsIsDisplayed = gpsLayer.isDisplayed.data
|
||||
try {
|
||||
gpsLayer.isDisplayed.setData(false)
|
||||
const geojson: FeatureCollection = downloadHelper.getCleanGeoJson(metaIsIncluded)
|
||||
const name = state.layout.id
|
||||
|
||||
const title = `MapComplete_${name}_export_${new Date()
|
||||
.toISOString()
|
||||
.substr(0, 19)}.${extension}`
|
||||
const promise = construct(geojson, title, status)
|
||||
let data: Blob | string
|
||||
if (typeof promise === "string") {
|
||||
data = promise
|
||||
} else if (typeof promise["then"] === "function") {
|
||||
data = await (<Promise<Blob | string>>promise)
|
||||
} else {
|
||||
data = <Blob>promise
|
||||
}
|
||||
const data: Blob | string = await construct(title, status)
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ export default class DownloadHelper {
|
|||
return header + "\n" + elements.join("\n") + "\n</svg>"
|
||||
}
|
||||
|
||||
public getCleanGeoJsonPerLayer(includeMetaData: boolean): Map<string, Feature[]> {
|
||||
private getCleanGeoJsonPerLayer(includeMetaData: boolean): Map<string, Feature[]> {
|
||||
const state = this._state
|
||||
const featuresPerLayer = new Map<string, any[]>()
|
||||
const neededLayers = state.layout.layers.filter((l) => l.source !== null).map((l) => l.id)
|
||||
|
|
@ -161,6 +161,7 @@ export default class DownloadHelper {
|
|||
|
||||
for (const neededLayer of neededLayers) {
|
||||
const indexedFeatureSource = state.perLayer.get(neededLayer)
|
||||
|
||||
let features = indexedFeatureSource.GetFeaturesWithin(bbox)
|
||||
// The 'indexedFeatureSources' contains _all_ features, they are not filtered yet
|
||||
const filter = state.layerState.filteredLayers.get(neededLayer)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,16 @@
|
|||
const downloadHelper = new DownloadHelper(state)
|
||||
|
||||
let metaIsIncluded = false
|
||||
const name = state.layout.id
|
||||
|
||||
function offerSvg(noSelfIntersectingLines: boolean): string {
|
||||
let numberOfFeatures = state.featureSummary.totalNumberOfFeatures
|
||||
|
||||
async function getGeojson() {
|
||||
await state.indexedFeatures.downloadAll()
|
||||
return downloadHelper.getCleanGeoJson(metaIsIncluded)
|
||||
}
|
||||
|
||||
async function offerSvg(noSelfIntersectingLines: boolean): Promise<string> {
|
||||
await state.indexedFeatures.downloadAll()
|
||||
const maindiv = document.getElementById("maindiv")
|
||||
const layers = state.layout.layers.filter((l) => l.source !== null)
|
||||
return downloadHelper.asSvg({
|
||||
|
|
@ -34,6 +41,8 @@
|
|||
|
||||
{#if $isLoading}
|
||||
<Loading />
|
||||
{:else if $numberOfFeatures > 100000}
|
||||
<Tr cls="alert" t={Translations.t.general.download.toMuch} />
|
||||
{:else}
|
||||
<div class="flex w-full flex-col" />
|
||||
<h3>
|
||||
|
|
@ -44,20 +53,18 @@
|
|||
{state}
|
||||
extension="geojson"
|
||||
mimetype="application/vnd.geo+json"
|
||||
construct={(geojson) => JSON.stringify(geojson)}
|
||||
construct={async () => JSON.stringify(await getGeojson())}
|
||||
mainText={t.downloadGeojson}
|
||||
helperText={t.downloadGeoJsonHelper}
|
||||
{metaIsIncluded}
|
||||
/>
|
||||
|
||||
<DownloadButton
|
||||
{state}
|
||||
extension="csv"
|
||||
mimetype="text/csv"
|
||||
construct={(geojson) => GeoOperations.toCSV(geojson)}
|
||||
construct={async () => GeoOperations.toCSV(await getGeojson())}
|
||||
mainText={t.downloadCSV}
|
||||
helperText={t.downloadCSVHelper}
|
||||
{metaIsIncluded}
|
||||
/>
|
||||
|
||||
<label class="mb-8 mt-2">
|
||||
|
|
@ -67,7 +74,6 @@
|
|||
|
||||
<DownloadButton
|
||||
{state}
|
||||
{metaIsIncluded}
|
||||
extension="svg"
|
||||
mimetype="image/svg+xml"
|
||||
mainText={t.downloadAsSvg}
|
||||
|
|
@ -77,7 +83,6 @@
|
|||
|
||||
<DownloadButton
|
||||
{state}
|
||||
{metaIsIncluded}
|
||||
extension="svg"
|
||||
mimetype="image/svg+xml"
|
||||
mainText={t.downloadAsSvgLinesOnly}
|
||||
|
|
@ -87,7 +92,6 @@
|
|||
|
||||
<DownloadButton
|
||||
{state}
|
||||
{metaIsIncluded}
|
||||
extension="png"
|
||||
mimetype="image/png"
|
||||
mainText={t.downloadAsPng}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
let t = Translations.t.general.download
|
||||
const downloadHelper = new DownloadHelper(state)
|
||||
|
||||
async function constructPdf(_, title: string, status: UIEventSource<string>) {
|
||||
async function constructPdf(title: string, status: UIEventSource<string>): Promise<Blob> {
|
||||
title =
|
||||
title.substring(0, title.length - 4) + "_" + template.format + "_" + template.orientation
|
||||
const templateUrls = SvgToPdf.templates[templateName].pages
|
||||
|
|
@ -33,11 +33,11 @@
|
|||
console.log("Creating an image for key", key)
|
||||
if (key === "qr") {
|
||||
const toShare = window.location.href.split("#")[0]
|
||||
return new Qr(toShare).toImageElement(parseFloat(width), parseFloat(height))
|
||||
return new Qr(toShare).toImageElement(parseFloat(width))
|
||||
}
|
||||
return downloadHelper.createImage(key, width, height)
|
||||
},
|
||||
textSubstitutions: <Record<string, string>>{
|
||||
textSubstitutions: <Record<string, string | Translation>>{
|
||||
"layout.title": state.layout.title,
|
||||
layoutid: state.layout.id,
|
||||
title: state.layout.title,
|
||||
|
|
@ -61,7 +61,6 @@
|
|||
construct={constructPdf}
|
||||
extension="pdf"
|
||||
helperText={t.downloadAsPdfHelper}
|
||||
metaIsIncluded={false}
|
||||
mainText={t.pdf.current_view_generic.Subs({
|
||||
orientation: template.orientation,
|
||||
paper_size: template.format.toUpperCase(),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import { OsmTags } from "../Models/OsmFeature"
|
|||
import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFeatureSource"
|
||||
import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider"
|
||||
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
|
||||
import { SummaryTileSourceRewriter } from "../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource"
|
||||
import LayoutSource from "../Logic/FeatureSource/Sources/LayoutSource"
|
||||
|
||||
/**
|
||||
* The state needed to render a special Visualisation.
|
||||
|
|
@ -30,12 +32,13 @@ export interface SpecialVisualizationState {
|
|||
readonly featureSwitches: FeatureSwitchState
|
||||
|
||||
readonly layerState: LayerState
|
||||
readonly featureSummary: SummaryTileSourceRewriter
|
||||
readonly featureProperties: {
|
||||
getStore(id: string): UIEventSource<Record<string, string>>
|
||||
trackFeature?(feature: { properties: OsmTags })
|
||||
}
|
||||
|
||||
readonly indexedFeatures: IndexedFeatureSource
|
||||
readonly indexedFeatures: IndexedFeatureSource & LayoutSource
|
||||
/**
|
||||
* Some features will create a new element that should be displayed.
|
||||
* These can be injected by appending them to this featuresource (and pinging it)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import mcChanges from "../../src/assets/generated/themes/mapcomplete-changes.jso
|
|||
import SvelteUIElement from "./Base/SvelteUIElement"
|
||||
import Filterview from "./BigComponents/Filterview.svelte"
|
||||
import FilteredLayer from "../Models/FilteredLayer"
|
||||
import DownloadButton from "./DownloadFlow/DownloadButton.svelte"
|
||||
import { SubtleButton } from "./Base/SubtleButton"
|
||||
import { GeoOperations } from "../Logic/GeoOperations"
|
||||
import { Polygon } from "geojson"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue