Refactoring of tagsFilters, fix conditional 'hideInAnswer'

This commit is contained in:
pietervdvn 2021-03-22 02:17:00 +01:00
parent f176b92a9c
commit 1ffad21c62
5 changed files with 79 additions and 68 deletions

View file

@ -97,8 +97,21 @@ export interface TagRenderingConfigJson {
* then: "Maintained by Agentschap Natuur en Bos" * then: "Maintained by Agentschap Natuur en Bos"
* hideInAnswer: true * hideInAnswer: true
* } * }
*
* Hide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate
*
* e.g.
*
*
* Also have a look for the meta-tags
*
* {
* if: "operator=Agentschap Natuur en Bos",
* then: "Maintained by Agentschap Natuur en Bos",
* hideInAnswer: "_country!=be"
* }
*/ */
hideInAnswer?: boolean, hideInAnswer?: boolean | string | AndOrTagConfigJson,
/** /**
* Only applicable if 'multiAnswer' is set. * Only applicable if 'multiAnswer' is set.
* This is for situations such as: * This is for situations such as:

View file

@ -1,7 +1,6 @@
import {Utils} from "../Utils"; import {Utils} from "../Utils";
export abstract class TagsFilter { export abstract class TagsFilter {
abstract matches(tags: { k: string, v: string }[]): boolean
abstract asOverpass(): string[] abstract asOverpass(): string[]
@ -11,13 +10,19 @@ export abstract class TagsFilter {
abstract isEquivalent(other: TagsFilter): boolean; abstract isEquivalent(other: TagsFilter): boolean;
matchesProperties(properties: Map<string, string>): boolean { abstract matchesProperties(properties: any): boolean;
return this.matches(TagUtils.proprtiesToKV(properties));
}
abstract asHumanString(linkToWiki: boolean, shorten: boolean); abstract asHumanString(linkToWiki: boolean, shorten: boolean);
abstract usedKeys(): string[]; abstract usedKeys(): string[];
public matches(tags: {k: string, v: string}[]){
const properties = {};
for (const kv of tags) {
properties[kv.k] = kv.v;
}
return this.matchesProperties(properties);
}
} }
@ -59,14 +64,15 @@ export class RegexTag extends TagsFilter {
isUsableAsAnswer(): boolean { isUsableAsAnswer(): boolean {
return false; return false;
} }
matches(tags: { k: string; v: string }[]): boolean { matchesProperties(tags: any): boolean {
for (const tag of tags) { for (const key in tags) {
if (RegexTag.doesMatch(tag.k, this.key)) { if (RegexTag.doesMatch(key, this.key)) {
return RegexTag.doesMatch(tag.v, this.value) != this.invert; const value = tags[key]
return RegexTag.doesMatch(value, this.value) != this.invert;
} }
} }
if(this.matchesEmpty){ if (this.matchesEmpty) {
// The value is 'empty' // The value is 'empty'
return !this.invert; return !this.invert;
} }
@ -123,14 +129,14 @@ export class Tag extends TagsFilter {
} }
} }
matches(tags: { k: string; v: string }[]): boolean {
matchesProperties(properties: any): boolean {
for (const tag of tags) { for (const propertiesKey in properties) {
if (this.key == tag.k) { if(this.key === propertiesKey){
return this.value === tag.v; const value = properties[propertiesKey];
return value === this.value;
} }
} }
// The tag was not found // The tag was not found
if (this.value === "") { if (this.value === "") {
// and it shouldn't be found! // and it shouldn't be found!
@ -192,10 +198,10 @@ export class Or extends TagsFilter {
super(); super();
this.or = or; this.or = or;
} }
matches(tags: { k: string; v: string }[]): boolean { matchesProperties(properties: any): boolean {
for (const tagsFilter of this.or) { for (const tagsFilter of this.or) {
if (tagsFilter.matches(tags)) { if (tagsFilter.matchesProperties(properties)) {
return true; return true;
} }
} }
@ -270,9 +276,9 @@ export class And extends TagsFilter {
return values; return values;
} }
matches(tags: { k: string; v: string }[]): boolean { matchesProperties(tags: any): boolean {
for (const tagsFilter of this.and) { for (const tagsFilter of this.and) {
if (!tagsFilter.matches(tags)) { if (!tagsFilter.matchesProperties(tags)) {
return false; return false;
} }
} }
@ -374,14 +380,6 @@ export class And extends TagsFilter {
export class TagUtils { export class TagUtils {
static proprtiesToKV(properties: any): { k: string, v: string }[] {
const result = [];
for (const k in properties) {
result.push({k: k, v: properties[k]})
}
return result;
}
static ApplyTemplate(template: string, tags: any): string { static ApplyTemplate(template: string, tags: any): string {
for (const k in tags) { for (const k in tags) {
while (template.indexOf("{" + k + "}") >= 0) { while (template.indexOf("{" + k + "}") >= 0) {

View file

@ -221,7 +221,7 @@ export default class TagRenderingQuestion extends UIElement {
if (mapping.hideInAnswer === true) { if (mapping.hideInAnswer === true) {
return undefined; return undefined;
} }
if(typeof(mapping.hideInAnswer) !== "boolean" && mapping.hideInAnswer.matches(this._tags.data)){ if(typeof(mapping.hideInAnswer) !== "boolean" && mapping.hideInAnswer.matchesProperties(this._tags.data)){
return undefined; return undefined;
} }
return new FixedInputElement( return new FixedInputElement(

View file

@ -188,7 +188,8 @@
"mappings": [ "mappings": [
{ {
"if": "operator=De Fietsambassade Gent", "if": "operator=De Fietsambassade Gent",
"then": "<a href='https://fietsambassade.gent.be/' target='_blank'>De Fietsambassade Gent</a>" "then": "<a href='https://fietsambassade.gent.be/' target='_blank'>De Fietsambassade Gent</a>",
"hideInAnswer": "_country!=be"
} }
] ]
}, },

View file

@ -27,24 +27,24 @@ new T("Tags", [
const tag = FromJSON.Tag("key=value") as Tag; const tag = FromJSON.Tag("key=value") as Tag;
equal(tag.key, "key"); equal(tag.key, "key");
equal(tag.value, "value"); equal(tag.value, "value");
equal(tag.matches([{k:"key",v:"value"}]), true) equal(tag.matchesProperties({"key":"value"}), true)
equal(tag.matches([{k:"key",v:"z"}]), false) equal(tag.matchesProperties({"key":"z"}), false)
equal(tag.matches([{k:"key",v:""}]), false) equal(tag.matchesProperties({"key":""}), false)
equal(tag.matches([{k:"other_key",v:""}]), false) equal(tag.matchesProperties({"other_key":""}), false)
equal(tag.matches([{k:"other_key",v:"value"}]), false) equal(tag.matchesProperties({"other_key":"value"}), false)
const isEmpty = FromJSON.Tag("key=") as Tag; const isEmpty = FromJSON.Tag("key=") as Tag;
equal(isEmpty.matches([{k:"key",v:"value"}]), false) equal(isEmpty.matchesProperties({"key":"value"}), false)
equal(isEmpty.matches([{k:"key",v:""}]), true) equal(isEmpty.matchesProperties({"key":""}), true)
equal(isEmpty.matches([{k:"other_key",v:""}]), true) equal(isEmpty.matchesProperties({"other_key":""}), true)
equal(isEmpty.matches([{k:"other_key",v:"value"}]), true) equal(isEmpty.matchesProperties({"other_key":"value"}), true)
const isNotEmpty = FromJSON.Tag("key!="); const isNotEmpty = FromJSON.Tag("key!=");
equal(isNotEmpty.matches([{k:"key",v:"value"}]), true) equal(isNotEmpty.matchesProperties({"key":"value"}), true)
equal(isNotEmpty.matches([{k:"key",v:"other_value"}]), true) equal(isNotEmpty.matchesProperties({"key":"other_value"}), true)
equal(isNotEmpty.matches([{k:"key",v:""}]), false) equal(isNotEmpty.matchesProperties({"key":""}), false)
equal(isNotEmpty.matches([{k:"other_key",v:""}]), false) equal(isNotEmpty.matchesProperties({"other_key":""}), false)
equal(isNotEmpty.matches([{k:"other_key",v:"value"}]), false) equal(isNotEmpty.matchesProperties({"other_key":"value"}), false)
@ -54,29 +54,29 @@ new T("Tags", [
const notReg = FromJSON.Tag("x!~y") as And; const notReg = FromJSON.Tag("x!~y") as And;
equal(notReg.matches([{k:"x",v:"y"}]), false) equal(notReg.matchesProperties({"x":"y"}), false)
equal(notReg.matches([{k:"x",v:"z"}]), true) equal(notReg.matchesProperties({"x":"z"}), true)
equal(notReg.matches([{k:"x",v:""}]), true) equal(notReg.matchesProperties({"x":""}), true)
equal(notReg.matches([]), true) equal(notReg.matchesProperties({}), true)
const noMatch = FromJSON.Tag("key!=value") as Tag; const noMatch = FromJSON.Tag("key!=value") as Tag;
equal(noMatch.matches([{k:"key",v:"value"}]), false) equal(noMatch.matchesProperties({"key":"value"}), false)
equal(noMatch.matches([{k:"key",v:"otherValue"}]), true) equal(noMatch.matchesProperties({"key":"otherValue"}), true)
equal(noMatch.matches([{k:"key",v:""}]), true) equal(noMatch.matchesProperties({"key":""}), true)
equal(noMatch.matches([{k:"otherKey",v:""}]), true) equal(noMatch.matchesProperties({"otherKey":""}), true)
const multiMatch = FromJSON.Tag("vending~.*bicycle_tube.*") as Tag; const multiMatch = FromJSON.Tag("vending~.*bicycle_tube.*") as Tag;
equal(multiMatch.matches([{k:"vending",v:"bicycle_tube"}]), true) equal(multiMatch.matchesProperties({"vending":"bicycle_tube"}), true)
equal(multiMatch.matches([{k:"vending",v:"something;bicycle_tube"}]), true) equal(multiMatch.matchesProperties({"vending":"something;bicycle_tube"}), true)
equal(multiMatch.matches([{k:"vending",v:"bicycle_tube;something"}]), true) equal(multiMatch.matchesProperties({"vending":"bicycle_tube;something"}), true)
equal(multiMatch.matches([{k:"vending",v:"xyz;bicycle_tube;something"}]), true) equal(multiMatch.matchesProperties({"vending":"xyz;bicycle_tube;something"}), true)
const nameStartsWith = FromJSON.Tag("name~[sS]peelbos.*") const nameStartsWith = FromJSON.Tag("name~[sS]peelbos.*")
equal(nameStartsWith.matches([{k:"name",v: "Speelbos Sint-Anna"}]), true) equal(nameStartsWith.matchesProperties({"name": "Speelbos Sint-Anna"}), true)
equal(nameStartsWith.matches([{k:"name",v: "speelbos Sint-Anna"}]), true) equal(nameStartsWith.matchesProperties({"name": "speelbos Sint-Anna"}), true)
equal(nameStartsWith.matches([{k:"name",v: "Sint-Anna"}]), false) equal(nameStartsWith.matchesProperties({"name": "Sint-Anna"}), false)
equal(nameStartsWith.matches([{k:"name",v: ""}]), false) equal(nameStartsWith.matchesProperties({"name": ""}), false)
})], })],
["Is equivalent test", (() => { ["Is equivalent test", (() => {
@ -143,7 +143,7 @@ new T("Tags", [
"Empty match test", "Empty match test",
() => { () => {
const t = new Tag("key",""); const t = new Tag("key","");
equal(false, t.matches([{k: "key", v:"somevalue"}])) equal(false, t.matchesProperties({ "key":"somevalue"}))
} }
], ],
[ [
@ -238,8 +238,7 @@ new T("Tags", [
equal(r.startHour,10 ); equal(r.startHour,10 );
equal(r.endHour, 12) equal(r.endHour, 12)
} }],
],
["Parse OH 1",() => { ["Parse OH 1",() => {
const rules = OH.ParseRule("11:00-19:00"); const rules = OH.ParseRule("11:00-19:00");
equal(rules.length, 7); equal(rules.length, 7);
@ -382,5 +381,5 @@ new T("Tags", [
equal(Utils.Round(-0.5), "-0.5") equal(Utils.Round(-0.5), "-0.5")
equal(Utils.Round(-1.6), "-1.6") equal(Utils.Round(-1.6), "-1.6")
}] }
]); ]]);