Reformat all files with prettier

This commit is contained in:
Pieter Vander Vennet 2022-09-08 21:40:48 +02:00
parent e22d189376
commit b541d3eab4
382 changed files with 50893 additions and 35566 deletions

View file

@ -1,29 +1,39 @@
import {Translation, TypedTranslation} from "../../UI/i18n/Translation";
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
import Translations from "../../UI/i18n/Translations";
import {TagUtils, UploadableTag} from "../../Logic/Tags/TagUtils";
import {And} from "../../Logic/Tags/And";
import ValidatedTextField from "../../UI/Input/ValidatedTextField";
import {Utils} from "../../Utils";
import {Tag} from "../../Logic/Tags/Tag";
import BaseUIElement from "../../UI/BaseUIElement";
import Combine from "../../UI/Base/Combine";
import Title from "../../UI/Base/Title";
import Link from "../../UI/Base/Link";
import List from "../../UI/Base/List";
import {MappingConfigJson, QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson";
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
import {Paragraph} from "../../UI/Base/Paragraph";
import { Translation, TypedTranslation } from "../../UI/i18n/Translation"
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import Translations from "../../UI/i18n/Translations"
import { TagUtils, UploadableTag } from "../../Logic/Tags/TagUtils"
import { And } from "../../Logic/Tags/And"
import ValidatedTextField from "../../UI/Input/ValidatedTextField"
import { Utils } from "../../Utils"
import { Tag } from "../../Logic/Tags/Tag"
import BaseUIElement from "../../UI/BaseUIElement"
import Combine from "../../UI/Base/Combine"
import Title from "../../UI/Base/Title"
import Link from "../../UI/Base/Link"
import List from "../../UI/Base/List"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "./Json/QuestionableTagRenderingConfigJson"
import { FixedUiElement } from "../../UI/Base/FixedUiElement"
import { Paragraph } from "../../UI/Base/Paragraph"
export interface Mapping {
readonly if: UploadableTag,
readonly ifnot?: UploadableTag,
readonly then: TypedTranslation<object>,
readonly icon: string,
readonly iconClass: string | "small" | "medium" | "large" | "small-height" | "medium-height" | "large-height",
readonly if: UploadableTag
readonly ifnot?: UploadableTag
readonly then: TypedTranslation<object>
readonly icon: string
readonly iconClass:
| string
| "small"
| "medium"
| "large"
| "small-height"
| "medium-height"
| "large-height"
readonly hideInAnswer: boolean | TagsFilter
readonly addExtraTags: Tag[],
readonly searchTerms?: Record<string, string[]>,
readonly addExtraTags: Tag[]
readonly searchTerms?: Record<string, string[]>
readonly priorityIf?: TagsFilter
}
@ -32,52 +42,49 @@ export interface Mapping {
* Identical data, but with some methods and validation
*/
export default class TagRenderingConfig {
public readonly id: string;
public readonly group: string;
public readonly render?: TypedTranslation<object>;
public readonly question?: TypedTranslation<object>;
public readonly condition?: TagsFilter;
public readonly description?: Translation;
public readonly id: string
public readonly group: string
public readonly render?: TypedTranslation<object>
public readonly question?: TypedTranslation<object>
public readonly condition?: TagsFilter
public readonly description?: Translation
public readonly configuration_warnings: string[] = []
public readonly freeform?: {
readonly key: string,
readonly type: string,
readonly placeholder: Translation,
readonly addExtraTags: UploadableTag[];
readonly inline: boolean,
readonly default?: string,
readonly key: string
readonly type: string
readonly placeholder: Translation
readonly addExtraTags: UploadableTag[]
readonly inline: boolean
readonly default?: string
readonly helperArgs?: (string | number | boolean)[]
};
}
public readonly multiAnswer: boolean;
public readonly multiAnswer: boolean
public readonly mappings?: Mapping[]
public readonly labels: string[]
constructor(json: string | QuestionableTagRenderingConfigJson, context?: string) {
if (json === undefined) {
throw "Initing a TagRenderingConfig with undefined in " + context;
throw "Initing a TagRenderingConfig with undefined in " + context
}
if (json === "questions") {
// Very special value
this.render = null;
this.question = null;
this.condition = null;
this.render = null
this.question = null
this.condition = null
this.id = "questions"
this.group = ""
return;
return
}
if (typeof json === "number") {
json = "" + json
}
let translationKey = context;
let translationKey = context
if (json["id"] !== undefined) {
const layerId = context.split(".")[0]
if (json["source"]) {
@ -91,43 +98,54 @@ export default class TagRenderingConfig {
}
}
if (typeof json === "string") {
this.render = Translations.T(json, translationKey + ".render");
this.multiAnswer = false;
return;
this.render = Translations.T(json, translationKey + ".render")
this.multiAnswer = false
return
}
this.id = json.id ?? ""; // Some tagrenderings - especially for the map rendering - don't need an ID
this.id = json.id ?? "" // Some tagrenderings - especially for the map rendering - don't need an ID
if (this.id.match(/^[a-zA-Z0-9 ()?\/=:;,_-]*$/) === null) {
throw "Invalid ID in " + context + ": an id can only contain [a-zA-Z0-0_-] as characters. The offending id is: " + this.id
throw (
"Invalid ID in " +
context +
": an id can only contain [a-zA-Z0-0_-] as characters. The offending id is: " +
this.id
)
}
this.group = json.group ?? "";
this.group = json.group ?? ""
this.labels = json.labels ?? []
this.render = Translations.T(json.render, translationKey + ".render");
this.question = Translations.T(json.question, translationKey + ".question");
this.description = Translations.T(json.description, translationKey + ".description");
this.condition = TagUtils.Tag(json.condition ?? {"and": []}, `${context}.condition`);
this.render = Translations.T(json.render, translationKey + ".render")
this.question = Translations.T(json.question, translationKey + ".question")
this.description = Translations.T(json.description, translationKey + ".description")
this.condition = TagUtils.Tag(json.condition ?? { and: [] }, `${context}.condition`)
if (json.freeform) {
if (json.freeform.addExtraTags !== undefined && json.freeform.addExtraTags.map === undefined) {
if (
json.freeform.addExtraTags !== undefined &&
json.freeform.addExtraTags.map === undefined
) {
throw `Freeform.addExtraTags should be a list of strings - not a single string (at ${context})`
}
const type = json.freeform.type ?? "string"
if (ValidatedTextField.AvailableTypes().indexOf(type) < 0) {
throw "At " + context + ".freeform.type is an unknown type: " + type + "; try one of " + ValidatedTextField.AvailableTypes().join(", ")
throw (
"At " +
context +
".freeform.type is an unknown type: " +
type +
"; try one of " +
ValidatedTextField.AvailableTypes().join(", ")
)
}
let placeholder: Translation = Translations.T(json.freeform.placeholder)
if (placeholder === undefined) {
const typeDescription = <Translation>Translations.t.validation[type]?.description
const key = json.freeform.key;
const key = json.freeform.key
if (typeDescription !== undefined) {
placeholder = typeDescription.OnEveryLanguage(l => key + " (" + l + ")")
placeholder = typeDescription.OnEveryLanguage((l) => key + " (" + l + ")")
} else {
placeholder = Translations.T(key + " (" + type + ")")
}
@ -137,12 +155,13 @@ export default class TagRenderingConfig {
key: json.freeform.key,
type,
placeholder,
addExtraTags: json.freeform.addExtraTags?.map((tg, i) =>
TagUtils.ParseUploadableTag(tg, `${context}.extratag[${i}]`)) ?? [],
addExtraTags:
json.freeform.addExtraTags?.map((tg, i) =>
TagUtils.ParseUploadableTag(tg, `${context}.extratag[${i}]`)
) ?? [],
inline: json.freeform.inline ?? false,
default: json.freeform.default,
helperArgs: json.freeform.helperArgs
helperArgs: json.freeform.helperArgs,
}
if (json.freeform["extraTags"] !== undefined) {
throw `Freeform.extraTags is defined. This should probably be 'freeform.addExtraTag' (at ${context})`
@ -152,7 +171,6 @@ export default class TagRenderingConfig {
}
if (json.freeform["args"] !== undefined) {
throw `Freeform.args is defined. This should probably be 'freeform.helperArgs' (at ${context})`
}
if (json.freeform.key === "questions") {
@ -161,28 +179,42 @@ export default class TagRenderingConfig {
}
}
if (this.freeform.type !== undefined && ValidatedTextField.AvailableTypes().indexOf(this.freeform.type) < 0) {
const knownKeys = ValidatedTextField.AvailableTypes().join(", ");
if (
this.freeform.type !== undefined &&
ValidatedTextField.AvailableTypes().indexOf(this.freeform.type) < 0
) {
const knownKeys = ValidatedTextField.AvailableTypes().join(", ")
throw `Freeform.key ${this.freeform.key} is an invalid type. Known keys are ${knownKeys}`
}
if (this.freeform.addExtraTags) {
const usedKeys = new And(this.freeform.addExtraTags).usedKeys();
const usedKeys = new And(this.freeform.addExtraTags).usedKeys()
if (usedKeys.indexOf(this.freeform.key) >= 0) {
throw `The freeform key ${this.freeform.key} will be overwritten by one of the extra tags, as they use the same key too. This is in ${context}`;
throw `The freeform key ${this.freeform.key} will be overwritten by one of the extra tags, as they use the same key too. This is in ${context}`
}
}
}
this.multiAnswer = json.multiAnswer ?? false
if (json.mappings) {
if (!Array.isArray(json.mappings)) {
throw "Tagrendering has a 'mappings'-object, but expected a list (" + context + ")"
}
const commonIconSize = Utils.NoNull(json.mappings.map(m => m.icon !== undefined ? m.icon["class"] : undefined))[0] ?? "small"
this.mappings = json.mappings.map((m, i) => TagRenderingConfig.ExtractMapping(m, i, translationKey, context, this.multiAnswer, this.question !== undefined, commonIconSize));
const commonIconSize =
Utils.NoNull(
json.mappings.map((m) => (m.icon !== undefined ? m.icon["class"] : undefined))
)[0] ?? "small"
this.mappings = json.mappings.map((m, i) =>
TagRenderingConfig.ExtractMapping(
m,
i,
translationKey,
context,
this.multiAnswer,
this.question !== undefined,
commonIconSize
)
)
}
if (this.question && this.freeform?.key === undefined && this.mappings === undefined) {
@ -196,14 +228,12 @@ export default class TagRenderingConfig {
continue
}
throw `${context}: The rendering for language ${ln} does not contain {questions}. This is a bug, as this rendering should include exactly this to trigger those questions to be shown!`
}
if (this.freeform?.key !== undefined && this.freeform?.key !== "questions") {
throw `${context}: If the ID is questions to trigger a question box, the only valid freeform value is 'questions' as well. Set freeform to questions or remove the freeform all together`
}
}
if (this.freeform) {
if (this.render === undefined) {
throw `${context}: Detected a freeform key without rendering... Key: ${this.freeform.key} in ${context}`
@ -222,21 +252,25 @@ export default class TagRenderingConfig {
if (txt.indexOf("{canonical(" + this.freeform.key + ")") >= 0) {
continue
}
if (this.freeform.type === "opening_hours" && txt.indexOf("{opening_hours_table(") >= 0) {
if (
this.freeform.type === "opening_hours" &&
txt.indexOf("{opening_hours_table(") >= 0
) {
continue
}
if (this.freeform.type === "wikidata" && txt.indexOf("{wikipedia(" + this.freeform.key) >= 0) {
if (
this.freeform.type === "wikidata" &&
txt.indexOf("{wikipedia(" + this.freeform.key) >= 0
) {
continue
}
if (this.freeform.key === "wikidata" && txt.indexOf("{wikipedia()") >= 0) {
continue
}
throw `${context}: The rendering for language ${ln} does not contain the freeform key {${this.freeform.key}}. This is a bug, as this rendering should show exactly this freeform key!\nThe rendering is ${txt} `
}
}
if (this.render && this.question && this.freeform === undefined) {
throw `${context}: Detected a tagrendering which takes input without freeform key in ${context}; the question is ${this.question.txt}`
}
@ -244,7 +278,7 @@ export default class TagRenderingConfig {
if (!json.multiAnswer && this.mappings !== undefined && this.question !== undefined) {
let keys = []
for (let i = 0; i < this.mappings.length; i++) {
const mapping = this.mappings[i];
const mapping = this.mappings[i]
if (mapping.if === undefined) {
throw `${context}.mappings[${i}].if is undefined`
}
@ -252,15 +286,17 @@ export default class TagRenderingConfig {
}
keys = Utils.Dedup(keys)
for (let i = 0; i < this.mappings.length; i++) {
const mapping = this.mappings[i];
const mapping = this.mappings[i]
if (mapping.hideInAnswer) {
continue
}
const usedKeys = mapping.if.usedKeys();
const usedKeys = mapping.if.usedKeys()
for (const expectedKey of keys) {
if (usedKeys.indexOf(expectedKey) < 0) {
const msg = `${context}.mappings[${i}]: This mapping only defines values for ${usedKeys.join(', ')}, but it should also give a value for ${expectedKey}`
const msg = `${context}.mappings[${i}]: This mapping only defines values for ${usedKeys.join(
", "
)}, but it should also give a value for ${expectedKey}`
this.configuration_warnings.push(msg)
}
}
@ -272,22 +308,21 @@ export default class TagRenderingConfig {
throw `${context} MultiAnswer is set, but no mappings are defined`
}
let allKeys = [];
let allHaveIfNot = true;
let allKeys = []
let allHaveIfNot = true
for (const mapping of this.mappings) {
if (mapping.hideInAnswer) {
continue;
continue
}
if (mapping.ifnot === undefined) {
allHaveIfNot = false;
allHaveIfNot = false
}
allKeys = allKeys.concat(mapping.if.usedKeys());
allKeys = allKeys.concat(mapping.if.usedKeys())
}
allKeys = Utils.Dedup(allKeys);
allKeys = Utils.Dedup(allKeys)
if (allKeys.length > 1 && !allHaveIfNot) {
throw `${context}: A multi-answer is defined, which generates values over multiple keys. Please define ifnot-tags too on every mapping`
}
}
}
@ -296,17 +331,24 @@ export default class TagRenderingConfig {
* tr.if // => new Tag("a","b")
* tr.priorityIf // => new Tag("_country","be")
*/
public static ExtractMapping(mapping: MappingConfigJson, i: number, translationKey: string,
context: string,
multiAnswer?: boolean, isQuestionable?: boolean, commonSize: string = "small") {
public static ExtractMapping(
mapping: MappingConfigJson,
i: number,
translationKey: string,
context: string,
multiAnswer?: boolean,
isQuestionable?: boolean,
commonSize: string = "small"
) {
const ctx = `${translationKey}.mappings.${i}`
if (mapping.if === undefined) {
throw `${ctx}: Invalid mapping: "if" is not defined in ${JSON.stringify(mapping)}`
}
if (mapping.then === undefined) {
if (mapping["render"] !== undefined) {
throw `${ctx}: Invalid mapping: no 'then'-clause found. You might have typed 'render' instead of 'then', change it in ${JSON.stringify(mapping)}`
throw `${ctx}: Invalid mapping: no 'then'-clause found. You might have typed 'render' instead of 'then', change it in ${JSON.stringify(
mapping
)}`
}
throw `${ctx}: Invalid mapping: no 'then'-clause found in ${JSON.stringify(mapping)}`
}
@ -315,7 +357,9 @@ export default class TagRenderingConfig {
}
if (mapping["render"] !== undefined) {
throw `${ctx}: Invalid mapping: a 'render'-key is present, this is probably a bug: ${JSON.stringify(mapping)}`
throw `${ctx}: Invalid mapping: a 'render'-key is present, this is probably a bug: ${JSON.stringify(
mapping
)}`
}
if (typeof mapping.if !== "string" && mapping.if["length"] !== undefined) {
throw `${ctx}: Invalid mapping: "if" is defined as an array. Use {"and": <your conditions>} or {"or": <your conditions>} instead`
@ -325,18 +369,23 @@ export default class TagRenderingConfig {
throw `${ctx}: Invalid mapping: got a multi-Answer with addExtraTags; this is not allowed`
}
let hideInAnswer: boolean | TagsFilter = false;
let hideInAnswer: boolean | TagsFilter = false
if (typeof mapping.hideInAnswer === "boolean") {
hideInAnswer = mapping.hideInAnswer;
hideInAnswer = mapping.hideInAnswer
} else if (mapping.hideInAnswer !== undefined) {
hideInAnswer = TagUtils.Tag(mapping.hideInAnswer, `${context}.mapping[${i}].hideInAnswer`);
hideInAnswer = TagUtils.Tag(
mapping.hideInAnswer,
`${context}.mapping[${i}].hideInAnswer`
)
}
const addExtraTags = (mapping.addExtraTags ?? []).map((str, j) => TagUtils.SimpleTag(str, `${ctx}.addExtraTags[${j}]`));
const addExtraTags = (mapping.addExtraTags ?? []).map((str, j) =>
TagUtils.SimpleTag(str, `${ctx}.addExtraTags[${j}]`)
)
if (hideInAnswer === true && addExtraTags.length > 0) {
throw `${ctx}: Invalid mapping: 'hideInAnswer' is set to 'true', but 'addExtraTags' is enabled as well. This means that extra tags will be applied if this mapping is chosen as answer, but it cannot be chosen as answer. This either indicates a thought error or obsolete code that must be removed.`
}
let icon = undefined;
let icon = undefined
let iconClass = commonSize
if (mapping.icon !== undefined) {
if (typeof mapping.icon === "string" && mapping.icon !== "") {
@ -346,18 +395,22 @@ export default class TagRenderingConfig {
iconClass = mapping.icon["class"] ?? iconClass
}
}
const prioritySearch = mapping.priorityIf !== undefined ? TagUtils.Tag(mapping.priorityIf) : undefined;
const prioritySearch =
mapping.priorityIf !== undefined ? TagUtils.Tag(mapping.priorityIf) : undefined
const mp = <Mapping>{
if: TagUtils.Tag(mapping.if, `${ctx}.if`),
ifnot: (mapping.ifnot !== undefined ? TagUtils.Tag(mapping.ifnot, `${ctx}.ifnot`) : undefined),
ifnot:
mapping.ifnot !== undefined
? TagUtils.Tag(mapping.ifnot, `${ctx}.ifnot`)
: undefined,
then: Translations.T(mapping.then, `${ctx}.then`),
hideInAnswer,
icon,
iconClass,
addExtraTags,
searchTerms: mapping.searchTerms,
priorityIf: prioritySearch
};
priorityIf: prioritySearch,
}
if (isQuestionable) {
if (hideInAnswer !== true && mp.if !== undefined && !mp.if.isUsableAsAnswer()) {
throw `${context}.mapping[${i}].if: This value cannot be used to answer a question, probably because it contains a regex or an OR. Either change it or set 'hideInAnswer'`
@ -368,7 +421,7 @@ export default class TagRenderingConfig {
}
}
return mp;
return mp
}
/**
@ -376,15 +429,14 @@ export default class TagRenderingConfig {
* @constructor
*/
public IsKnown(tags: Record<string, string>): boolean {
if (this.condition &&
!this.condition.matchesProperties(tags)) {
if (this.condition && !this.condition.matchesProperties(tags)) {
// Filtered away by the condition, so it is kindof known
return true;
return true
}
if (this.multiAnswer) {
for (const m of this.mappings ?? []) {
if (TagUtils.MatchesMultiAnswer(m.if, tags)) {
return true;
return true
}
}
@ -394,15 +446,14 @@ export default class TagRenderingConfig {
return value !== undefined && value !== ""
}
return false
}
if (this.GetRenderValue(tags) !== undefined) {
// This value is known and can be rendered
return true;
return true
}
return false;
return false
}
/**
@ -411,39 +462,49 @@ export default class TagRenderingConfig {
* @param tags
* @constructor
*/
public GetRenderValues(tags: Record<string, string>): { then: Translation, icon?: string, iconClass?: string }[] {
public GetRenderValues(
tags: Record<string, string>
): { then: Translation; icon?: string; iconClass?: string }[] {
if (!this.multiAnswer) {
return [this.GetRenderValueWithImage(tags)]
}
// A flag to check that the freeform key isn't matched multiple times
// A flag to check that the freeform key isn't matched multiple times
// If it is undefined, it is "used" already, or at least we don't have to check for it anymore
let freeformKeyDefined = this.freeform?.key !== undefined;
let freeformKeyDefined = this.freeform?.key !== undefined
let usedFreeformValues = new Set<string>()
// We run over all the mappings first, to check if the mapping matches
const applicableMappings: { then: TypedTranslation<Record<string, string>>, img?: string }[] = Utils.NoNull((this.mappings ?? [])?.map(mapping => {
if (mapping.if === undefined) {
return mapping;
}
if (TagUtils.MatchesMultiAnswer(mapping.if, tags)) {
if (freeformKeyDefined && mapping.if.isUsableAsAnswer()) {
// THe freeform key is defined: what value does it use though?
// We mark the value to see if we have any leftovers
const value = mapping.if.asChange({}).find(kv => kv.k === this.freeform.key).v
usedFreeformValues.add(value)
const applicableMappings: {
then: TypedTranslation<Record<string, string>>
img?: string
}[] = Utils.NoNull(
(this.mappings ?? [])?.map((mapping) => {
if (mapping.if === undefined) {
return mapping
}
return mapping;
}
return undefined;
}))
if (TagUtils.MatchesMultiAnswer(mapping.if, tags)) {
if (freeformKeyDefined && mapping.if.isUsableAsAnswer()) {
// THe freeform key is defined: what value does it use though?
// We mark the value to see if we have any leftovers
const value = mapping.if
.asChange({})
.find((kv) => kv.k === this.freeform.key).v
usedFreeformValues.add(value)
}
return mapping
}
return undefined
})
)
if (freeformKeyDefined && tags[this.freeform.key] !== undefined) {
const freeformValues = tags[this.freeform.key].split(";")
const leftovers = freeformValues.filter(v => !usedFreeformValues.has(v))
const leftovers = freeformValues.filter((v) => !usedFreeformValues.has(v))
for (const leftover of leftovers) {
applicableMappings.push({
then:
new TypedTranslation<object>(this.render.replace("{" + this.freeform.key + "}", leftover).translations)
then: new TypedTranslation<object>(
this.render.replace("{" + this.freeform.key + "}", leftover).translations
),
})
}
}
@ -451,7 +512,10 @@ export default class TagRenderingConfig {
return applicableMappings
}
public GetRenderValue(tags: any, defltValue: any = undefined): TypedTranslation<any> | undefined {
public GetRenderValue(
tags: any,
defltValue: any = undefined
): TypedTranslation<any> | undefined {
return this.GetRenderValueWithImage(tags, defltValue)?.then
}
@ -460,7 +524,10 @@ export default class TagRenderingConfig {
* Not compatible with multiAnswer - use GetRenderValueS instead in that case
* @constructor
*/
public GetRenderValueWithImage(tags: any, defltValue: any = undefined): { then: TypedTranslation<any>, icon?: string } | undefined {
public GetRenderValueWithImage(
tags: any,
defltValue: any = undefined
): { then: TypedTranslation<any>; icon?: string } | undefined {
if (this.condition !== undefined) {
if (!this.condition.matchesProperties(tags)) {
return undefined
@ -470,22 +537,23 @@ export default class TagRenderingConfig {
if (this.mappings !== undefined && !this.multiAnswer) {
for (const mapping of this.mappings) {
if (mapping.if === undefined) {
return mapping;
return mapping
}
if (mapping.if.matchesProperties(tags)) {
return mapping;
return mapping
}
}
}
if (this.id === "questions" ||
if (
this.id === "questions" ||
this.freeform?.key === undefined ||
tags[this.freeform.key] !== undefined
) {
return {then: this.render}
return { then: this.render }
}
return {then: defltValue};
return { then: defltValue }
}
/**
@ -498,52 +566,57 @@ export default class TagRenderingConfig {
const translations: Translation[] = []
for (const key in this) {
if (!this.hasOwnProperty(key)) {
continue;
continue
}
const o = this[key]
if (o instanceof Translation) {
translations.push(o)
}
}
return translations;
return translations
}
FreeformValues(): { key: string, type?: string, values?: string [] } {
FreeformValues(): { key: string; type?: string; values?: string[] } {
try {
const key = this.freeform?.key
const answerMappings = this.mappings?.filter(m => m.hideInAnswer !== true)
const answerMappings = this.mappings?.filter((m) => m.hideInAnswer !== true)
if (key === undefined) {
let values: { k: string, v: string }[][] = Utils.NoNull(answerMappings?.map(m => m.if.asChange({})) ?? [])
let values: { k: string; v: string }[][] = Utils.NoNull(
answerMappings?.map((m) => m.if.asChange({})) ?? []
)
if (values.length === 0) {
return;
return
}
const allKeys = values.map(arr => arr.map(o => o.k))
let common = allKeys[0];
const allKeys = values.map((arr) => arr.map((o) => o.k))
let common = allKeys[0]
for (const keyset of allKeys) {
common = common.filter(item => keyset.indexOf(item) >= 0)
common = common.filter((item) => keyset.indexOf(item) >= 0)
}
const commonKey = common[0]
if (commonKey === undefined) {
return undefined;
return undefined
}
return {
key: commonKey,
values: Utils.NoNull(values.map(arr => arr.filter(item => item.k === commonKey)[0]?.v))
values: Utils.NoNull(
values.map((arr) => arr.filter((item) => item.k === commonKey)[0]?.v)
),
}
}
let values = Utils.NoNull(answerMappings?.map(m => m.if.asChange({}).filter(item => item.k === key)[0]?.v) ?? [])
let values = Utils.NoNull(
answerMappings?.map(
(m) => m.if.asChange({}).filter((item) => item.k === key)[0]?.v
) ?? []
)
if (values.length === undefined) {
values = undefined
}
return {
key,
type: this.freeform.type,
values
values,
}
} catch (e) {
console.error("Could not create FreeformValues for tagrendering", this.id)
@ -552,80 +625,93 @@ export default class TagRenderingConfig {
}
GenerateDocumentation(): BaseUIElement {
let withRender: (BaseUIElement | string)[] = [];
let withRender: (BaseUIElement | string)[] = []
if (this.freeform?.key !== undefined) {
withRender = [
`This rendering asks information about the property `,
Link.OsmWiki(this.freeform.key),
new Paragraph(new Combine([
"This is rendered with ",
new FixedUiElement(this.render.txt).SetClass("literalcode bold")
]))
new Paragraph(
new Combine([
"This is rendered with ",
new FixedUiElement(this.render.txt).SetClass("literalcode bold"),
])
),
]
}
let mappings: BaseUIElement = undefined;
let mappings: BaseUIElement = undefined
if (this.mappings !== undefined) {
mappings = new List(
[].concat(...this.mappings.map(m => {
[].concat(
...this.mappings.map((m) => {
const msgs: (string | BaseUIElement)[] = [
new Combine(
[
new FixedUiElement(m.then.txt).SetClass("bold"),
" corresponds with ",
new FixedUiElement( m.if.asHumanString(true, false, {})).SetClass("code")
]
)
new Combine([
new FixedUiElement(m.then.txt).SetClass("bold"),
" corresponds with ",
new FixedUiElement(m.if.asHumanString(true, false, {})).SetClass(
"code"
),
]),
]
if (m.hideInAnswer === true) {
msgs.push(new FixedUiElement("This option cannot be chosen as answer").SetClass("italic"))
msgs.push(
new FixedUiElement(
"This option cannot be chosen as answer"
).SetClass("italic")
)
}
if (m.ifnot !== undefined) {
msgs.push("Unselecting this answer will add " + m.ifnot.asHumanString(true, false, {}))
msgs.push(
"Unselecting this answer will add " +
m.ifnot.asHumanString(true, false, {})
)
}
return msgs;
}
))
return msgs
})
)
)
}
let condition: BaseUIElement = undefined
if (this.condition !== undefined && !this.condition?.matchesProperties({})) {
condition = new Combine(["Only visible if ",
new FixedUiElement(this.condition.asHumanString(false, false, {})
).SetClass("code")
, " is shown"])
condition = new Combine([
"Only visible if ",
new FixedUiElement(this.condition.asHumanString(false, false, {})).SetClass("code"),
" is shown",
])
}
let group: BaseUIElement = undefined
if (this.group !== undefined && this.group !== "") {
group = new Combine([
"This tagrendering is part of group ", new FixedUiElement(this.group).SetClass("code")
"This tagrendering is part of group ",
new FixedUiElement(this.group).SetClass("code"),
])
}
let labels: BaseUIElement = undefined
if (this.labels?.length > 0) {
labels = new Combine([
"This tagrendering has labels ",
...this.labels.map(label => new FixedUiElement(label).SetClass("code"))
...this.labels.map((label) => new FixedUiElement(label).SetClass("code")),
]).SetClass("flex")
}
return new Combine([
new Title(this.id, 3),
this.description,
this.question !== undefined ?
new Combine(["The question is ", new FixedUiElement(this.question.txt).SetClass("font-bold bold")]) :
new FixedUiElement(
"This tagrendering has no question and is thus read-only"
).SetClass("italic"),
this.question !== undefined
? new Combine([
"The question is ",
new FixedUiElement(this.question.txt).SetClass("font-bold bold"),
])
: new FixedUiElement(
"This tagrendering has no question and is thus read-only"
).SetClass("italic"),
new Combine(withRender),
mappings,
condition,
group,
labels
]).SetClass("flex flex-col");
labels,
]).SetClass("flex flex-col")
}
}
}