Mapillary bugfix

This commit is contained in:
Pieter Vander Vennet 2020-10-27 14:13:37 +01:00
parent 895aa132ec
commit ab2e9425c2
5 changed files with 114 additions and 111 deletions

View file

@ -130,7 +130,12 @@ export class ImageSearcher extends UIEventSource<{key: string, url: string}[]> {
} }
if (this._tags.data.mapillary) { if (this._tags.data.mapillary) {
this.AddImage(undefined,"https://www.mapillary.com/map/im/" + this._tags.data.mapillary) let mapillary = this._tags.data.mapillary;
const prefix = "https://www.mapillary.com/map/im/";
if(mapillary.indexOf(prefix) < 0){
mapillary = prefix + mapillary;
}
this.AddImage(undefined, mapillary)
} }
} }

View file

@ -1,4 +1,6 @@
import {Utils} from "../Utils"; import {Utils} from "../Utils";
import {Util} from "leaflet";
import indexOf = Util.indexOf;
export abstract class TagsFilter { export abstract class TagsFilter {
abstract matches(tags: { k: string, v: string }[]): boolean abstract matches(tags: { k: string, v: string }[]): boolean
@ -344,20 +346,31 @@ export class TagUtils {
} }
/** /**
* Given multiple tagsfilters which can be used as answer, will take the tags with the same keys together as set. * Given two hashes of {key --> values[]}, makes sure that every neededTag is present in availableTags
* E.g: */
* static AllKeysAreContained(availableTags: any, neededTags: any){
* FlattenMultiAnswer([and: [ "x=a", "y=0;1"], and: ["x=b", "y=2"], and: ["x=", "y=3"]]) for (const neededKey in neededTags) {
* will result in const availableValues : string[] = availableTags[neededKey]
* ["x=a;b", "y=0;1;2;3"] if(availableValues === undefined){
return false;
}
const neededValues : string[] = neededTags[neededKey];
for (const neededValue of neededValues) {
if(indexOf(availableValues, neededValue) < 0){
return false;
}
}
}
return true;
}
/***
* Creates a hash {key --> [values]}, with all the values present in the tagsfilter
* *
* @param tagsFilters * @param tagsFilters
* @constructor * @constructor
*/ */
static FlattenMultiAnswer(tagsFilters: TagsFilter[]): And { static SplitKeys(tagsFilters: TagsFilter[]){
if (tagsFilters === undefined) {
return new And([]);
}
const keyValues = {} // Map string -> string[] const keyValues = {} // Map string -> string[]
tagsFilters = [...tagsFilters] // copy all tagsFilters = [...tagsFilters] // copy all
while (tagsFilters.length > 0) { while (tagsFilters.length > 0) {
@ -384,91 +397,30 @@ export class TagUtils {
console.error("Invalid type to flatten the multiAnswer", tagsFilter); console.error("Invalid type to flatten the multiAnswer", tagsFilter);
throw "Invalid type to FlattenMultiAnswer" throw "Invalid type to FlattenMultiAnswer"
} }
return keyValues;
}
/**
* Given multiple tagsfilters which can be used as answer, will take the tags with the same keys together as set.
* E.g:
*
* FlattenMultiAnswer([and: [ "x=a", "y=0;1"], and: ["x=b", "y=2"], and: ["x=", "y=3"]])
* will result in
* ["x=a;b", "y=0;1;2;3"]
*
* @param tagsFilters
* @constructor
*/
static FlattenMultiAnswer(tagsFilters: TagsFilter[]): And {
if (tagsFilters === undefined) {
return new And([]);
}
let keyValues = TagUtils.SplitKeys(tagsFilters);
const and: TagsFilter[] = [] const and: TagsFilter[] = []
for (const key in keyValues) { for (const key in keyValues) {
and.push(new Tag(key, Utils.Dedup(keyValues[key]).join(";"))); and.push(new Tag(key, Utils.Dedup(keyValues[key]).join(";")));
} }
return new And(and); return new And(and);
} }
/**
* Splits the actualTags onto a list of which the values are the same as the tagsFilters.
* Leftovers are returned in the list too if there is an 'undefined' value
*/
static SplitMultiAnswer(actualTags: TagsFilter, possibleTags: TagsFilter[], freeformKey: string, freeformExtraTags: TagsFilter): TagsFilter[] {
const queue: TagsFilter[] = [actualTags]
const keyValues = {} // key ==> value[]
while (queue.length > 0) {
const tf = queue.pop();
if (tf instanceof And) {
queue.push(...tf.and);
continue;
}
if (tf instanceof Tag) {
if (keyValues[tf.key] === undefined) {
keyValues[tf.key] = []
}
keyValues[tf.key].push(...tf.value.split(";"));
continue;
}
if (tf === undefined) {
continue;
}
throw "Invalid tagfilter: " + JSON.stringify(tf)
}
const foundValues = [];
for (const possibleTag of possibleTags) {
if (possibleTag === undefined) {
continue;
}
if (possibleTag instanceof Tag) {
const key = possibleTag.key;
const actualValues: string[] = keyValues[key] ?? [];
const possibleValues = possibleTag.value.split(";");
let allPossibleValuesFound = true;
for (const possibleValue of possibleValues) {
if (actualValues.indexOf(possibleValue) < 0) {
allPossibleValuesFound = false;
}
}
if (!allPossibleValuesFound) {
continue;
}
// At this point, we know that 'possibleTag' is completely present in the tagset
// we add the possibleTag to the found values
foundValues.push(possibleTag);
for (const possibleValue of possibleValues) {
actualValues.splice(actualValues.indexOf(possibleValue), 1);
}
continue;
}
throw "Unsupported possibletag: " + JSON.stringify(possibleTag);
}
let leftoverTag = undefined;
if (keyValues[freeformKey] !== undefined && keyValues[freeformKey].length !== 0) {
leftoverTag = new Tag(freeformKey, keyValues[freeformKey].join(";"));
if (freeformExtraTags !== undefined) {
leftoverTag = new And([
leftoverTag,
freeformExtraTags
])
}
foundValues.push(leftoverTag);
}
return foundValues;
}
} }

View file

@ -18,6 +18,8 @@ import {Changes} from "../../Logic/Osm/Changes";
import {VariableUiElement} from "../Base/VariableUIElement"; import {VariableUiElement} from "../Base/VariableUIElement";
import Translations from "../i18n/Translations"; import Translations from "../i18n/Translations";
import {FixedUiElement} from "../Base/FixedUiElement"; import {FixedUiElement} from "../Base/FixedUiElement";
import {Util} from "leaflet";
import indexOf = Util.indexOf;
/** /**
* Shows the question element. * Shows the question element.
@ -112,6 +114,10 @@ export default class TagRenderingQuestion extends UIElement {
} }
private SplitMultiAnswer(tags: TagsFilter) {
}
private GenerateMultiAnswer(elements: InputElement<TagsFilter>[], freeformField: InputElement<TagsFilter>): InputElement<TagsFilter> { private GenerateMultiAnswer(elements: InputElement<TagsFilter>[], freeformField: InputElement<TagsFilter>): InputElement<TagsFilter> {
const possibleTags = elements.map(el => el.GetValue().data); const possibleTags = elements.map(el => el.GetValue().data);
const checkBoxes = new CheckBoxes(elements); const checkBoxes = new CheckBoxes(elements);
@ -128,22 +134,50 @@ export default class TagRenderingQuestion extends UIElement {
return TagUtils.FlattenMultiAnswer(tags); return TagUtils.FlattenMultiAnswer(tags);
}, },
(tags: TagsFilter) => { (tags: TagsFilter) => {
const splitUpValues = TagUtils.SplitMultiAnswer(tags, possibleTags, this._configuration.freeform?.key, new And(this._configuration.freeform?.addExtraTags)); // {key --> values[]}
const presentTags = TagUtils.SplitKeys([tags]);
const indices: number[] = [] const indices: number[] = []
// We also collect the values that have to be added to the freeform field
let freeformExtras: string[] = []
if (this._configuration.freeform?.key) {
freeformExtras = [...(presentTags[this._configuration.freeform.key] ?? [])]
}
for (let i = 0; i < splitUpValues.length; i++) { for (let j = 0; j < elements.length; j++) {
let splitUpValue = splitUpValues[i]; const inputElement = elements[j];
if (inputElement === freeformField) {
continue;
}
const val = inputElement.GetValue();
const neededTags = TagUtils.SplitKeys([val.data]);
for (let j = 0; j < elements.length; j++) { // if every 'neededKeys'-value is present in presentKeys, we have a match and enable the index
let inputElement = elements[j]; if (TagUtils.AllKeysAreContained(presentTags, neededTags)) {
if (inputElement.IsValid(splitUpValue)) { indices.push(j);
indices.push(j); if (freeformExtras.length > 0) {
inputElement.GetValue().setData(splitUpValue); const freeformsToRemove: string[] = (neededTags[this._configuration.freeform.key] ?? []);
break; for (const toRm of freeformsToRemove) {
const i = freeformExtras.indexOf(toRm);
if (i >= 0) {
freeformExtras.splice(i, 1);
}
}
} }
} }
} }
console.log(indices) console.log(indices, freeformExtras);
if (freeformField) {
if (freeformExtras.length > 0) {
freeformField.GetValue().setData(new Tag(this._configuration.freeform.key, freeformExtras.join(";")));
indices.push(indexOf(elements, freeformField))
} else {
freeformField.GetValue().setData(undefined);
}
}
return indices; return indices;
}, },
elements.map(el => el.GetValue()) elements.map(el => el.GetValue())

View file

@ -1,11 +1,10 @@
.featureinfobox-title { .featureinfobox-title {
background-color: deeppink; font-size: xx-large;
} }
.featureinfobox-icons img{ .featureinfobox-icons img{
max-height: 1.5em; max-height: 1.5em;
} }
.featureinfobox-icons { .featureinfobox-icons {
background-color: red;
} }
.featureinfobox-titlebar{ .featureinfobox-titlebar{

29
test.ts
View file

@ -6,29 +6,42 @@ import {TagRenderingConfigJson} from "./Customizations/JSON/TagRenderingConfigJs
import TagRenderingConfig from "./Customizations/JSON/TagRenderingConfig"; import TagRenderingConfig from "./Customizations/JSON/TagRenderingConfig";
import Locale from "./UI/i18n/Locale"; import Locale from "./UI/i18n/Locale";
import EditableTagRendering from "./UI/Popup/EditableTagRendering"; import EditableTagRendering from "./UI/Popup/EditableTagRendering";
import TagRenderingQuestion from "./UI/Popup/TagRenderingQuestion";
const tagRendering: TagRenderingConfigJson = { const tagRendering: TagRenderingConfigJson = {
question: {"en": "What is the name of?", nl: "Wat is de naam van?", fr: "C'est quoi le nom"}, question: {"en": "What is the name of?", nl: "Wat is de naam van?", fr: "C'est quoi le nom"},
mappings: [ mappings: [
{ {
if: "noname=yes", if: "valves=A",
then: "Has no name" then: "A"
},
{
if: "valves=B",
then: "B"
},
{
if: "valves=C",
then: "C"
}, {
if: "valves:special=A",
then: "SPecial"
} }
], ],
render: "The name is {name}", render: "Valves: {valves}",
multiAnswer: true,
freeform: { freeform: {
key: "name", key: "valves",
type: "string", type: "string",
addExtraTags: ["noname="] addExtraTags: ["fixme=valves"]
}//*/ }
} }
const config = new TagRenderingConfig(tagRendering) const config = new TagRenderingConfig(tagRendering)
const tags = new UIEventSource({id: "node/-1", "amenity": "bench", name: "pietervdvn"}) const tags = new UIEventSource({id: "node/-1", "amenity": "bench", name: "pietervdvn"})
// new TagRenderingQuestion(tags, config).AttachTo("maindiv") new TagRenderingQuestion(tags, config).AttachTo("maindiv")
new EditableTagRendering(tags, config).AttachTo('maindiv') // new EditableTagRendering(tags, config).AttachTo('maindiv')
Locale.CreateLanguagePicker(["nl", "en", "fr"]).AttachTo("extradiv") Locale.CreateLanguagePicker(["nl", "en", "fr"]).AttachTo("extradiv")
/*/ /*/