diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts index 2effce698..d3ae11ac8 100644 --- a/Logic/FeatureSource/FeaturePipeline.ts +++ b/Logic/FeatureSource/FeaturePipeline.ts @@ -210,7 +210,11 @@ export default class FeaturePipeline { handleTile: tile => { new RegisteringAllFromFeatureSourceActor(tile) if (tile.layer.layerDef.maxAgeOfCache > 0) { - self.localStorageSavers.get(tile.layer.layerDef.id).addTile(tile) + const saver = self.localStorageSavers.get(tile.layer.layerDef.id) + if(saver === undefined){ + console.error("No localStorageSaver found for layer ",tile.layer.layerDef.id) + } + saver?.addTile(tile) } perLayerHierarchy.get(tile.layer.layerDef.id).registerTile(tile) tile.features.addCallbackAndRunD(_ => self.newDataLoadedSignal.setData(tile)) diff --git a/Models/ThemeConfig/PointRenderingConfig.ts b/Models/ThemeConfig/PointRenderingConfig.ts index 8e047c24b..44d9f2c99 100644 --- a/Models/ThemeConfig/PointRenderingConfig.ts +++ b/Models/ThemeConfig/PointRenderingConfig.ts @@ -47,7 +47,7 @@ export default class PointRenderingConfig extends WithContextLoader { if (this.location.size == 0) { throw "A pointRendering should have at least one 'location' to defined where it should be rendered. (At " + context + ".location)" } - this.icon = this.tr("icon", ""); + this.icon = this.tr("icon", undefined); this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => { let tr: TagRenderingConfig; if (typeof overlay.then === "string" && @@ -65,8 +65,8 @@ export default class PointRenderingConfig extends WithContextLoader { }; }); - const iconPath = this.icon.GetRenderValue({id: "node/-1"}).txt; - if (iconPath.startsWith(Utils.assets_path)) { + const iconPath = this.icon?.GetRenderValue({id: "node/-1"})?.txt; + if (iconPath !== undefined && iconPath.startsWith(Utils.assets_path)) { const iconKey = iconPath.substr(Utils.assets_path.length); if (Svg.All[iconKey] === undefined) { throw "Builtin SVG asset not found: " + iconPath; @@ -200,7 +200,8 @@ export default class PointRenderingConfig extends WithContextLoader { } - const iconAndBadges = new Combine([this.GetSimpleIcon(tags), this.GetBadges(tags)]) + const icon = this.GetSimpleIcon(tags) + const iconAndBadges = new Combine([, this.GetBadges(tags)]) .SetClass("block relative") if (!options?.noSize) { @@ -208,9 +209,21 @@ export default class PointRenderingConfig extends WithContextLoader { } else { iconAndBadges.SetClass("w-full h-full") } + + let label = this.GetLabel(tags) + let htmlEl : BaseUIElement; + if(icon === undefined && label === undefined){ + htmlEl = undefined + }else if(icon === undefined){ + htmlEl = label + }else if(label === undefined){ + htmlEl = iconAndBadges + }else { + htmlEl = new Combine([iconAndBadges, label]).SetStyle("flex flex-col") + } return { - html: new Combine([iconAndBadges, this.GetLabel(tags)]).SetStyle("flex flex-col"), + html: htmlEl, iconSize: [iconW, iconH], iconAnchor: [anchorW, anchorH], popupAnchor: [0, 3 - anchorH], diff --git a/UI/AllThemesGui.ts b/UI/AllThemesGui.ts index 0113ddbc1..3c83e2a49 100644 --- a/UI/AllThemesGui.ts +++ b/UI/AllThemesGui.ts @@ -8,6 +8,8 @@ import {Utils} from "../Utils"; import LanguagePicker from "./LanguagePicker"; import IndexText from "./BigComponents/IndexText"; import FeaturedMessage from "./BigComponents/FeaturedMessage"; +import Toggle from "./Input/Toggle"; +import {SubtleButton} from "./Base/SubtleButton"; export default class AllThemesGui { constructor() { @@ -15,16 +17,22 @@ export default class AllThemesGui { try { new FixedUiElement("").AttachTo("centermessage") - const state = new UserRelatedState(undefined, undefined); + const state = new UserRelatedState(undefined); const intro = new Combine([ + LanguagePicker.CreateLanguagePicker(Translations.t.index.title.SupportedLanguages()) - .SetClass("absolute top-2 right-3"), + + .SetClass("flex absolute top-2 right-3"), new IndexText() ]); new Combine([ intro, new FeaturedMessage(), new MoreScreen(state, true), + new Toggle( + undefined, + new SubtleButton(undefined, Translations.t.index.logIn).SetStyle("height:min-content").onClick(() => state.osmConnection.AttemptLogin()), + state.osmConnection.isLoggedIn), Translations.t.general.aboutMapcomplete .Subs({"osmcha_link": Utils.OsmChaLinkFor(7)}) .SetClass("link-underline"), diff --git a/UI/BigComponents/FeaturedMessage.ts b/UI/BigComponents/FeaturedMessage.ts index aede8e416..508f1be0c 100644 --- a/UI/BigComponents/FeaturedMessage.ts +++ b/UI/BigComponents/FeaturedMessage.ts @@ -33,16 +33,11 @@ export default class FeaturedMessage extends Combine { public static WelcomeMessages(): { start_date: Date, end_date: Date, message: string, featured_theme?: string }[] { const all_messages: { start_date: Date, end_date: Date, message: string, featured_theme?: string }[] = [] - console.log("Constructing the list...", welcome_messages) for (const i in welcome_messages) { - console.log(i) if (isNaN(Number(i))) { continue } - console.log("> ", i) const wm = welcome_messages[i] - console.log(wm) - if (wm === null) { continue } diff --git a/assets/layers/type_node/type_node.json b/assets/layers/type_node/type_node.json index 4609041ed..7f9228a51 100644 --- a/assets/layers/type_node/type_node.json +++ b/assets/layers/type_node/type_node.json @@ -3,7 +3,8 @@ "description": "This is a priviliged meta_layer which exports _every_ point in OSM. This only works if zoomed below the point that the full tile is loaded (and not loaded via Overpass). Note that this point will also contain a property `parent_ways` which contains all the ways this node is part of as a list. This is mainly used for extremely specialized themes, which do advanced conflations. Expert use only.", "minzoom": 18, "source": { - "osmTags": "id~node/.*" + "osmTags": "id~node/.*", + "maxCacheAge": 0 }, "mapRendering": null, "name": "All OSM Nodes", diff --git a/assets/themes/grb_import/grb.json b/assets/themes/grb_import/grb.json index 0d6bd41bf..444d0b195 100644 --- a/assets/themes/grb_import/grb.json +++ b/assets/themes/grb_import/grb.json @@ -28,9 +28,194 @@ "overrideAll": { "minzoom": 18 }, - "trackAllNodes": true, "enableGeolocation": false, "layers": [ + { + "id": "osm-fixmes", + "name": { + "nl": "Fixmes op gebouwen" + }, + "passAllFeatures": true, + "source": { + "maxCacheAge": 0, + "osmTags": { + "and": [ + "fixme~*", + "building~*" + ] + } + }, + "calculatedTags": [ + "_grbNumber=(feat.properties.fixme?.match(/GRB thinks that this has number ([^;]+)/ ) ?? ['','none']) [1]" + ], + "title": { + "render": { + "nl": "{addr:street} {addr:housenumber}" + }, + "mappings": [ + { + "if": { + "and": [ + "fixme~*" + ] + }, + "then": { + "nl": "{fixme}" + } + } + ] + }, + "description": { + "nl": "Dit gebouw heeft een foutmelding" + }, + "tagRenderings": [ + { + "id": "grb-housenumber", + "render": { + "nl": "Het huisnummer is {addr:housenumber}" + }, + "question": { + "nl": "Wat is het huisnummer?" + }, + "freeform": { + "key": "addr:housenumber" + }, + "mappings": [ + { + "if": { + "and": [ + "not:addr:housenumber=yes", + "addr:housenumber=" + ] + }, + "then": { + "nl": "Geen huisnummer" + } + }, + { + "if": { + "and": [ + "addr:housenumber:={_grbNumber}", + "fixme=" + ] + }, + "then": "Het huisnummer is {_grbNumber}, wat overeenkomt met het GRB", + "hideInAnswer": { + "or": [ + "_grbNumber=", + "_grbNumber=none", + "_grbNumber=no number" + ] + } + }, + { + "if": { + "and": [ + "addr:housenumber=", + "not:addr:housenumber=yes", + "fixme=" + ] + }, + "then": "Dit gebouw heeft geen nummer, net zoals in het GRB", + "hideInAnswer": "_grbNumber!=no number" + } + ] + }, + { + "id": "grb-unit", + "question": "Wat is de wooneenheid-aanduiding?", + "render": { + "nl": "De wooneenheid-aanduiding is {addr:unit} " + }, + "freeform": { + "key": "addr:unit" + }, + "mappings": [ + { + "if": "addr:unit=", + "then": "Geen wooneenheid-nummer" + } + ] + }, + { + "id": "grb-street", + "render": { + "nl": "De straat is {addr:street}" + }, + "freeform": { + "key": "addr:street" + }, + "question": { + "nl": "Wat is de straat?" + } + }, + { + "id": "grb-fixme", + "render": { + "nl": "De fixme is {fixme}" + }, + "question": { + "nl": "Wat zegt de fixme?" + }, + "freeform": { + "key": "fixme" + }, + "mappings": [ + { + "if": { + "and": [ + "fixme=" + ] + }, + "then": { + "nl": "Geen fixme" + } + } + ] + }, + { + "id": "grb-min-level", + "render": { + "nl": "Dit gebouw begint maar op de {building:min_level} verdieping" + }, + "question": { + "nl": "Hoeveel verdiepingen ontbreken?" + }, + "freeform": { + "key": "building:min_level", + "type": "pnat" + } + } + ], + "mapRendering": [ + { + "location": [ + "point", + "centroid" + ], + "label": { + "mappings": [ + { + "if": "addr:housenumber~*", + "then": "
{addr:housenumber}
" + } + ] + }, + "iconSize": { + "render": "40,40,center" + } + }, + { + "dashArray": "2 2", + "color": { + "render": "#00f" + }, + "width": { + "render": "2" + } + } + ] + }, { "builtin": "type_node", "isShown": { @@ -197,191 +382,6 @@ "all_tags" ] }, - { - "id": "osm-fixmes", - "name": { - "nl": "Fixmes op gebouwen" - }, - "source": { - "maxCacheAge": 0, - "osmTags": { - "and": [ - "fixme~*", - "building~*" - ] - } - }, - "calculatedTags": [ - "_grbNumber=(feat.properties.fixme?.match(/GRB thinks that this has number ([^;]+)/ ) ?? ['','none']) [1]" - ], - "title": { - "render": { - "nl": "{addr:street} {addr:housenumber}" - }, - "mappings": [ - { - "if": { - "and": [ - "fixme~*" - ] - }, - "then": { - "nl": "{fixme}" - } - } - ] - }, - "description": { - "nl": "Dit gebouw heeft een foutmelding" - }, - "tagRenderings": [ - { - "id": "grb-housenumber", - "render": { - "nl": "Het huisnummer is {addr:housenumber}" - }, - "question": { - "nl": "Wat is het huisnummer?" - }, - "freeform": { - "key": "addr:housenumber" - }, - "mappings": [ - { - "if": { - "and": [ - "not:addr:housenumber=yes", - "addr:housenumber=" - ] - }, - "then": { - "nl": "Geen huisnummer" - } - }, - { - "if": { - "and": [ - "addr:housenumber:={_grbNumber}", - "fixme=" - ] - }, - "then": "Het huisnummer is {_grbNumber}, wat overeenkomt met het GRB", - "hideInAnswer": { - "or": [ - "_grbNumber=", - "_grbNumber=none", - "_grbNumber=no number" - ] - } - }, - { - "if": { - "and": [ - "addr:housenumber=", - "not:addr:housenumber=yes", - "fixme=" - ] - }, - "then": "Dit gebouw heeft geen nummer, net zoals in het GRB", - "hideInAnswer": "_grbNumber!=no number" - } - ] - }, - { - "id": "grb-unit", - "question": "Wat is de wooneenheid-aanduiding?", - "render": { - "nl": "De wooneenheid-aanduiding is {addr:unit} " - }, - "freeform": { - "key": "addr:unit" - }, - "mappings": [ - { - "if": "addr:unit=", - "then": "Geen wooneenheid-nummer" - } - ] - }, - { - "id": "grb-street", - "render": { - "nl": "De straat is {addr:street}" - }, - "freeform": { - "key": "addr:street" - }, - "question": { - "nl": "Wat is de straat?" - } - }, - { - "id": "grb-fixme", - "render": { - "nl": "De fixme is {fixme}" - }, - "question": { - "nl": "Wat zegt de fixme?" - }, - "freeform": { - "key": "fixme" - }, - "mappings": [ - { - "if": { - "and": [ - "fixme=" - ] - }, - "then": { - "nl": "Geen fixme" - } - } - ] - }, - { - "id": "grb-min-level", - "render": { - "nl": "Dit gebouw begint maar op de {building:min_level} verdieping" - }, - "question": { - "nl": "Hoeveel verdiepingen ontbreken?" - }, - "freeform": { - "key": "building:min_level", - "type": "pnat" - } - } - ], - "mapRendering": [ - { - "location": [ - "point", - "centroid" - ], - "label": { - "mappings": [ - { - "if": "addr:housenumber~*", - "then": "
{addr:housenumber}
" - } - ] - }, - "iconSize": { - "render": "40,40,center" - } - }, - { - "dashes": "2 2", - "color": { - "render": "#00f" - }, - "width": { - "render": "2" - } - } - ] - }, { "id": "crab-addresses 2021-10-26", "source": { @@ -450,190 +450,6 @@ } ] }, - { - "id": "grb-fixmes", - "name": { - "nl": "Fixmes op gebouwen" - }, - "source": { - "maxCacheAge": 0, - "osmTags": { - "and": [ - "fixme~*", - "building~*" - ] - } - }, - "calculatedTags": [ - "_grbNumber=(feat.properties.fixme?.match(/GRB thinks that this has number ([^;]+)/ ) ?? ['','none']) [1]" - ], - "title": { - "render": { - "nl": "{addr:street} {addr:housenumber}" - }, - "mappings": [ - { - "if": { - "and": [ - "fixme~*" - ] - }, - "then": { - "nl": "{fixme}" - } - } - ] - }, - "description": { - "nl": "Dit gebouw heeft een foutmelding" - }, - "tagRenderings": [ - { - "id": "grb-housenumber", - "render": { - "nl": "Het huisnummer is {addr:housenumber}" - }, - "question": { - "nl": "Wat is het huisnummer?" - }, - "freeform": { - "key": "addr:housenumber" - }, - "mappings": [ - { - "if": { - "and": [ - "not:addr:housenumber=yes", - "addr:housenumber=" - ] - }, - "then": { - "nl": "Geen huisnummer" - } - }, - { - "if": { - "and": [ - "addr:housenumber:={_grbNumber}", - "fixme=" - ] - }, - "then": "Het huisnummer is {_grbNumber}, wat overeenkomt met het GRB", - "hideInAnswer": { - "or": [ - "_grbNumber=", - "_grbNumber=none", - "_grbNumber=no number" - ] - } - }, - { - "if": { - "and": [ - "addr:housenumber=", - "not:addr:housenumber=yes", - "fixme=" - ] - }, - "then": "Dit gebouw heeft geen nummer, net zoals in het GRB", - "hideInAnswer": "_grbNumber!=no number" - } - ] - }, - { - "id": "grb-unit", - "question": "Wat is de wooneenheid-aanduiding?", - "render": { - "nl": "De wooneenheid-aanduiding is {addr:unit} " - }, - "freeform": { - "key": "addr:unit" - }, - "mappings": [ - { - "if": "addr:unit=", - "then": "Geen wooneenheid-nummer" - } - ] - }, - { - "id": "grb-street", - "render": { - "nl": "De straat is {addr:street}" - }, - "freeform": { - "key": "addr:street" - }, - "question": { - "nl": "Wat is de straat?" - } - }, - { - "id": "grb-fixme", - "render": { - "nl": "De fixme is {fixme}" - }, - "question": { - "nl": "Wat zegt de fixme?" - }, - "freeform": { - "key": "fixme" - }, - "mappings": [ - { - "if": { - "and": [ - "fixme=" - ] - }, - "then": { - "nl": "Geen fixme" - } - } - ] - }, - { - "id": "grb-min-level", - "render": { - "nl": "Dit gebouw begint maar op de {building:min_level} verdieping" - }, - "question": { - "nl": "Hoeveel verdiepingen ontbreken?" - }, - "freeform": { - "key": "building:min_level", - "type": "pnat" - } - } - ], - "mapRendering": [ - { - "location": [ - "point", - "centroid" - ], - "iconSize": { - "render": "40,40,center" - }, - "label": { - "mappings": [ - { - "if": "addr:housenumber~*", - "then": "
{addr:housenumber}
" - } - ] - } - }, - { - "width": { - "render": "2" - }, - "color": { - "render": "#00f" - } - } - ] - }, { "id": "GRB", "source": { diff --git a/langs/en.json b/langs/en.json index b6088e213..59be9ebaa 100644 --- a/langs/en.json +++ b/langs/en.json @@ -28,7 +28,8 @@ "title": "Welcome to MapComplete", "featuredThemeTitle": "Featured this week", "intro": "MapComplete is an OpenStreetMap-viewer and editor, which shows you information about features of a specific theme and allows to update it.", - "pickTheme": "Pick a theme below to get started." + "pickTheme": "Pick a theme below to get started.", + "logIn": "Log in to see other themes you previously visited" }, "split": { "split": "Split", diff --git a/langs/themes/de.json b/langs/themes/de.json index ff1dd3d63..07f704334 100644 --- a/langs/themes/de.json +++ b/langs/themes/de.json @@ -581,6 +581,25 @@ "shortDescription": "Eine Karte zum Ansehen und Bearbeiten verschiedener Elementen der Fahrradinfrastruktur.", "title": "Fahrradinfrastruktur" }, + "cyclenodes": { + "description": "Diese Karte zeigt Knotenpunktnetzwerke für Radfahrer und erlaubt auch neue Knoten zu mappen", + "layers": { + "1": { + "presets": { + "0": { + "title": "Knotenpunkt" + }, + "1": { + "title": "Knotenpunkt im Netzwerk Spree-Neiße" + } + }, + "title": { + "render": "Knotenpunkt" + } + } + }, + "title": "Fahrrad-Knotenpunktnetzwerke" + }, "cyclestreets": { "description": "Eine Fahrradstraße ist eine Straße, auf der motorisierter Verkehr Radfahrer nicht überholen darf. Sie sind durch ein spezielles Verkehrsschild gekennzeichnet. Fahrradstraßen gibt es in den Niederlanden und Belgien, aber auch in Deutschland und Frankreich. ", "layers": { diff --git a/langs/themes/en.json b/langs/themes/en.json index 84ceba6a3..60d838d9c 100644 --- a/langs/themes/en.json +++ b/langs/themes/en.json @@ -609,6 +609,45 @@ "shortDescription": "A map where you can view and edit things related to the bicycle infrastructure.", "title": "Bicycle infrastructure" }, + "cyclenodes": { + "description": "This map shows cycle node networks and allows you to add new nodes easily", + "layers": { + "0": { + "name": "node to node links", + "tagRenderings": { + "node2node-survey:date": { + "question": "When was this node to node link last surveyed?", + "render": "This node to node link was last surveyed on {survey:date}" + } + }, + "title": { + "mappings": { + "0": { + "then": "node to node link {ref}" + } + }, + "render": "node to node link" + } + }, + "1": { + "name": "nodes", + "tagRenderings": { + "node-expected_rcn_route_relations": { + "question": "How many other cycle nodes does this node link to?", + "render": "This node links to {expected_rcn_route_relations} other cycle nodes." + }, + "node-survey:date": { + "question": "When was this cycle node last surveyed?", + "render": "This cycle node was last surveyed on {survey:date}" + } + }, + "title": { + "render": "cycle node {rcn_ref}" + } + } + }, + "title": "Cycle Node Networks" + }, "cyclestreets": { "description": "A cyclestreet is is a street where motorized traffic is not allowed to overtake cyclists. They are signposted by a special traffic sign. Cyclestreets can be found in the Netherlands and Belgium, but also in Germany and France. ", "layers": { @@ -795,7 +834,7 @@ "grb": { "description": "This theme is an attempt to help automating the GRB import.
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 this firefox extension for it to work.", "layers": { - "1": { + "2": { "tagRenderings": { "building type": { "question": "What kind of building is this?" diff --git a/langs/themes/nl.json b/langs/themes/nl.json index 583b80ef4..63cc77941 100644 --- a/langs/themes/nl.json +++ b/langs/themes/nl.json @@ -753,7 +753,7 @@ "grb": { "description": "GRB Fixup", "layers": { - "3": { + "0": { "description": "Dit gebouw heeft een foutmelding", "name": "Fixmes op gebouwen", "tagRenderings": {