forked from MapComplete/MapComplete
First working version of the notes-layer, add filtering
This commit is contained in:
parent
ebb510da04
commit
91d2272861
19 changed files with 282 additions and 109 deletions
|
@ -22,7 +22,7 @@ export default class Constants {
|
|||
/**
|
||||
* Layer IDs of layers which have special properties through built-in hooks
|
||||
*/
|
||||
public static readonly priviliged_layers: string[] = [...Constants.added_by_default, "type_node", ...Constants.no_include]
|
||||
public static readonly priviliged_layers: string[] = [...Constants.added_by_default, "type_node", "notes", ...Constants.no_include]
|
||||
|
||||
|
||||
// The user journey states thresholds when a new feature gets unlocked
|
||||
|
|
|
@ -3,14 +3,20 @@ import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
|||
import FilterConfigJson from "./Json/FilterConfigJson";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
||||
import ValidatedTextField from "../../UI/Input/ValidatedTextField";
|
||||
import {Utils} from "../../Utils";
|
||||
import {TagRenderingConfigJson} from "./Json/TagRenderingConfigJson";
|
||||
import {AndOrTagConfigJson} from "./Json/TagConfigJson";
|
||||
|
||||
export default class FilterConfig {
|
||||
public readonly id: string
|
||||
public readonly options: {
|
||||
question: Translation;
|
||||
osmTags: TagsFilter;
|
||||
originalTagsSpec: string | AndOrTagConfigJson
|
||||
fields: { name: string, type: string }[]
|
||||
}[];
|
||||
|
||||
|
||||
constructor(json: FilterConfigJson, context: string) {
|
||||
if (json.options === undefined) {
|
||||
throw `A filter without options was given at ${context}`
|
||||
|
@ -28,23 +34,49 @@ export default class FilterConfig {
|
|||
}
|
||||
this.id = json.id;
|
||||
this.options = json.options.map((option, i) => {
|
||||
const ctx = `${context}.options[${i}]`;
|
||||
const question = Translations.T(
|
||||
option.question,
|
||||
context + ".options-[" + i + "].question"
|
||||
);
|
||||
const osmTags = TagUtils.Tag(
|
||||
option.osmTags ?? {and: []},
|
||||
`${context}.options-[${i}].osmTags`
|
||||
`${ctx}.question`
|
||||
);
|
||||
let osmTags = TagUtils.Tag(
|
||||
option.osmTags ?? {and: []},
|
||||
`${ctx}.osmTags`
|
||||
);
|
||||
|
||||
if (question === undefined) {
|
||||
throw `Invalid filter: no question given at ${context}[${i}]`
|
||||
throw `Invalid filter: no question given at ${ctx}`
|
||||
}
|
||||
|
||||
return {question: question, osmTags: osmTags};
|
||||
const fields: { name: string, type: string }[] = ((option.fields) ?? []).map((f, i) => {
|
||||
const type = f.type ?? "string"
|
||||
if (!ValidatedTextField.AllTypes.has(type)) {
|
||||
throw `Invalid filter: ${type} is not a valid validated textfield type (at ${ctx}.fields[${i}])\n\tTry one of ${Array.from(ValidatedTextField.AllTypes.keys()).join(",")}`
|
||||
}
|
||||
if (f.name === undefined || f.name === "" || f.name.match(/[a-z0-9_-]+/) == null) {
|
||||
throw `Invalid filter: a variable name should match [a-z0-9_-]+ at ${ctx}.fields[${i}]`
|
||||
}
|
||||
return {
|
||||
name: f.name,
|
||||
type
|
||||
}
|
||||
})
|
||||
|
||||
if(fields.length > 0){
|
||||
// erase the tags, they aren't needed
|
||||
osmTags = TagUtils.Tag({and:[]})
|
||||
}
|
||||
|
||||
return {question: question, osmTags: osmTags, fields, originalTagsSpec: option.osmTags};
|
||||
});
|
||||
|
||||
if (this.options.some(o => o.fields.length > 0) && this.options.length > 1) {
|
||||
throw `Invalid filter at ${context}: a filter with textfields should only offer a single option.`
|
||||
}
|
||||
|
||||
if (this.options.length > 1 && this.options[0].osmTags["and"]?.length !== 0) {
|
||||
throw "Error in " + context + "." + this.id + ": the first option of a multi-filter should always be the 'reset' option and not have any filters"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,5 +11,12 @@ export default interface FilterConfigJson {
|
|||
* If there is only one option this will be a checkbox
|
||||
* Filtering is done based on the given osmTags that are compared to the objects in that layer.
|
||||
*/
|
||||
options: { question: string | any; osmTags?: AndOrTagConfigJson | string }[];
|
||||
options: {
|
||||
question: string | any;
|
||||
osmTags?: AndOrTagConfigJson | string,
|
||||
fields?: {
|
||||
name: string,
|
||||
type?: string | "string"
|
||||
}[]
|
||||
}[];
|
||||
}
|
|
@ -111,7 +111,7 @@ export default class TagRenderingConfig {
|
|||
}
|
||||
|
||||
|
||||
if (ValidatedTextField.AllTypes[this.freeform.type] === undefined) {
|
||||
if (!ValidatedTextField.AllTypes.has(this.freeform.type)) {
|
||||
const knownKeys = ValidatedTextField.tpList.map(tp => tp.name).join(", ");
|
||||
throw `Freeform.key ${this.freeform.key} is an invalid type. Known keys are ${knownKeys}`
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export class Tiles {
|
|||
const result: T[] = []
|
||||
const total = tileRange.total
|
||||
if (total > 100000) {
|
||||
throw "Tilerange too big (z is "+tileRange.zoomlevel+")"
|
||||
throw `Tilerange too big (z is ${tileRange.zoomlevel}, total tiles needed: ${tileRange.total})`
|
||||
}
|
||||
for (let x = tileRange.xstart; x <= tileRange.xend; x++) {
|
||||
for (let y = tileRange.ystart; y <= tileRange.yend; y++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue