Improvements to pdfExport, small tweaks to the themes
This commit is contained in:
parent
38635ba8b2
commit
f946ad38b7
8 changed files with 102 additions and 39 deletions
|
@ -20,6 +20,8 @@ import BaseLayer from "../Models/BaseLayer";
|
||||||
import LayoutConfig from "../Customizations/JSON/LayoutConfig";
|
import LayoutConfig from "../Customizations/JSON/LayoutConfig";
|
||||||
import {FixedUiElement} from "./Base/FixedUiElement";
|
import {FixedUiElement} from "./Base/FixedUiElement";
|
||||||
import Translations from "./i18n/Translations";
|
import Translations from "./i18n/Translations";
|
||||||
|
import State from "../State";
|
||||||
|
import Constants from "../Models/Constants";
|
||||||
|
|
||||||
export default class ExportPDF {
|
export default class ExportPDF {
|
||||||
// dimensions of the map in milimeter
|
// dimensions of the map in milimeter
|
||||||
|
@ -100,7 +102,7 @@ export default class ExportPDF {
|
||||||
}
|
}
|
||||||
|
|
||||||
private cleanup() {
|
private cleanup() {
|
||||||
new FixedUiElement("Screenshot taken!").AttachTo(this.freeDivId)
|
// new FixedUiElement("Screenshot taken!").AttachTo(this.freeDivId)
|
||||||
this._screenhotTaken = true;
|
this._screenhotTaken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,28 +126,67 @@ export default class ExportPDF {
|
||||||
|
|
||||||
doc.setDrawColor(255, 255, 255)
|
doc.setDrawColor(255, 255, 255)
|
||||||
doc.setFillColor(255, 255, 255)
|
doc.setFillColor(255, 255, 255)
|
||||||
doc.roundedRect(12, 5, 125, 30, 5, 5, 'FD')
|
doc.roundedRect(12, 10, 145, 25, 5, 5, 'FD')
|
||||||
|
|
||||||
doc.setFontSize(20)
|
doc.setFontSize(20)
|
||||||
doc.text(layout.title.txt, 40, 20, {
|
doc.textWithLink(layout.title.txt, 40, 18.5, {
|
||||||
maxWidth: 100
|
maxWidth: 125,
|
||||||
|
url: window.location.href
|
||||||
})
|
})
|
||||||
doc.setFontSize(10)
|
doc.setFontSize(10)
|
||||||
doc.text(t.attr.txt, 40, 25, {
|
doc.text(t.generatedWith.txt, 40, 23, {
|
||||||
maxWidth: 100
|
maxWidth: 125
|
||||||
})
|
})
|
||||||
|
const backgroundLayer : BaseLayer = State.state.backgroundLayer.data
|
||||||
|
const attribution = new FixedUiElement(backgroundLayer.layer().getAttribution() ?? backgroundLayer.name).ConstructElement().innerText
|
||||||
|
doc.textWithLink(t.attr.txt, 40, 26.5, {
|
||||||
|
maxWidth: 125,
|
||||||
|
url: "https://www.openstreetmap.org/copyright"
|
||||||
|
})
|
||||||
|
|
||||||
|
doc.text(t.attrBackground.Subs({
|
||||||
|
background: attribution
|
||||||
|
}).txt, 40, 30)
|
||||||
|
|
||||||
|
let date = new Date().toISOString().substr(0,16)
|
||||||
|
|
||||||
|
doc.setFontSize(7)
|
||||||
|
doc.text(t.versionInfo.Subs({
|
||||||
|
version: Constants.vNumber,
|
||||||
|
date: date
|
||||||
|
}).txt, 40, 34, {
|
||||||
|
maxWidth: 125
|
||||||
|
})
|
||||||
|
|
||||||
// Add the logo of the layout
|
// Add the logo of the layout
|
||||||
let img = document.createElement('img');
|
let img = document.createElement('img');
|
||||||
const imgSource = layout.icon
|
const imgSource = layout.icon
|
||||||
|
const imgType = imgSource.substr(imgSource.lastIndexOf(".") + 1);
|
||||||
img.src = imgSource
|
img.src = imgSource
|
||||||
try {
|
console.log(imgType)
|
||||||
doc.addImage(img, imgSource.substr(imgSource.lastIndexOf(".")), 15, 12, 20, 20);
|
if (imgType.toLowerCase() === "svg") {
|
||||||
} catch (e) {
|
new FixedUiElement("").AttachTo(this.freeDivId)
|
||||||
// TODO: support svg rendering...
|
|
||||||
console.error(e)
|
// This is an svg image, we use the canvas to convert it to a png
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
canvas.width = 500
|
||||||
|
canvas.height = 500
|
||||||
|
img.style.width = "100%"
|
||||||
|
img.style.height = "100%"
|
||||||
|
ctx.drawImage(img, 0, 0, 500, 500);
|
||||||
|
const base64img = canvas.toDataURL("image/png")
|
||||||
|
doc.addImage(base64img, 'png', 15, 12, 20, 20);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doc.addImage(img, imgType, 15, 12, 20, 20);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.save("MapComplete_export.pdf");
|
doc.save(`MapComplete_${layout.title.txt}_${date}.pdf`);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,11 +633,15 @@
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "width:carriageway",
|
"key": "width:carriageway",
|
||||||
"type": "length", "helperArgs": ["20", "map"]
|
"type": "length",
|
||||||
|
"helperArgs": [
|
||||||
|
"20",
|
||||||
|
"map"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"question": {
|
"question": {
|
||||||
"en": "What is the carriage width of this road (in meters)?<br/><span class='subtle'>This is measured from kerb to kerb, including parking lanes</span>",
|
"en": "What is the carriage width of this road (in meters)?",
|
||||||
"nl": "Hoe breed is de rijbaan in deze straat (in meters)?<br/><span class='subtle'>Gemeten van stoepsteen tot stoepsten, inclusief parkeerstroken</span>"
|
"nl": "Hoe breed is de rijbaan in deze straat (in meters)?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -971,7 +975,11 @@
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "cycleway:buffer",
|
"key": "cycleway:buffer",
|
||||||
"type": "length", "helperArgs": ["20", "map"]
|
"type": "length",
|
||||||
|
"helperArgs": [
|
||||||
|
"20",
|
||||||
|
"map"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1308,7 +1316,11 @@
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "width:carriageway",
|
"key": "width:carriageway",
|
||||||
"type": "length", "helperArgs": ["20", "map"]
|
"type": "length",
|
||||||
|
"helperArgs": [
|
||||||
|
"20",
|
||||||
|
"map"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"question": {
|
"question": {
|
||||||
"en": "What is the carriage width of this road (in meters)?<br/><span class='subtle'>This is measured from kerb to kerb, including parking lanes</span>",
|
"en": "What is the carriage width of this road (in meters)?<br/><span class='subtle'>This is measured from kerb to kerb, including parking lanes</span>",
|
||||||
|
@ -1509,7 +1521,11 @@
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "maxwidth:physical",
|
"key": "maxwidth:physical",
|
||||||
"type": "length", "helperArgs": ["20", "map"]
|
"type": "length",
|
||||||
|
"helperArgs": [
|
||||||
|
"20",
|
||||||
|
"map"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1529,8 +1545,11 @@
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "width:seperation",
|
"key": "width:seperation",
|
||||||
"type": "length",
|
"type": "length",
|
||||||
"helperArgs": ["20", "map"]
|
"helperArgs": [
|
||||||
|
"20",
|
||||||
|
"map"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
11
index.html
11
index.html
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!-- WARNING: index.html serves as a template. If you want to change something, change it there -->
|
<!-- WARNING: index.html serves as a template. If you want to change something, change it there -->
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
@ -24,8 +23,9 @@
|
||||||
<link rel="icon" href="./assets/svg/add.svg" sizes="any" type="image/svg+xml">
|
<link rel="icon" href="./assets/svg/add.svg" sizes="any" type="image/svg+xml">
|
||||||
<meta property="og:image" content="./assets/SocialImage.png">
|
<meta property="og:image" content="./assets/SocialImage.png">
|
||||||
<meta property="og:title" content="MapComplete - editable, thematic maps with OpenStreetMap">
|
<meta property="og:title" content="MapComplete - editable, thematic maps with OpenStreetMap">
|
||||||
<meta property="og:description" content="MapComplete is a platform to visualize OpenStreetMap on a specific topic and to easily contribute data back to it.">
|
<meta property="og:description"
|
||||||
|
content="MapComplete is a platform to visualize OpenStreetMap on a specific topic and to easily contribute data back to it.">
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="512x512" href="./assets/generated/svg_mapcomplete_logo512.png">
|
<link rel="apple-touch-icon" sizes="512x512" href="./assets/generated/svg_mapcomplete_logo512.png">
|
||||||
<link rel="apple-touch-icon" sizes="384x384" href="./assets/generated/svg_mapcomplete_logo384.png">
|
<link rel="apple-touch-icon" sizes="384x384" href="./assets/generated/svg_mapcomplete_logo384.png">
|
||||||
<link rel="apple-touch-icon" sizes="192x192" href="./assets/generated/svg_mapcomplete_logo192.png">
|
<link rel="apple-touch-icon" sizes="192x192" href="./assets/generated/svg_mapcomplete_logo192.png">
|
||||||
|
@ -74,10 +74,7 @@
|
||||||
Loading MapComplete, hang on...
|
Loading MapComplete, hang on...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span id="belowmap"
|
<span id="belowmap" class="absolute" style="z-index: -1">Below</span>
|
||||||
class="absolute"
|
|
||||||
style="z-index: -1"
|
|
||||||
>Below</span>
|
|
||||||
<div id="leafletDiv"></div>
|
<div id="leafletDiv"></div>
|
||||||
|
|
||||||
<script src="./index.ts"></script>
|
<script src="./index.ts"></script>
|
||||||
|
|
|
@ -62,7 +62,10 @@
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"pdf": {
|
"pdf": {
|
||||||
"attr": "Generated with MapComplete.osm.be - map data © OpenStreetMap Contributors, reusable under ODbL"
|
"generatedWith": "Generated with MapComplete.osm.be",
|
||||||
|
"attr": "Map data © OpenStreetMap Contributors, reusable under ODbL",
|
||||||
|
"attrBackground": "Background layer: {background}",
|
||||||
|
"versionInfo": "v{version} - generated on {date}"
|
||||||
},
|
},
|
||||||
"loginWithOpenStreetMap": "Login with OpenStreetMap",
|
"loginWithOpenStreetMap": "Login with OpenStreetMap",
|
||||||
"welcomeBack": "You are logged in, welcome back!",
|
"welcomeBack": "You are logged in, welcome back!",
|
||||||
|
|
|
@ -2364,12 +2364,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"presets": {
|
|
||||||
"0": {
|
|
||||||
"title": "Paden",
|
|
||||||
"description": "Voeg een ontbrekend, erkend pad toe."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1108,6 +1108,10 @@
|
||||||
"then": "This is not a cyclestreet."
|
"then": "This is not a cyclestreet."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"render": "The carriage width of this road is <strong>{width:carriageway}m</strong>",
|
||||||
|
"question": "What is the carriage width of this road (in meters)?<br/><span class='subtle'>This is measured from kerb to kerb, including parking lanes</span>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -970,6 +970,10 @@
|
||||||
"then": "Dit is geen fietsstraat"
|
"then": "Dit is geen fietsstraat"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"render": "De breedte van deze rijbaan in deze straat is <strong>{width:carriageway}m</strong>",
|
||||||
|
"question": "Hoe breed is de rijbaan in deze straat (in meters)?<br/><span class='subtle'>Gemeten van stoepsteen tot stoepsten, inclusief parkeerstroken</span>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as fs from "fs";
|
||||||
import {readFileSync, writeFileSync} from "fs";
|
import {readFileSync, writeFileSync} from "fs";
|
||||||
import {Utils} from "../Utils";
|
import {Utils} from "../Utils";
|
||||||
import ScriptUtils from "./ScriptUtils";
|
import ScriptUtils from "./ScriptUtils";
|
||||||
|
import {Layer} from "leaflet";
|
||||||
|
|
||||||
const knownLanguages = ["en", "nl", "de", "fr", "es", "gl", "ca"];
|
const knownLanguages = ["en", "nl", "de", "fr", "es", "gl", "ca"];
|
||||||
|
|
||||||
|
@ -40,12 +41,12 @@ class TranslationPart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recursiveAdd(object: any) {
|
recursiveAdd(object: any, context: string) {
|
||||||
|
|
||||||
|
|
||||||
const isProbablyTranslationObject = knownLanguages.map(l => object.hasOwnProperty(l)).filter(x => x).length > 0;
|
const isProbablyTranslationObject = knownLanguages.map(l => object.hasOwnProperty(l)).filter(x => x).length > 0;
|
||||||
if (isProbablyTranslationObject) {
|
if (isProbablyTranslationObject) {
|
||||||
this.addTranslationObject(object)
|
this.addTranslationObject(object, context)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ class TranslationPart {
|
||||||
this.contents.set(key, new TranslationPart())
|
this.contents.set(key, new TranslationPart())
|
||||||
}
|
}
|
||||||
|
|
||||||
(this.contents.get(key) as TranslationPart).recursiveAdd(v);
|
(this.contents.get(key) as TranslationPart).recursiveAdd(v, context + "." + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ function generateTranslationsObjectFrom(objects: { path: string, parsed: { id: s
|
||||||
if (config === undefined) {
|
if (config === undefined) {
|
||||||
throw "Got something not parsed! Path is " + layerFile.path
|
throw "Got something not parsed! Path is " + layerFile.path
|
||||||
}
|
}
|
||||||
layerTr.recursiveAdd(config)
|
layerTr.recursiveAdd(config, layerFile.path)
|
||||||
tr.contents.set(config.id, layerTr)
|
tr.contents.set(config.id, layerTr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +302,7 @@ function mergeThemeTranslations() {
|
||||||
|
|
||||||
const oldLanguages = config.language;
|
const oldLanguages = config.language;
|
||||||
const allTranslations = new TranslationPart();
|
const allTranslations = new TranslationPart();
|
||||||
allTranslations.recursiveAdd(config)
|
allTranslations.recursiveAdd(config, themeFile.path)
|
||||||
const newLanguages = allTranslations.knownLanguages()
|
const newLanguages = allTranslations.knownLanguages()
|
||||||
const languageDiff = newLanguages.filter(l => oldLanguages.indexOf(l) < 0).join(", ")
|
const languageDiff = newLanguages.filter(l => oldLanguages.indexOf(l) < 0).join(", ")
|
||||||
if (languageDiff !== "") {
|
if (languageDiff !== "") {
|
||||||
|
|
Loading…
Reference in a new issue