forked from MapComplete/MapComplete
More work on GRB theme, add 'apply_action' button
This commit is contained in:
parent
a456842773
commit
6c39f563b6
6 changed files with 275 additions and 66 deletions
|
@ -183,7 +183,7 @@ Some advanced functions are available on **feat** as well:
|
|||
### overlapWith
|
||||
|
||||
Gives a list of features from the specified layer which this feature (partly) overlaps with. If the current feature is a point, all features that embed the point are given. The returned value is `{ feat: GeoJSONFeature, overlap: number}[]` where `overlap` is the overlapping surface are (in m²) for areas, the overlapping length (in meter) if the current feature is a line or `undefined` if the current feature is a point.
|
||||
|
||||
The resulting list is sorted in descending order by overlap. The feature with the most overlap will thus be the first in the list
|
||||
For example to get all objects which overlap or embed from a layer, use `_contained_climbing_routes_properties=feat.overlapWith('climbing_route')`
|
||||
|
||||
0. ...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)
|
||||
|
|
|
@ -23,6 +23,7 @@ General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_nam
|
|||
- [canonical](#canonical)
|
||||
- [import_button](#import_button)
|
||||
- [multi_apply](#multi_apply)
|
||||
- [tag_apply](#tag_apply)
|
||||
|
||||
|
||||
|
||||
|
@ -191,6 +192,8 @@ key | _undefined_ | The key of the tag to give the canonical text for
|
|||
|
||||
This button will copy the data from an external dataset into OpenStreetMap. It is only functional in official themes but can be tested in unofficial themes.
|
||||
|
||||
#### Importing a dataset into OpenStreetMap: requirements
|
||||
|
||||
If you want to import a dataset, make sure that:
|
||||
|
||||
1. The dataset to import has a suitable license
|
||||
|
@ -199,17 +202,42 @@ If you want to import a dataset, make sure that:
|
|||
|
||||
There are also some technicalities in your theme to keep in mind:
|
||||
|
||||
1. The new point will be added and will flow through the program as any other new point as if it came from OSM.
|
||||
1. The new feature will be added and will flow through the program as any other new point as if it came from OSM.
|
||||
This means that there should be a layer which will match the new tags and which will display it.
|
||||
2. The original point from your geojson layer will gain the tag '_imported=yes'.
|
||||
2. The original feature from your geojson layer will gain the tag '_imported=yes'.
|
||||
This should be used to change the appearance or even to hide it (eg by changing the icon size to zero)
|
||||
3. There should be a way for the theme to detect previously imported points, even after reloading.
|
||||
A reference number to the original dataset is an excellen way to do this
|
||||
A reference number to the original dataset is an excellent way to do this
|
||||
4. When importing ways, the theme creator is also responsible of avoiding overlapping ways.
|
||||
|
||||
#### Disabled in unofficial themes
|
||||
|
||||
The import button can be tested in an unofficial theme by adding `test=true` or `backend=osm-test` as [URL-paramter](URL_Parameters.md).
|
||||
The import button will show up then. If in testmode, you can read the changeset-XML directly in the web console.
|
||||
In the case that MapComplete is pointed to the testing grounds, the edit will be made on https://master.apis.dev.openstreetmap.org
|
||||
|
||||
|
||||
#### Specifying which tags to copy or add
|
||||
|
||||
The first argument of the import button takes a `;`-seperated list of tags to add.
|
||||
|
||||
These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`.
|
||||
This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature.
|
||||
|
||||
If a value to substitute is undefined, empty string will be used instead.
|
||||
|
||||
This supports multiple values, e.g. `ref=$source:geometry:type/$source:geometry:ref`
|
||||
|
||||
Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with `[a-zA-Z0-9_:]*`). Sadly, delimiting with `{}` as these already mark the boundaries of the special rendering...
|
||||
|
||||
Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript)
|
||||
|
||||
|
||||
|
||||
|
||||
name | default | description
|
||||
------ | --------- | -------------
|
||||
tags | _undefined_ | Tags to copy-specification. This contains one or more pairs (seperated by a `;`), e.g. `amenity=fast_food; addr:housenumber=$number`. This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. (Hint: prepare these values, e.g. with calculatedTags)
|
||||
tags | _undefined_ | The tags to add onto the new object - see specification above
|
||||
text | Import this data into OpenStreetMap | The text to show on the button
|
||||
icon | ./assets/svg/addSmall.svg | A nice icon to show in the button
|
||||
minzoom | 18 | How far the contributor must zoom in before being able to import the point
|
||||
|
@ -233,4 +261,33 @@ overwrite | _undefined_ | If set to 'true', the tags on the other objects will a
|
|||
|
||||
#### Example usage
|
||||
|
||||
{multi_apply(_features_with_the_same_name_within_100m, name:etymology:wikidata;name:etymology, Apply etymology information on all nearby objects with the same name)} Generated from UI/SpecialVisualisations.ts
|
||||
{multi_apply(_features_with_the_same_name_within_100m, name:etymology:wikidata;name:etymology, Apply etymology information on all nearby objects with the same name)}
|
||||
|
||||
|
||||
### tag_apply
|
||||
|
||||
Shows a big button; clicking this button will apply certain tags onto the feature.
|
||||
|
||||
The first argument takes a specification of which tags to add.
|
||||
These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`.
|
||||
This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature.
|
||||
|
||||
If a value to substitute is undefined, empty string will be used instead.
|
||||
|
||||
This supports multiple values, e.g. `ref=$source:geometry:type/$source:geometry:ref`
|
||||
|
||||
Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with `[a-zA-Z0-9_:]*`). Sadly, delimiting with `{}` as these already mark the boundaries of the special rendering...
|
||||
|
||||
Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript)
|
||||
|
||||
|
||||
name | default | description
|
||||
------ | --------- | -------------
|
||||
tags_to_apply | _undefined_ | A specification of the tags to apply
|
||||
message | _undefined_ | The text to show to the contributor
|
||||
image | _undefined_ | An image to show to the contributor on the button
|
||||
id_of_object_to_apply_this_one | _undefined_ | If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element
|
||||
|
||||
#### Example usage
|
||||
|
||||
`{tag_apply(survey_date:=$_now:date, Surveyed today!)}` Generated from UI/SpecialVisualisations.ts
|
|
@ -34,6 +34,10 @@ import ShowDataLayer from "./ShowDataLayer/ShowDataLayer";
|
|||
import Link from "./Base/Link";
|
||||
import List from "./Base/List";
|
||||
import {OsmConnection} from "../Logic/Osm/OsmConnection";
|
||||
import {SubtleButton} from "./Base/SubtleButton";
|
||||
import ChangeTagAction from "../Logic/Osm/Actions/ChangeTagAction";
|
||||
import {And} from "../Logic/Tags/And";
|
||||
import Toggle from "./Input/Toggle";
|
||||
|
||||
export interface SpecialVisualization {
|
||||
funcName: string,
|
||||
|
@ -45,6 +49,17 @@ export interface SpecialVisualization {
|
|||
|
||||
export default class SpecialVisualizations {
|
||||
|
||||
private static tagsToApplyHelpText = `These can either be a tag to add, such as \`amenity=fast_food\` or can use a substitution, e.g. \`addr:housenumber=$number\`.
|
||||
This new point will then have the tags \`amenity=fast_food\` and \`addr:housenumber\` with the value that was saved in \`number\` in the original feature.
|
||||
|
||||
If a value to substitute is undefined, empty string will be used instead.
|
||||
|
||||
This supports multiple values, e.g. \`ref=$source:geometry:type/$source:geometry:ref\`
|
||||
|
||||
Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with \`[a-zA-Z0-9_:]*\`). Sadly, delimiting with \`{}\` as these already mark the boundaries of the special rendering...
|
||||
|
||||
Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript)
|
||||
`
|
||||
public static specialVisualizations: SpecialVisualization[] =
|
||||
[
|
||||
{
|
||||
|
@ -222,7 +237,6 @@ export default class SpecialVisualizations {
|
|||
return minimap;
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
funcName: "sided_minimap",
|
||||
docs: "A small map showing _only one side_ the selected feature. *This features requires to have linerenderings with offset* as only linerenderings with a postive or negative offset will be shown. Note: in most cases, this map will be automatically introduced",
|
||||
|
@ -305,14 +319,14 @@ export default class SpecialVisualizations {
|
|||
name: "key",
|
||||
defaultValue: "opening_hours",
|
||||
doc: "The tagkey from which the table is constructed."
|
||||
},{
|
||||
}, {
|
||||
name: "prefix",
|
||||
defaultValue: "",
|
||||
doc:"Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__"
|
||||
},{
|
||||
doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__"
|
||||
}, {
|
||||
name: "postfix",
|
||||
defaultValue: "",
|
||||
doc:"Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__"
|
||||
doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__"
|
||||
}],
|
||||
example: "A normal opening hours table can be invoked with `{opening_hours_table()}`. A table for e.g. conditional access with opening hours can be `{opening_hours_table(access:conditional, no @ &LPARENS, &RPARENS)}`",
|
||||
constr: (state: State, tagSource: UIEventSource<any>, args) => {
|
||||
|
@ -529,57 +543,21 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
|
||||
The first argument of the import button takes a \`;\`-seperated list of tags to add.
|
||||
|
||||
These can either be a tag to add, such as \`amenity=fast_food\` or can use a substitution, e.g. \`addr:housenumber=$number\`.
|
||||
This new point will then have the tags \`amenity=fast_food\` and \`addr:housenumber\` with the value that was saved in \`number\` in the original feature.
|
||||
|
||||
If a value to substitute is undefined, empty string will be used instead.
|
||||
|
||||
This supports multiple values, e.g. \`ref=$source:geometry:type/$source:geometry:ref\`
|
||||
|
||||
Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with \`[a-zA-Z0-9_:]*\`). Sadly, delimiting with \`{}\` as these already mark the boundaries of the special rendering...
|
||||
|
||||
Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript)
|
||||
|
||||
${SpecialVisualizations.tagsToApplyHelpText}
|
||||
|
||||
`,
|
||||
constr: (state, tagSource, args) => {
|
||||
if (!state.layoutToUse.official && !(state.featureSwitchIsTesting.data || state.osmConnection._oauth_config.url === OsmConnection.oauth_configs["osm-test"].url)) {
|
||||
return new Combine([new FixedUiElement("The import button is disabled for unofficial themes to prevent accidents.").SetClass("alert"),
|
||||
new FixedUiElement("To test, add <b>test=true</b> or <b>backend=osm-test</b> to the URL. The changeset will be printed in the console. Please open a PR to officialize this theme to actually enable the import button.")])
|
||||
}
|
||||
const tgsSpec = args[0].split(";").map(spec => {
|
||||
const kv = spec.split("=").map(s => s.trim());
|
||||
if (kv.length != 2) {
|
||||
throw "Invalid key spec: multiple '=' found in " + spec
|
||||
}
|
||||
return kv
|
||||
})
|
||||
const rewrittenTags: UIEventSource<Tag[]> = tagSource.map(tags => {
|
||||
const newTags: Tag [] = []
|
||||
for (const [key, value] of tgsSpec) {
|
||||
if (value.indexOf('$') >= 0) {
|
||||
|
||||
let parts = value.split("$")
|
||||
// THe first of the split won't start with a '$', so no substitution needed
|
||||
let actualValue = parts[0]
|
||||
parts.shift()
|
||||
|
||||
for (const part of parts) {
|
||||
const [_, varName, leftOver] = part.match(/([a-zA-Z0-9_:]*)(.*)/)
|
||||
actualValue += (tags[varName] ?? "") + leftOver
|
||||
}
|
||||
newTags.push(new Tag(key, actualValue))
|
||||
} else {
|
||||
newTags.push(new Tag(key, value))
|
||||
}
|
||||
}
|
||||
return newTags
|
||||
})
|
||||
const rewrittenTags = SpecialVisualizations.generateTagsToApply(args[0], tagSource)
|
||||
const id = tagSource.data.id;
|
||||
const feature = state.allElements.ContainingFeatures.get(id)
|
||||
const minzoom = Number(args[3])
|
||||
const message = args[1]
|
||||
const message = args[1]
|
||||
const image = args[2]
|
||||
|
||||
|
||||
return new ImportButton(
|
||||
image, message, tagSource, rewrittenTags, feature, minzoom, state
|
||||
)
|
||||
|
@ -636,12 +614,113 @@ Note that these values can be prepare with javascript in the theme by using a [c
|
|||
);
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
funcName: "tag_apply",
|
||||
docs: "Shows a big button; clicking this button will apply certain tags onto the feature.\n\nThe first argument takes a specification of which tags to add.\n" + SpecialVisualizations.tagsToApplyHelpText,
|
||||
args: [
|
||||
{
|
||||
name: "tags_to_apply",
|
||||
doc: "A specification of the tags to apply"
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
doc: "The text to show to the contributor"
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
doc: "An image to show to the contributor on the button"
|
||||
},
|
||||
{
|
||||
name: "id_of_object_to_apply_this_one",
|
||||
defaultValue: undefined,
|
||||
doc: "If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element"
|
||||
}
|
||||
],
|
||||
example: "`{tag_apply(survey_date:=$_now:date, Surveyed today!)}`",
|
||||
constr: (state, tags, args) => {
|
||||
const tagsToApply = SpecialVisualizations.generateTagsToApply(args[0], tags)
|
||||
const msg = args[1]
|
||||
let image = args[2]?.trim()
|
||||
if (image === "" || image === "undefined") {
|
||||
image = undefined
|
||||
}
|
||||
const targetIdKey = args[3]
|
||||
const t = Translations.t.general.apply_button
|
||||
|
||||
const tagsExplanation = new VariableUiElement(tagsToApply.map(tagsToApply => {
|
||||
const tagsStr = tagsToApply.map(t => t.asHumanString(false, true)).join("&");
|
||||
let el: BaseUIElement = new FixedUiElement(tagsStr)
|
||||
if(targetIdKey !== undefined){
|
||||
const targetId = tags.data[targetIdKey] ?? tags.data.id
|
||||
el = t.appliedOnAnotherObject.Subs({tags: tagsStr , id: targetId })
|
||||
}
|
||||
return el;
|
||||
}
|
||||
)).SetClass("subtle")
|
||||
|
||||
const applied = new UIEventSource(false)
|
||||
const applyButton = new SubtleButton(image, new Combine([msg, tagsExplanation]).SetClass("flex flex-col"))
|
||||
.onClick(() => {
|
||||
const targetId = tags.data[ targetIdKey] ?? tags.data.id
|
||||
const changeAction = new ChangeTagAction(targetId,
|
||||
new And(tagsToApply.data),
|
||||
tags.data, // We pass in the tags of the selected element, not the tags of the target element!
|
||||
{
|
||||
theme: state.layoutToUse.id,
|
||||
changeType: "answer"
|
||||
}
|
||||
)
|
||||
state.changes.applyAction(changeAction)
|
||||
applied.setData(true)
|
||||
})
|
||||
|
||||
|
||||
return new Toggle(
|
||||
new Toggle(
|
||||
t.isApplied.SetClass("thanks"),
|
||||
applyButton,
|
||||
applied
|
||||
)
|
||||
, undefined, state.osmConnection.isLoggedIn)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
static HelpMessage: BaseUIElement = SpecialVisualizations.GenHelpMessage();
|
||||
private static generateTagsToApply(spec: string, tagSource: UIEventSource<any>): UIEventSource<Tag[]> {
|
||||
|
||||
private static GenHelpMessage() {
|
||||
const tgsSpec = spec.split(";").map(spec => {
|
||||
const kv = spec.split("=").map(s => s.trim());
|
||||
if (kv.length != 2) {
|
||||
throw "Invalid key spec: multiple '=' found in " + spec
|
||||
}
|
||||
return kv
|
||||
})
|
||||
return tagSource.map(tags => {
|
||||
const newTags: Tag [] = []
|
||||
for (const [key, value] of tgsSpec) {
|
||||
if (value.indexOf('$') >= 0) {
|
||||
|
||||
let parts = value.split("$")
|
||||
// THe first of the split won't start with a '$', so no substitution needed
|
||||
let actualValue = parts[0]
|
||||
parts.shift()
|
||||
|
||||
for (const part of parts) {
|
||||
const [_, varName, leftOver] = part.match(/([a-zA-Z0-9_:]*)(.*)/)
|
||||
actualValue += (tags[varName] ?? "") + leftOver
|
||||
}
|
||||
newTags.push(new Tag(key, actualValue))
|
||||
} else {
|
||||
newTags.push(new Tag(key, value))
|
||||
}
|
||||
}
|
||||
return newTags
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public static HelpMessage() {
|
||||
|
||||
const helpTexts =
|
||||
SpecialVisualizations.specialVisualizations.map(viz => new Combine(
|
||||
|
@ -651,7 +730,7 @@ Note that these values can be prepare with javascript in the theme by using a [c
|
|||
viz.args.length > 0 ? new Table(["name", "default", "description"],
|
||||
viz.args.map(arg => {
|
||||
let defaultArg = arg.defaultValue ?? "_undefined_"
|
||||
if(defaultArg == ""){
|
||||
if (defaultArg == "") {
|
||||
defaultArg = "_empty string_"
|
||||
}
|
||||
return [arg.name, defaultArg, arg.doc];
|
||||
|
@ -665,9 +744,9 @@ Note that these values can be prepare with javascript in the theme by using a [c
|
|||
]
|
||||
));
|
||||
|
||||
|
||||
|
||||
const toc = new List(
|
||||
SpecialVisualizations.specialVisualizations.map(viz => new Link(viz.funcName, "#"+viz.funcName))
|
||||
SpecialVisualizations.specialVisualizations.map(viz => new Link(viz.funcName, "#" + viz.funcName))
|
||||
)
|
||||
|
||||
return new Combine([
|
||||
|
@ -679,4 +758,5 @@ Note that these values can be prepare with javascript in the theme by using a [c
|
|||
]
|
||||
).SetClass("flex flex-col");
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,8 @@
|
|||
"nl": "Grb Fixup"
|
||||
},
|
||||
"description": {
|
||||
"nl": "GRB Fixup"
|
||||
"nl": "GRB Fixup",
|
||||
"en": "This theme is an attempt to help automating the GRB import.<br/>Note that this is very hacky and 'steals' the GRB data from an external site; in order to do this, you need to install and activate <a href='https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/'>this firefox extension</a> for it to work."
|
||||
},
|
||||
"language": [
|
||||
"nl"
|
||||
|
@ -23,6 +24,9 @@
|
|||
"clustering": {
|
||||
"maxZoom": 15
|
||||
},
|
||||
"overrideAll": {
|
||||
"minzoom": 18
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"id": "OSM-buildings",
|
||||
|
@ -31,7 +35,6 @@
|
|||
"osmTags": "building~*",
|
||||
"maxCacheAge": 0
|
||||
},
|
||||
"minzoom": 16,
|
||||
"mapRendering": [
|
||||
{
|
||||
"width": {
|
||||
|
@ -67,6 +70,55 @@
|
|||
],
|
||||
"title": "OSM-gebouw",
|
||||
"tagRenderings": [
|
||||
{
|
||||
"id": "building type",
|
||||
"freeform": {
|
||||
"key": "building"
|
||||
},
|
||||
"render": "The building type is <b>{building}</b>",
|
||||
"mappings": [
|
||||
{
|
||||
"if": "building=house",
|
||||
"then": "A normal house"
|
||||
},
|
||||
{
|
||||
"if": "building=detached",
|
||||
"then": "A house detached from other building"
|
||||
},
|
||||
{
|
||||
"if": "building=semidetached_house",
|
||||
"then": "A house sharing only one wall with another house"
|
||||
},
|
||||
{
|
||||
"if": "building=apartments",
|
||||
"then": "An apartment building - highrise for living"
|
||||
},
|
||||
{
|
||||
"if": "building=office",
|
||||
"then": "An office building - highrise for work"
|
||||
},
|
||||
{
|
||||
"if": "building=apartments",
|
||||
"then": "An apartment building"
|
||||
},
|
||||
{
|
||||
"if": "building=shed",
|
||||
"then": "A small shed, e.g. in a garden"
|
||||
},
|
||||
{
|
||||
"if": "building=garage",
|
||||
"then": "A single garage to park a car"
|
||||
},
|
||||
{
|
||||
"if": "building=garages",
|
||||
"then": "A building containing only garages; typically they are all identical"
|
||||
},
|
||||
{
|
||||
"if": "building=yes",
|
||||
"then": "A building - no specification"
|
||||
}
|
||||
]
|
||||
},
|
||||
"all_tags"
|
||||
]
|
||||
},
|
||||
|
@ -99,7 +151,6 @@
|
|||
},
|
||||
"maxCacheAge": 0
|
||||
},
|
||||
"minzoom": 18,
|
||||
"mapRendering": [
|
||||
{
|
||||
"color": {
|
||||
|
@ -124,7 +175,6 @@
|
|||
"name": {
|
||||
"nl": "Fixmes op gebouwen"
|
||||
},
|
||||
"minzoom": 21,
|
||||
"source": {
|
||||
"maxCacheAge": 0,
|
||||
"osmTags": {
|
||||
|
@ -314,7 +364,6 @@
|
|||
"geoJsonZoomLevel": 18,
|
||||
"maxCacheAge": 0
|
||||
},
|
||||
"minzoom": 16,
|
||||
"name": "CRAB-addressen",
|
||||
"title": "CRAB-adres",
|
||||
"mapRendering": [
|
||||
|
@ -372,7 +421,6 @@
|
|||
"name": {
|
||||
"nl": "Fixmes op gebouwen"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
"maxCacheAge": 0,
|
||||
"osmTags": {
|
||||
|
@ -563,7 +611,6 @@
|
|||
},
|
||||
"name": "GRB geometries",
|
||||
"title": "GRB outline",
|
||||
"minzoom": 16,
|
||||
"calculatedTags": [
|
||||
"_overlaps_with=feat.overlapWith('OSM-buildings').filter(f => f.overlap > 1 && (feat.get('_surface') < 20 || f.overlap / feat.get('_surface')) > 0.9)[0] ?? null",
|
||||
"_overlap_absolute=feat.get('_overlaps_with')?.overlap",
|
||||
|
@ -587,6 +634,26 @@
|
|||
"render": "<div>The overlapping openstreetmap-building is a <b>{_osm_obj:building}</b> and covers <b>{_overlap_percentage}%</b> of the GRB building<div><h3>GRB geometry:</h3>{minimap(21, id):height:10rem;border-radius:1rem;overflow:hidden}<h3>OSM geometry:</h3>{minimap(21,_osm_obj:id):height:10rem;border-radius:1rem;overflow:hidden}",
|
||||
"condition": "_overlaps_with!=null"
|
||||
},
|
||||
{
|
||||
"id": "apply-id",
|
||||
"render": "{tag_apply(source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref,Mark the OSM-building as imported,,_osm_obj:id)}",
|
||||
"condition": {
|
||||
"and": [
|
||||
"_overlaps_with!=null"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "apply-building-type",
|
||||
"render": "{tag_apply(building=$building,Use the building type from GRB,,_osm_obj:id)}",
|
||||
"condition": {
|
||||
"and": [
|
||||
"_overlaps_with!=null",
|
||||
"_osm_obj:building=yes",
|
||||
"building!=yes"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Import-button",
|
||||
"render": "{import_button(building=$building; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref, Upload this building to OpenStreetMap)}",
|
||||
|
@ -594,7 +661,8 @@
|
|||
{
|
||||
"if": "_overlaps_with!=null",
|
||||
"then": "Cannot be imported directly, there is a nearly identical building geometry in OpenStreetMap"
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
"all_tags"
|
||||
],
|
||||
|
|
|
@ -131,6 +131,10 @@
|
|||
"previouslyHiddenTitle": "Previously visited hidden themes",
|
||||
"hiddenExplanation": "These themes are only visible if you know the link. You have discovered {hidden_discovered} out of {total_hidden} hidden themes"
|
||||
},
|
||||
"apply_button": {
|
||||
"isApplied": "The changes are applied",
|
||||
"appliedOnAnotherObject": "The object {id} will receive {tags}"
|
||||
},
|
||||
"sharescreen": {
|
||||
"intro": "<h3>Share this map</h3> Share this map by copying the link below and sending it to friends and family:",
|
||||
"addToHomeScreen": "<h3>Add to your home screen</h3>You can easily add this website to your smartphone home screen for a native feel. Click the 'add to home screen' button in the URL bar to do this.",
|
||||
|
|
|
@ -22,7 +22,7 @@ function WriteFile(filename, html: string | BaseUIElement, autogenSource: string
|
|||
]).AsMarkdown());
|
||||
}
|
||||
|
||||
WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage, ["UI/SpecialVisualisations.ts"])
|
||||
WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), ["UI/SpecialVisualisations.ts"])
|
||||
WriteFile("./Docs/CalculatedTags.md", new Combine([SimpleMetaTagger.HelpText(), ExtraFunction.HelpText()]).SetClass("flex-col"),
|
||||
["SimpleMetaTagger", "ExtraFunction"])
|
||||
WriteFile("./Docs/SpecialInputElements.md", ValidatedTextField.HelpText(), ["ValidatedTextField.ts"]);
|
||||
|
|
Loading…
Reference in a new issue