Automatically load appropriate suggestions for brands and operators

This commit is contained in:
Pieter Vander Vennet 2024-05-23 11:28:51 +02:00
parent 3146fa0d26
commit 67f23eea14
11 changed files with 70 additions and 47 deletions

View file

@ -4,22 +4,12 @@ import * as nsiWD from "../node_modules/name-suggestion-index/dist/wikidata.min.
import { existsSync, writeFileSync } from "fs"
import ScriptUtils from "./ScriptUtils"
import { Utils } from "../src/Utils"
import { WikimediaImageProvider } from "../src/Logic/ImageProviders/WikimediaImageProvider"
import { renameSync } from "node:fs"
export default class DownloadNsiLogos extends Script {
class DownloadNsiLogos extends Script {
constructor() {
super("Downloads all images of the NSI")
}
private async getWikimediaUrl(startUrl: string) {
if (!startUrl) {
return startUrl
}
}
private async downloadLogo(nsiItem: NSIItem, type: string, basePath: string) {
try {
return await this.downloadLogoUnsafe(nsiItem, type, basePath)
@ -71,8 +61,8 @@ export default class DownloadNsiLogos extends Script {
}
if ((<string>logos.wikidata).toLowerCase().endsWith(".svg")) {
console.log("Written SVG", path)
if(!path.endsWith(".svg")){
throw "Undetected svg path:"+logos.wikidata
if (!path.endsWith(".svg")) {
throw "Undetected svg path:" + logos.wikidata
}
writeFileSync(path, dloaded["content"], "utf8")
return true
@ -90,8 +80,12 @@ export default class DownloadNsiLogos extends Script {
}
async main(args: string[]): Promise<void> {
const type = "brand"
async main(): Promise<void> {
await this.downloadFor("operator")
await this.downloadFor("brand")
}
async downloadFor(type: "brand" | "operator"): Promise<void> {
const items = NameSuggestionIndex.allPossible(type)
const basePath = "./public/assets/data/nsi/logos/"
let downloadCount = 0

View file

@ -883,7 +883,8 @@ export class TagRenderingConfigUtils {
return config
}
const clone: TagRenderingConfig = Object.create(config)
clone.mappings = [...clone.mappings ?? [], ...extraMappings]
const oldMappingsCloned = clone.mappings?.map(m => ({ ...m, priorityIf: m.priorityIf ?? TagUtils.Tag("id~*") })) ?? []
clone.mappings = [...oldMappingsCloned, ...extraMappings]
return clone
})
}

View file

@ -11,6 +11,7 @@
import UserRelatedState from "../../Logic/State/UserRelatedState"
import Delete_icon from "../../assets/svg/Delete_icon.svelte"
import BackButton from "../Base/BackButton.svelte"
import TagRenderingEditableDynamic from "../Popup/TagRendering/TagRenderingEditableDynamic.svelte"
export let state: SpecialVisualizationState
export let selectedElement: Feature
@ -68,7 +69,7 @@
tabindex="-1"
>
{#each $knownTagRenderings as config (config.id)}
<TagRenderingEditable
<TagRenderingEditableDynamic
{tags}
{config}
{state}

View file

@ -550,14 +550,13 @@ export default class ShowDataLayer {
return
}
const bbox = BBox.bboxAroundAll(features.map(BBox.get))
console.log("Zooming to features", bbox.asGeoJson())
console.debug("Zooming to features", bbox.asGeoJson())
window.requestAnimationFrame(() => {
map.resize()
map.fitBounds(bbox.toLngLat(), {
padding: { top: 10, bottom: 10, left: 10, right: 10 },
animate: false
})
map.resize()
map.fitBounds(bbox.toLngLat(), {
padding: { top: 10, bottom: 10, left: 10, right: 10 },
animate: false
})
})
}

View file

@ -55,7 +55,7 @@ export default class OpeningHoursVisualization extends Toggle {
applicableWeek.startingMonday
)
Locale.language.mapD((lng) => {
console.log("Setting OH description to", lng, textual)
console.debug("Setting OH description to", lng, textual)
vis.ConstructElement().ariaLabel = textual.textFor(lng)
})
return vis

View file

@ -3,16 +3,16 @@
* Shows all questions for which the answers are unknown.
* The questions can either be shown all at once or one at a time (in which case they can be skipped)
*/
import TagRenderingConfig, { TagRenderingConfigUtils } from "../../../Models/ThemeConfig/TagRenderingConfig"
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
import { UIEventSource } from "../../../Logic/UIEventSource"
import type { Feature } from "geojson"
import type { SpecialVisualizationState } from "../../SpecialVisualization"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import TagRenderingQuestion from "./TagRenderingQuestion.svelte"
import Tr from "../../Base/Tr.svelte"
import Translations from "../../i18n/Translations.js"
import { Utils } from "../../../Utils"
import { onDestroy } from "svelte"
import TagRenderingQuestion from "./TagRenderingQuestion.svelte"
import TagRenderingQuestionDynamic from "./TagRenderingQuestionDynamic.svelte"
export let layer: LayerConfig
@ -26,7 +26,8 @@
export let onlyForLabels: string[] | undefined = undefined
const _onlyForLabels = new Set(onlyForLabels)
/**
* If set, only questions _not_ having these labels will be shown
* If set, only questions _not_ having these labels will be shown.
* This is used for a partial questionbox
*/
export let notForLabels: string[] | undefined = undefined
const _notForLabels = new Set(notForLabels)
@ -41,14 +42,15 @@
}
return true
}
const baseQuestions = (layer.tagRenderings ?? [])?.filter(
(tr) => allowed(tr.labels) && tr.question !== undefined
)
let skippedQuestions = new UIEventSource<Set<string>>(new Set<string>())
let questionboxElem: HTMLDivElement
let questionsToAsk = tags.map(
(tags) => {
const baseQuestions = (layer.tagRenderings ?? [])?.filter(
(tr) => allowed(tr.labels) && tr.question !== undefined
)
const questionsToAsk: TagRenderingConfig[] = []
for (const baseQuestion of baseQuestions) {
if (skippedQuestions.data.has(baseQuestion.id)) {

View file

@ -11,7 +11,7 @@
import { Utils } from "../../../Utils"
import { twMerge } from "tailwind-merge"
import EditButton from "./EditButton.svelte"
import TagRenderingAnswerDynamic from "./TagRenderingAnswerDynamic.svelte"
import TagRenderingAnswer from "./TagRenderingAnswer.svelte"
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
@ -100,7 +100,7 @@
</TagRenderingQuestion>
{:else}
<div class="low-interaction flex items-center justify-between overflow-hidden rounded px-2">
<TagRenderingAnswerDynamic id={answerId} {config} {tags} {selectedElement} {state} {layer} />
<TagRenderingAnswer id={answerId} {config} {tags} {selectedElement} {state} {layer} />
<EditButton
arialabel={config.editButtonAriaLabel}
ariaLabelledBy={answerId}
@ -112,7 +112,7 @@
{/if}
{:else}
<div class="h-full w-full overflow-hidden">
<TagRenderingAnswerDynamic {config} {tags} {selectedElement} {state} {layer} />
<TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} />
</div>
{/if}
</div>

View file

@ -0,0 +1,26 @@
<script lang="ts">
import TagRenderingConfig, { TagRenderingConfigUtils } from "../../../Models/ThemeConfig/TagRenderingConfig"
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
import type { Feature } from "geojson"
import type { SpecialVisualizationState } from "../../SpecialVisualization"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import TagRenderingEditable from "./TagRenderingEditable.svelte"
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
export let selectedElement: Feature | undefined
export let state: SpecialVisualizationState
export let layer: LayerConfig = undefined
export let editingEnabled: Store<boolean> | undefined = state?.featureSwitchUserbadge
export let highlightedRendering: UIEventSource<string> = undefined
export let clss = undefined
export let editMode = !config.IsKnown(tags.data)
let dynamicConfig = TagRenderingConfigUtils.withNameSuggestionIndex(config, tags, selectedElement)
</script>
<TagRenderingEditable config={$dynamicConfig} {editMode} {clss} {highlightedRendering} {editingEnabled} {layer} {state}
{selectedElement} {tags} />

View file

@ -3,7 +3,6 @@
import type { SpecialVisualizationState } from "../../SpecialVisualization"
import Tr from "../../Base/Tr.svelte"
import type { Feature } from "geojson"
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig"
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
import FreeformInput from "./FreeformInput.svelte"
@ -59,7 +58,6 @@
*/
let checkedMappings: boolean[]
let mappings: Mapping[] = config?.mappings ?? []
let searchTerm: UIEventSource<string> = new UIEventSource("")
let dispatch = createEventDispatcher<{
@ -74,7 +72,7 @@
*/
function initialize(tgs: Record<string, string>, confg: TagRenderingConfig): void {
mappings = confg.mappings?.filter((m) => {
const mappings = confg.mappings?.filter((m) => {
if (typeof m.hideInAnswer === "boolean") {
return !m.hideInAnswer
}
@ -169,7 +167,7 @@
onDestroy(
freeformInput.subscribe((freeformValue) => {
if (!mappings || mappings?.length == 0 || config.freeform?.key === undefined) {
if (!config?.mappings || config?.mappings?.length == 0 || config.freeform?.key === undefined) {
return
}
// If a freeform value is given, mark the 'mapping' as marked
@ -178,11 +176,11 @@
// Initialization didn't yet run
return
}
checkedMappings[mappings.length] = freeformValue?.length > 0
checkedMappings[config?.mappings.length] = freeformValue?.length > 0
return
}
if (freeformValue?.length > 0) {
selectedMapping = mappings.length
selectedMapping = config.mappings.length
}
})
)
@ -192,7 +190,7 @@
allowDeleteOfFreeform &&
$freeformInput === undefined &&
$freeformInputUnvalidated === "" &&
(mappings?.length ?? 0) === 0
(config?.mappings?.length ?? 0) === 0
) {
selectedTags = new Tag(config.freeform.key, "")
} else {
@ -353,7 +351,7 @@
{#if config.freeform?.key && !(mappings?.length > 0)}
{#if config.freeform?.key && !(config?.mappings?.length > 0)}
<!-- There are no options to choose from, simply show the input element: fill out the text field -->
<FreeformInput
{config}
@ -367,7 +365,7 @@
unvalidatedText={freeformInputUnvalidated}
on:submit={() => onSave()}
/>
{:else if mappings !== undefined && !config.multiAnswer}
{:else if config.mappings !== undefined && !config.multiAnswer}
<!-- Simple radiobuttons as mapping -->
<div class="flex flex-col">
{#each config.mappings as mapping, i (mapping.then)}
@ -416,7 +414,7 @@
</label>
{/if}
</div>
{:else if mappings !== undefined && config.multiAnswer}
{:else if config.mappings !== undefined && config.multiAnswer}
<!-- Multiple answers can be chosen: checkboxes -->
<div class="flex flex-col">
{#each config.mappings as mapping, i (mapping.then)}
@ -480,7 +478,7 @@
<!-- TagRenderingQuestion-buttons -->
<slot name="cancel" />
<slot name="save-button" {selectedTags}>
{#if allowDeleteOfFreeform && (mappings?.length ?? 0) === 0 && $freeformInput === undefined && $freeformInputUnvalidated === ""}
{#if allowDeleteOfFreeform && (config?.mappings?.length ?? 0) === 0 && $freeformInput === undefined && $freeformInputUnvalidated === ""}
<button
class="primary flex"
on:click|stopPropagation|preventDefault={() => onSave()}

View file

@ -8,6 +8,7 @@ import type { SpecialVisualizationState } from "../../SpecialVisualization"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import TagRenderingQuestion from "./TagRenderingQuestion.svelte"
import type { UploadableTag } from "../../../Logic/Tags/TagUtils"
import { writable } from "svelte/store"
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
@ -22,6 +23,7 @@ export let allowDeleteOfFreeform: boolean = false
let dynamicConfig = TagRenderingConfigUtils.withNameSuggestionIndex(config, tags, selectedElement)
</script>
<TagRenderingQuestion

View file

@ -685,6 +685,6 @@
<CloseAnimation isOpened={state.guistate.themeIsOpened} moveTo={openMapButton} debug="theme"/>
<CloseAnimation isOpened={state.guistate.menuIsOpened} moveTo={openMenuButton} debug="menu"/>
<CloseAnimation isOpened={selectedLayer.map(sl => (sl !== undefined && sl === currentViewLayer))} moveTo={openCurrentViewLayerButton} debug="currentViewLayer"/>
<CloseAnimation isOpened={selectedElement.map(sl =>{ console.log("SE is", sl); return sl !== undefined && sl?.properties?.id === LastClickFeatureSource.newPointElementId })} moveTo={openNewElementButton} debug="newElement"/>
<CloseAnimation isOpened={selectedElement.map(sl => sl !== undefined && sl?.properties?.id === LastClickFeatureSource.newPointElementId)} moveTo={openNewElementButton} debug="newElement"/>
<CloseAnimation isOpened={state.guistate.filtersPanelIsOpened} moveTo={openFilterButton} debug="filter"/>
<CloseAnimation isOpened={state.guistate.backgroundLayerSelectionIsOpened} moveTo={openBackgroundButton} debug="bg"/>