forked from MapComplete/MapComplete
Test with name suggestion index
This commit is contained in:
parent
00ab3a1b77
commit
6786c8f321
7 changed files with 371 additions and 5 deletions
103
src/UI/InputElement/Helpers/NameSuggestionIndexInput.svelte
Normal file
103
src/UI/InputElement/Helpers/NameSuggestionIndexInput.svelte
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<script lang="ts">
|
||||
import type { Feature, MultiPolygon } from "geojson"
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||
import * as nsi from "../../../../node_modules/name-suggestion-index/dist/nsi.json"
|
||||
import * as nsiFeatures from "../../../../node_modules/name-suggestion-index/dist/featureCollection.json"
|
||||
import { LocationConflation } from "@rapideditor/location-conflation"
|
||||
import * as turf from "@turf/turf"
|
||||
|
||||
const nsiFile: NSIFile = nsi
|
||||
const loco = new LocationConflation(nsiFeatures)
|
||||
|
||||
/**
|
||||
* All props for this input helper
|
||||
*/
|
||||
export let value: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
export let feature: Feature
|
||||
|
||||
// Currently hardcoded, should be dynamic
|
||||
let maintag = "amenity=atm"
|
||||
let tag = "brand"
|
||||
|
||||
const path = `${tag}s/${maintag.split("=")[0]}/${maintag.split("=")[1]}`
|
||||
let items = nsiFile.nsi[path].items
|
||||
|
||||
// Get the coordinates if the feature is a point, otherwise use the center
|
||||
let lon: number
|
||||
let lat: number
|
||||
if (feature.geometry.type === "Point") {
|
||||
const coordinates = feature.geometry.coordinates
|
||||
lon = coordinates[0]
|
||||
lat = coordinates[1]
|
||||
} else {
|
||||
lon = feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2
|
||||
lat = feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2
|
||||
}
|
||||
|
||||
// Filter the items
|
||||
let filter = ""
|
||||
$: filteredItems = items
|
||||
.filter((item) => item.displayName.toLowerCase().includes(filter.toLowerCase()))
|
||||
.filter((item) => {
|
||||
// Check if the feature is in the location set using the location-conflation library
|
||||
const resolvedSet = loco.resolveLocationSet(item.locationSet)
|
||||
if (resolvedSet) {
|
||||
const setFeature: Feature<MultiPolygon> = resolvedSet.feature
|
||||
// We actually have a location set, so we can check if the feature is in it, by determining if our point is inside of the MultiPolygon using @turf/boolean-point-in-polygon
|
||||
return turf.booleanPointInPolygon([lon, lat], setFeature.geometry)
|
||||
}
|
||||
return true
|
||||
})
|
||||
.slice(0, 25)
|
||||
|
||||
/**
|
||||
* Some interfaces for the NSI files
|
||||
*/
|
||||
interface NSIFile {
|
||||
_meta: {
|
||||
version: string
|
||||
generated: string
|
||||
url: string
|
||||
hash: string
|
||||
}
|
||||
nsi: {
|
||||
[path: string]: NSIEntry
|
||||
}
|
||||
}
|
||||
|
||||
interface NSIEntry {
|
||||
properties: {
|
||||
path: string
|
||||
skipCollection?: boolean
|
||||
preserveTags?: string[]
|
||||
exclude: unknown
|
||||
}
|
||||
items: NSIItem[]
|
||||
}
|
||||
|
||||
interface NSIItem {
|
||||
displayName: string
|
||||
id: string
|
||||
locationSet: unknown
|
||||
tags: {
|
||||
[key: string]: string
|
||||
}
|
||||
fromTemplate?: boolean
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<input type="text" placeholder="Filter entries" bind:value={filter} />
|
||||
<div class="flex h-32 w-full flex-wrap overflow-hidden">
|
||||
{#each filteredItems as item}
|
||||
<div
|
||||
class="m-1 h-fit rounded-full border border-black p-4 text-center"
|
||||
on:click={() => {
|
||||
value.setData(item.tags[tag])
|
||||
}}
|
||||
>
|
||||
{item.displayName}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte"
|
||||
import SlopeInput from "./Helpers/SlopeInput.svelte"
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import NameSuggestionIndexInput from "./Helpers/NameSuggestionIndexInput.svelte"
|
||||
|
||||
export let type: ValidatorType
|
||||
export let value: UIEventSource<string | object>
|
||||
|
|
@ -50,4 +51,6 @@
|
|||
<SlopeInput {value} {feature} {state} />
|
||||
{:else if type === "wikidata"}
|
||||
<ToSvelte construct={() => InputHelpers.constructWikidataHelper(value, properties)} />
|
||||
{:else if type === "nsi"}
|
||||
<NameSuggestionIndexInput {value} {feature} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import TagValidator from "./Validators/TagValidator"
|
|||
import IdValidator from "./Validators/IdValidator"
|
||||
import SlopeValidator from "./Validators/SlopeValidator"
|
||||
import VeloparkValidator from "./Validators/VeloparkValidator"
|
||||
import NameSuggestionIndexValidator from "./Validators/NameSuggestionIndexValidator"
|
||||
|
||||
export type ValidatorType = (typeof Validators.availableTypes)[number]
|
||||
|
||||
|
|
@ -60,6 +61,7 @@ export default class Validators {
|
|||
"id",
|
||||
"slope",
|
||||
"velopark",
|
||||
"nsi",
|
||||
] as const
|
||||
|
||||
public static readonly AllValidators: ReadonlyArray<Validator> = [
|
||||
|
|
@ -89,6 +91,7 @@ export default class Validators {
|
|||
new IdValidator(),
|
||||
new SlopeValidator(),
|
||||
new VeloparkValidator(),
|
||||
new NameSuggestionIndexValidator(),
|
||||
]
|
||||
|
||||
private static _byType = Validators._byTypeConstructor()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
import Title from "../../Base/Title"
|
||||
import Combine from "../../Base/Combine"
|
||||
import { Validator } from "../Validator"
|
||||
import Table from "../../Base/Table"
|
||||
|
||||
export default class NameSuggestionIndexValidator extends Validator {
|
||||
constructor() {
|
||||
super(
|
||||
"nsi",
|
||||
new Combine([
|
||||
"Gives a list of possible suggestions for a brand or operator tag.",
|
||||
new Title("Helper arguments"),
|
||||
new Table(
|
||||
["name", "doc"],
|
||||
[
|
||||
[
|
||||
"options",
|
||||
new Combine([
|
||||
"A JSON-object of type `{ main: string, key: string }`. ",
|
||||
new Table(
|
||||
["subarg", "doc"],
|
||||
[
|
||||
[
|
||||
"main",
|
||||
"The main tag to give suggestions for, e.g. `amenity=restaurant`.",
|
||||
],
|
||||
["key", "The key to give suggestions for, e.g. `brand`."],
|
||||
]
|
||||
),
|
||||
]),
|
||||
],
|
||||
]
|
||||
),
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue