forked from MapComplete/MapComplete
Chore: housekeeping
This commit is contained in:
parent
cd9e03dd6f
commit
b300fffdc5
156 changed files with 4436 additions and 1318 deletions
|
|
@ -19,273 +19,272 @@ import { Utils } from "../../Utils"
|
|||
|
||||
export class DataImportSpecialVisualisations {
|
||||
public static initList(): (SpecialVisualization & { group })[] {
|
||||
return [
|
||||
new TagApplyButton(),
|
||||
new PointImportButtonViz(),
|
||||
new WayImportButtonViz(),
|
||||
new ConflateImportButtonViz(),
|
||||
new PlantNetDetectionViz(),
|
||||
{
|
||||
funcName: "maproulette_set_status",
|
||||
group: "data_import",
|
||||
docs: "Change the status of the given MapRoulette task",
|
||||
needsUrls: [Maproulette.defaultEndpoint],
|
||||
example:
|
||||
" The following example sets the status to '2' (false positive)\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
" \"id\": \"mark_duplicate\",\n" +
|
||||
" \"render\": {\n" +
|
||||
" \"special\": {\n" +
|
||||
" \"type\": \"maproulette_set_status\",\n" +
|
||||
" \"message\": {\n" +
|
||||
" \"en\": \"Mark as not found or false positive\"\n" +
|
||||
" },\n" +
|
||||
" \"status\": \"2\",\n" +
|
||||
" \"image\": \"close\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"```",
|
||||
args: [
|
||||
{
|
||||
name: "message",
|
||||
doc: "A message to show to the user"
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
doc: "Image to show",
|
||||
defaultValue: "confirm"
|
||||
},
|
||||
{
|
||||
name: "message_confirm",
|
||||
doc: "What to show when the task is closed, either by the user or was already closed."
|
||||
},
|
||||
{
|
||||
name: "status",
|
||||
doc: "A statuscode to apply when the button is clicked. 1 = `close`, 2 = `false_positive`, 3 = `skip`, 4 = `deleted`, 5 = `already fixed` (on the map, e.g. for duplicates), 6 = `too hard`",
|
||||
defaultValue: "1"
|
||||
},
|
||||
{
|
||||
name: "maproulette_id",
|
||||
doc: "The property name containing the maproulette id",
|
||||
defaultValue: "mr_taskId"
|
||||
},
|
||||
{
|
||||
name: "ask_feedback",
|
||||
doc: "If not an empty string, this will be used as question to ask some additional feedback. A text field will be added",
|
||||
defaultValue: ""
|
||||
}
|
||||
],
|
||||
return [
|
||||
new TagApplyButton(),
|
||||
new PointImportButtonViz(),
|
||||
new WayImportButtonViz(),
|
||||
new ConflateImportButtonViz(),
|
||||
new PlantNetDetectionViz(),
|
||||
{
|
||||
funcName: "maproulette_set_status",
|
||||
group: "data_import",
|
||||
docs: "Change the status of the given MapRoulette task",
|
||||
needsUrls: [Maproulette.defaultEndpoint],
|
||||
example:
|
||||
" The following example sets the status to '2' (false positive)\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
' "id": "mark_duplicate",\n' +
|
||||
' "render": {\n' +
|
||||
' "special": {\n' +
|
||||
' "type": "maproulette_set_status",\n' +
|
||||
' "message": {\n' +
|
||||
' "en": "Mark as not found or false positive"\n' +
|
||||
" },\n" +
|
||||
' "status": "2",\n' +
|
||||
' "image": "close"\n' +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"```",
|
||||
args: [
|
||||
{
|
||||
name: "message",
|
||||
doc: "A message to show to the user",
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
doc: "Image to show",
|
||||
defaultValue: "confirm",
|
||||
},
|
||||
{
|
||||
name: "message_confirm",
|
||||
doc: "What to show when the task is closed, either by the user or was already closed.",
|
||||
},
|
||||
{
|
||||
name: "status",
|
||||
doc: "A statuscode to apply when the button is clicked. 1 = `close`, 2 = `false_positive`, 3 = `skip`, 4 = `deleted`, 5 = `already fixed` (on the map, e.g. for duplicates), 6 = `too hard`",
|
||||
defaultValue: "1",
|
||||
},
|
||||
{
|
||||
name: "maproulette_id",
|
||||
doc: "The property name containing the maproulette id",
|
||||
defaultValue: "mr_taskId",
|
||||
},
|
||||
{
|
||||
name: "ask_feedback",
|
||||
doc: "If not an empty string, this will be used as question to ask some additional feedback. A text field will be added",
|
||||
defaultValue: "",
|
||||
},
|
||||
],
|
||||
|
||||
constr: (state, tagsSource, args) => {
|
||||
let [
|
||||
message,
|
||||
image,
|
||||
message_closed,
|
||||
statusToSet,
|
||||
maproulette_id_key,
|
||||
askFeedback
|
||||
] = args
|
||||
if (image === "") {
|
||||
image = "confirm"
|
||||
}
|
||||
if (maproulette_id_key === "" || maproulette_id_key === undefined) {
|
||||
maproulette_id_key = "mr_taskId"
|
||||
}
|
||||
statusToSet = statusToSet ?? "1"
|
||||
return new SvelteUIElement(MaprouletteSetStatus, {
|
||||
state,
|
||||
tags: tagsSource,
|
||||
message,
|
||||
image,
|
||||
message_closed,
|
||||
statusToSet,
|
||||
maproulette_id_key,
|
||||
askFeedback
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
funcName: "linked_data_from_website",
|
||||
group: "data_import",
|
||||
docs: "Attempts to load (via a proxy) the specified website and parsed ld+json from there. Suitable data will be offered to import into OSM. Note: this element is added by default",
|
||||
args: [
|
||||
{
|
||||
name: "key",
|
||||
defaultValue: "website",
|
||||
doc: "Attempt to load ld+json from the specified URL. This can be in an embedded <script type='ld+json'>"
|
||||
},
|
||||
{
|
||||
name: "useProxy",
|
||||
defaultValue: "yes",
|
||||
doc: "If 'yes', uses the provided proxy server. This proxy server will scrape HTML and search for a script with `lang='ld+json'`. If `no`, the data will be downloaded and expects a linked-data-json directly"
|
||||
},
|
||||
{
|
||||
name: "host",
|
||||
doc: "If not using a proxy, define what host the website is allowed to connect to"
|
||||
},
|
||||
{
|
||||
name: "mode",
|
||||
doc: "If `display`, only show the data in tabular and readonly form, ignoring already existing tags. This is used to explicitly show all the tags. If unset or anything else, allow to apply/import on OSM"
|
||||
},
|
||||
{
|
||||
name: "collapsed",
|
||||
defaultValue: "yes",
|
||||
doc: "If the containing accordion should be closed"
|
||||
}
|
||||
],
|
||||
needsUrls: [Constants.linkedDataProxy, "http://www.schema.org"],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tags: UIEventSource<Record<string, string>>,
|
||||
argument: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): BaseUIElement {
|
||||
const key = argument[0] ?? "website"
|
||||
const useProxy = argument[1] !== "no"
|
||||
const readonly = argument[3] === "readonly"
|
||||
const isClosed = (argument[4] ?? "yes") === "yes"
|
||||
|
||||
const countryStore: Store<string | undefined> = tags.mapD(
|
||||
(tags) => tags._country
|
||||
)
|
||||
const sourceUrl: Store<string | undefined> = tags.mapD((tags) => {
|
||||
if (!tags[key] || tags[key] === "undefined") {
|
||||
return null
|
||||
constr: (state, tagsSource, args) => {
|
||||
let [
|
||||
message,
|
||||
image,
|
||||
message_closed,
|
||||
statusToSet,
|
||||
maproulette_id_key,
|
||||
askFeedback,
|
||||
] = args
|
||||
if (image === "") {
|
||||
image = "confirm"
|
||||
}
|
||||
return tags[key]
|
||||
})
|
||||
const externalData: Store<{ success: GeoJsonProperties } | { error }> =
|
||||
sourceUrl.bindD(
|
||||
(url) => {
|
||||
const country = countryStore.data
|
||||
if (url.startsWith("https://data.velopark.be/")) {
|
||||
if (maproulette_id_key === "" || maproulette_id_key === undefined) {
|
||||
maproulette_id_key = "mr_taskId"
|
||||
}
|
||||
statusToSet = statusToSet ?? "1"
|
||||
return new SvelteUIElement(MaprouletteSetStatus, {
|
||||
state,
|
||||
tags: tagsSource,
|
||||
message,
|
||||
image,
|
||||
message_closed,
|
||||
statusToSet,
|
||||
maproulette_id_key,
|
||||
askFeedback,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "linked_data_from_website",
|
||||
group: "data_import",
|
||||
docs: "Attempts to load (via a proxy) the specified website and parsed ld+json from there. Suitable data will be offered to import into OSM. Note: this element is added by default",
|
||||
args: [
|
||||
{
|
||||
name: "key",
|
||||
defaultValue: "website",
|
||||
doc: "Attempt to load ld+json from the specified URL. This can be in an embedded <script type='ld+json'>",
|
||||
},
|
||||
{
|
||||
name: "useProxy",
|
||||
defaultValue: "yes",
|
||||
doc: "If 'yes', uses the provided proxy server. This proxy server will scrape HTML and search for a script with `lang='ld+json'`. If `no`, the data will be downloaded and expects a linked-data-json directly",
|
||||
},
|
||||
{
|
||||
name: "host",
|
||||
doc: "If not using a proxy, define what host the website is allowed to connect to",
|
||||
},
|
||||
{
|
||||
name: "mode",
|
||||
doc: "If `display`, only show the data in tabular and readonly form, ignoring already existing tags. This is used to explicitly show all the tags. If unset or anything else, allow to apply/import on OSM",
|
||||
},
|
||||
{
|
||||
name: "collapsed",
|
||||
defaultValue: "yes",
|
||||
doc: "If the containing accordion should be closed",
|
||||
},
|
||||
],
|
||||
needsUrls: [Constants.linkedDataProxy, "http://www.schema.org"],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tags: UIEventSource<Record<string, string>>,
|
||||
argument: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): BaseUIElement {
|
||||
const key = argument[0] ?? "website"
|
||||
const useProxy = argument[1] !== "no"
|
||||
const readonly = argument[3] === "readonly"
|
||||
const isClosed = (argument[4] ?? "yes") === "yes"
|
||||
|
||||
const countryStore: Store<string | undefined> = tags.mapD(
|
||||
(tags) => tags._country
|
||||
)
|
||||
const sourceUrl: Store<string | undefined> = tags.mapD((tags) => {
|
||||
if (!tags[key] || tags[key] === "undefined") {
|
||||
return null
|
||||
}
|
||||
return tags[key]
|
||||
})
|
||||
const externalData: Store<{ success: GeoJsonProperties } | { error }> =
|
||||
sourceUrl.bindD(
|
||||
(url) => {
|
||||
const country = countryStore.data
|
||||
if (url.startsWith("https://data.velopark.be/")) {
|
||||
return Stores.FromPromiseWithErr(
|
||||
(async () => {
|
||||
try {
|
||||
const loadAll =
|
||||
layer.id.toLowerCase().indexOf("maproulette") >=
|
||||
0 // Dirty hack
|
||||
const features =
|
||||
await LinkedDataLoader.fetchVeloparkEntry(
|
||||
url,
|
||||
loadAll
|
||||
)
|
||||
const feature =
|
||||
features.find(
|
||||
(f) => f.properties["ref:velopark"] === url
|
||||
) ?? features[0]
|
||||
const properties = feature.properties
|
||||
properties["ref:velopark"] = url
|
||||
console.log(
|
||||
"Got properties from velopark:",
|
||||
properties
|
||||
)
|
||||
return properties
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
throw e
|
||||
}
|
||||
})()
|
||||
)
|
||||
}
|
||||
if (country === undefined) {
|
||||
return undefined
|
||||
}
|
||||
return Stores.FromPromiseWithErr(
|
||||
(async () => {
|
||||
try {
|
||||
const loadAll =
|
||||
layer.id.toLowerCase().indexOf("maproulette") >=
|
||||
0 // Dirty hack
|
||||
const features =
|
||||
await LinkedDataLoader.fetchVeloparkEntry(
|
||||
url,
|
||||
loadAll
|
||||
)
|
||||
const feature =
|
||||
features.find(
|
||||
(f) => f.properties["ref:velopark"] === url
|
||||
) ?? features[0]
|
||||
const properties = feature.properties
|
||||
properties["ref:velopark"] = url
|
||||
console.log(
|
||||
"Got properties from velopark:",
|
||||
properties
|
||||
return await LinkedDataLoader.fetchJsonLd(
|
||||
url,
|
||||
{ country },
|
||||
useProxy ? "proxy" : "fetch-lod"
|
||||
)
|
||||
return properties
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
throw e
|
||||
console.log(
|
||||
"Could not get with proxy/download LOD, attempting to download directly. Error for ",
|
||||
url,
|
||||
"is",
|
||||
e
|
||||
)
|
||||
return await LinkedDataLoader.fetchJsonLd(
|
||||
url,
|
||||
{ country },
|
||||
"fetch-raw"
|
||||
)
|
||||
}
|
||||
})()
|
||||
)
|
||||
}
|
||||
if (country === undefined) {
|
||||
return undefined
|
||||
}
|
||||
return Stores.FromPromiseWithErr(
|
||||
(async () => {
|
||||
try {
|
||||
return await LinkedDataLoader.fetchJsonLd(
|
||||
url,
|
||||
{ country },
|
||||
useProxy ? "proxy" : "fetch-lod"
|
||||
)
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"Could not get with proxy/download LOD, attempting to download directly. Error for ",
|
||||
url,
|
||||
"is",
|
||||
e
|
||||
)
|
||||
return await LinkedDataLoader.fetchJsonLd(
|
||||
url,
|
||||
{ country },
|
||||
"fetch-raw"
|
||||
)
|
||||
}
|
||||
})()
|
||||
)
|
||||
},
|
||||
[countryStore]
|
||||
},
|
||||
[countryStore]
|
||||
)
|
||||
|
||||
externalData.addCallbackAndRunD((lod) =>
|
||||
console.log("linked_data_from_website received the following data:", lod)
|
||||
)
|
||||
|
||||
externalData.addCallbackAndRunD((lod) =>
|
||||
console.log("linked_data_from_website received the following data:", lod)
|
||||
)
|
||||
|
||||
return new Toggle(
|
||||
new SvelteUIElement(ComparisonTool, {
|
||||
feature,
|
||||
return new Toggle(
|
||||
new SvelteUIElement(ComparisonTool, {
|
||||
feature,
|
||||
state,
|
||||
tags,
|
||||
layer,
|
||||
externalData,
|
||||
sourceUrl,
|
||||
readonly,
|
||||
collapsed: isClosed,
|
||||
}),
|
||||
undefined,
|
||||
sourceUrl.map((url) => !!url)
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "compare_data",
|
||||
group: "data_import",
|
||||
needsUrls: (args) => args[1].split(";"),
|
||||
args: [
|
||||
{
|
||||
name: "url",
|
||||
required: true,
|
||||
doc: "The attribute containing the url where to fetch more data",
|
||||
},
|
||||
{
|
||||
name: "host",
|
||||
required: true,
|
||||
doc: "The domain name(s) where data might be fetched from - this is needed to set the CSP. A domain must include 'https', e.g. 'https://example.com'. For multiple domains, separate them with ';'. If you don't know the possible domains, use '*'. ",
|
||||
},
|
||||
{
|
||||
name: "readonly",
|
||||
required: false,
|
||||
doc: "If 'yes', will not show 'apply'-buttons",
|
||||
},
|
||||
],
|
||||
docs: "Gives an interactive element which shows a tag comparison between the OSM-object and the upstream object. This allows to copy some or all tags into OSM",
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
args: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): BaseUIElement {
|
||||
const url = args[0]
|
||||
const readonly = args[3] === "yes"
|
||||
const externalData = Stores.FromPromiseWithErr(Utils.downloadJson(url))
|
||||
return new SvelteUIElement(ComparisonTool, {
|
||||
url,
|
||||
state,
|
||||
tags,
|
||||
tags: tagSource,
|
||||
layer,
|
||||
externalData,
|
||||
sourceUrl,
|
||||
feature,
|
||||
readonly,
|
||||
collapsed: isClosed
|
||||
}),
|
||||
undefined,
|
||||
sourceUrl.map((url) => !!url)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
funcName: "compare_data",
|
||||
group: "data_import",
|
||||
needsUrls: (args) => args[1].split(";"),
|
||||
args: [
|
||||
{
|
||||
name: "url",
|
||||
required: true,
|
||||
doc: "The attribute containing the url where to fetch more data"
|
||||
externalData,
|
||||
})
|
||||
},
|
||||
{
|
||||
name: "host",
|
||||
required: true,
|
||||
doc: "The domain name(s) where data might be fetched from - this is needed to set the CSP. A domain must include 'https', e.g. 'https://example.com'. For multiple domains, separate them with ';'. If you don't know the possible domains, use '*'. "
|
||||
},
|
||||
{
|
||||
name: "readonly",
|
||||
required: false,
|
||||
doc: "If 'yes', will not show 'apply'-buttons"
|
||||
}
|
||||
],
|
||||
docs: "Gives an interactive element which shows a tag comparison between the OSM-object and the upstream object. This allows to copy some or all tags into OSM",
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
args: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): BaseUIElement {
|
||||
const url = args[0]
|
||||
const readonly = args[3] === "yes"
|
||||
const externalData = Stores.FromPromiseWithErr(Utils.downloadJson(url))
|
||||
return new SvelteUIElement(ComparisonTool, {
|
||||
url,
|
||||
state,
|
||||
tags: tagSource,
|
||||
layer,
|
||||
feature,
|
||||
readonly,
|
||||
externalData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,27 +8,28 @@ import MarkAsFavouriteMini from "../Popup/MarkAsFavouriteMini.svelte"
|
|||
|
||||
export class FavouriteVisualisations {
|
||||
public static initList(): SpecialVisualizationSvelte[] {
|
||||
return [{
|
||||
funcName: "favourite_status",
|
||||
return [
|
||||
{
|
||||
funcName: "favourite_status",
|
||||
|
||||
docs: "A button that allows a (logged in) contributor to mark a location as a favourite location",
|
||||
args: [],
|
||||
group: "favourites",
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
argument: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(MarkAsFavourite, {
|
||||
tags: tagSource,
|
||||
state,
|
||||
layer,
|
||||
feature
|
||||
})
|
||||
}
|
||||
},
|
||||
docs: "A button that allows a (logged in) contributor to mark a location as a favourite location",
|
||||
args: [],
|
||||
group: "favourites",
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
argument: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(MarkAsFavourite, {
|
||||
tags: tagSource,
|
||||
state,
|
||||
layer,
|
||||
feature,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "favourite_icon",
|
||||
group: "favourites",
|
||||
|
|
@ -45,9 +46,10 @@ export class FavouriteVisualisations {
|
|||
tags: tagSource,
|
||||
state,
|
||||
layer,
|
||||
feature
|
||||
feature,
|
||||
})
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ class NearbyImageVis implements SpecialVisualizationSvelte {
|
|||
{
|
||||
name: "mode",
|
||||
defaultValue: "closed",
|
||||
doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown"
|
||||
doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown",
|
||||
},
|
||||
{
|
||||
name: "readonly",
|
||||
required: false,
|
||||
doc: "If 'readonly' or 'yes', will not show the 'link'-button"
|
||||
}
|
||||
doc: "If 'readonly' or 'yes', will not show the 'link'-button",
|
||||
},
|
||||
]
|
||||
group: "images"
|
||||
docs =
|
||||
|
|
@ -49,13 +49,12 @@ class NearbyImageVis implements SpecialVisualizationSvelte {
|
|||
lat,
|
||||
feature,
|
||||
layer,
|
||||
linkable: !readonly
|
||||
linkable: !readonly,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class ImageVisualisations {
|
||||
|
||||
static initList(): SpecialVisualizationSvelte[] {
|
||||
return [
|
||||
new NearbyImageVis(),
|
||||
|
|
@ -67,8 +66,8 @@ export class ImageVisualisations {
|
|||
{
|
||||
name: "image_key",
|
||||
defaultValue: AllImageProviders.defaultKeys.join(","),
|
||||
doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... Multiple values are allowed if ';'-separated "
|
||||
}
|
||||
doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... Multiple values are allowed if ';'-separated ",
|
||||
},
|
||||
],
|
||||
needsUrls: AllImageProviders.apiUrls,
|
||||
constr: (state, tags, args) => {
|
||||
|
|
@ -77,9 +76,11 @@ export class ImageVisualisations {
|
|||
imagePrefixes = [].concat(...args.map((a) => a.split(",")))
|
||||
}
|
||||
const images = AllImageProviders.loadImagesFor(tags, imagePrefixes)
|
||||
const estimated = tags.mapD(tags => AllImageProviders.estimateNumberOfImages(tags, imagePrefixes))
|
||||
const estimated = tags.mapD((tags) =>
|
||||
AllImageProviders.estimateNumberOfImages(tags, imagePrefixes)
|
||||
)
|
||||
return new SvelteUIElement(ImageCarousel, { state, tags, images, estimated })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "image_upload",
|
||||
|
|
@ -90,18 +91,18 @@ export class ImageVisualisations {
|
|||
{
|
||||
name: "image-key",
|
||||
doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)",
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "label",
|
||||
doc: "The text to show on the button",
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "disable_blur",
|
||||
doc: "If set to 'true' or 'yes', then face blurring will be disabled. To be used sparingly",
|
||||
required: false
|
||||
}
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
constr: (state, tags, args, feature) => {
|
||||
const targetKey = args[0] === "" ? undefined : args[0]
|
||||
|
|
@ -113,10 +114,10 @@ export class ImageVisualisations {
|
|||
feature,
|
||||
labelText: args[1],
|
||||
image: args[2],
|
||||
noBlur: noBlur === "true" || noBlur === "yes"
|
||||
noBlur: noBlur === "true" || noBlur === "yes",
|
||||
})
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization"
|
||||
import {
|
||||
SpecialVisualization,
|
||||
SpecialVisualizationState,
|
||||
SpecialVisualizationSvelte,
|
||||
} from "../SpecialVisualization"
|
||||
import Constants from "../../Models/Constants"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Feature } from "geojson"
|
||||
|
|
@ -24,30 +28,30 @@ class CloseNoteViz implements SpecialVisualizationSvelte {
|
|||
{
|
||||
name: "text",
|
||||
doc: "Text to show on this button",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "icon",
|
||||
doc: "Icon to show",
|
||||
defaultValue: "checkmark.svg"
|
||||
defaultValue: "checkmark.svg",
|
||||
},
|
||||
{
|
||||
name: "idkey",
|
||||
doc: "The property name where the ID of the note to close can be found",
|
||||
defaultValue: "id"
|
||||
defaultValue: "id",
|
||||
},
|
||||
{
|
||||
name: "comment",
|
||||
doc: "Text to add onto the note when closing"
|
||||
doc: "Text to add onto the note when closing",
|
||||
},
|
||||
{
|
||||
name: "minZoom",
|
||||
doc: "If set, only show the closenote button if zoomed in enough"
|
||||
doc: "If set, only show the closenote button if zoomed in enough",
|
||||
},
|
||||
{
|
||||
name: "zoomButton",
|
||||
doc: "Text to show if not zoomed in enough"
|
||||
}
|
||||
doc: "Text to show if not zoomed in enough",
|
||||
},
|
||||
]
|
||||
public readonly group: "notes"
|
||||
|
||||
|
|
@ -69,12 +73,11 @@ class CloseNoteViz implements SpecialVisualizationSvelte {
|
|||
message: comment,
|
||||
text: Translations.T(text),
|
||||
minzoom: minZoom,
|
||||
zoomMoreMessage: zoomButton
|
||||
zoomMoreMessage: zoomButton,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AddNoteCommentViz implements SpecialVisualizationSvelte {
|
||||
funcName = "add_note_comment"
|
||||
needsUrls = [Constants.osmAuthConfig.url]
|
||||
|
|
@ -83,21 +86,23 @@ class AddNoteCommentViz implements SpecialVisualizationSvelte {
|
|||
{
|
||||
name: "Id-key",
|
||||
doc: "The property name where the ID of the note to close can be found",
|
||||
defaultValue: "id"
|
||||
}
|
||||
defaultValue: "id",
|
||||
},
|
||||
]
|
||||
public readonly group: "notes"
|
||||
|
||||
|
||||
public constr(state: SpecialVisualizationState, tags: UIEventSource<Record<string, string>>): SvelteUIElement {
|
||||
public constr(
|
||||
state: SpecialVisualizationState,
|
||||
tags: UIEventSource<Record<string, string>>
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(AddNoteComment, { state, tags })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class NoteVisualisations {
|
||||
public static initList(): (SpecialVisualization & { group })[] {
|
||||
return [new AddNoteCommentViz(),
|
||||
return [
|
||||
new AddNoteCommentViz(),
|
||||
new CloseNoteViz(),
|
||||
{
|
||||
funcName: "open_note",
|
||||
|
|
@ -114,9 +119,9 @@ export class NoteVisualisations {
|
|||
const [lon, lat] = GeoOperations.centerpointCoordinates(feature)
|
||||
return new SvelteUIElement(CreateNewNote, {
|
||||
state,
|
||||
coordinate: new UIEventSource({ lon, lat })
|
||||
coordinate: new UIEventSource({ lon, lat }),
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "add_image_to_note",
|
||||
|
|
@ -125,8 +130,8 @@ export class NoteVisualisations {
|
|||
{
|
||||
name: "Id-key",
|
||||
doc: "The property name where the ID of the note to close can be found",
|
||||
defaultValue: "id"
|
||||
}
|
||||
defaultValue: "id",
|
||||
},
|
||||
],
|
||||
group: "notes",
|
||||
needsUrls: [Imgur.apiUrl, ...Imgur.supportingUrls],
|
||||
|
|
@ -135,7 +140,7 @@ export class NoteVisualisations {
|
|||
const id = tags.data[args[0] ?? "id"]
|
||||
tags = state.featureProperties.getStore(id)
|
||||
return new SvelteUIElement(UploadImage, { state, tags, layer, feature })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "visualize_note_comments",
|
||||
|
|
@ -145,13 +150,13 @@ export class NoteVisualisations {
|
|||
{
|
||||
name: "commentsKey",
|
||||
doc: "The property name of the comments, which should be stringified json",
|
||||
defaultValue: "comments"
|
||||
defaultValue: "comments",
|
||||
},
|
||||
{
|
||||
name: "start",
|
||||
doc: "Drop the first 'start' comments",
|
||||
defaultValue: "0"
|
||||
}
|
||||
defaultValue: "0",
|
||||
},
|
||||
],
|
||||
needsUrls: [Constants.osmAuthConfig.url],
|
||||
constr: (state, tags, args) =>
|
||||
|
|
@ -171,13 +176,13 @@ export class NoteVisualisations {
|
|||
(comment) =>
|
||||
new SvelteUIElement(NoteCommentElement, {
|
||||
comment,
|
||||
state
|
||||
state,
|
||||
})
|
||||
)
|
||||
).SetClass("flex flex-col")
|
||||
})
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,16 +24,16 @@ export class ReviewSpecialVisualisations {
|
|||
{
|
||||
name: "subjectKey",
|
||||
defaultValue: "name",
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>"
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>",
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value"
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value",
|
||||
},
|
||||
{
|
||||
name: "question",
|
||||
doc: "The question to ask during the review"
|
||||
}
|
||||
doc: "The question to ask during the review",
|
||||
},
|
||||
],
|
||||
constr: (state, tags, args, feature, layer) => {
|
||||
const nameKey = args[0] ?? "name"
|
||||
|
|
@ -45,7 +45,7 @@ export class ReviewSpecialVisualisations {
|
|||
state.userRelatedState?.mangroveIdentity,
|
||||
{
|
||||
nameKey: nameKey,
|
||||
fallbackName
|
||||
fallbackName,
|
||||
},
|
||||
state.featureSwitchIsTesting
|
||||
)
|
||||
|
|
@ -55,9 +55,9 @@ export class ReviewSpecialVisualisations {
|
|||
tags,
|
||||
feature,
|
||||
layer,
|
||||
question
|
||||
question,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
const listReviews: SpecialVisualization & { group } = {
|
||||
funcName: "list_reviews",
|
||||
|
|
@ -69,12 +69,12 @@ export class ReviewSpecialVisualisations {
|
|||
{
|
||||
name: "subjectKey",
|
||||
defaultValue: "name",
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>"
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>",
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value"
|
||||
}
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value",
|
||||
},
|
||||
],
|
||||
constr: (state, tags, args, feature, layer) => {
|
||||
const nameKey = args[0] ?? "name"
|
||||
|
|
@ -85,12 +85,12 @@ export class ReviewSpecialVisualisations {
|
|||
state.userRelatedState?.mangroveIdentity,
|
||||
{
|
||||
nameKey: nameKey,
|
||||
fallbackName
|
||||
fallbackName,
|
||||
},
|
||||
state.featureSwitchIsTesting
|
||||
)
|
||||
return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer })
|
||||
}
|
||||
},
|
||||
}
|
||||
return [
|
||||
{
|
||||
|
|
@ -102,12 +102,12 @@ export class ReviewSpecialVisualisations {
|
|||
{
|
||||
name: "subjectKey",
|
||||
defaultValue: "name",
|
||||
doc: "The key to use to determine the subject. If the value is specified, the subject will be <b>tags[subjectKey]</b> and will use this to filter the reviews."
|
||||
doc: "The key to use to determine the subject. If the value is specified, the subject will be <b>tags[subjectKey]</b> and will use this to filter the reviews.",
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value"
|
||||
}
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value",
|
||||
},
|
||||
],
|
||||
constr: (state, tags, args, feature) => {
|
||||
const nameKey = args[0] ?? "name"
|
||||
|
|
@ -118,14 +118,14 @@ export class ReviewSpecialVisualisations {
|
|||
state.userRelatedState.mangroveIdentity,
|
||||
{
|
||||
nameKey: nameKey,
|
||||
fallbackName
|
||||
fallbackName,
|
||||
},
|
||||
state.featureSwitchIsTesting
|
||||
)
|
||||
return new SvelteUIElement(StarsBarIcon, {
|
||||
score: reviews.average
|
||||
score: reviews.average,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
createReview,
|
||||
listReviews,
|
||||
|
|
@ -137,8 +137,8 @@ export class ReviewSpecialVisualisations {
|
|||
args: [
|
||||
{
|
||||
name: "text",
|
||||
doc: "The text that is shown on the button"
|
||||
}
|
||||
doc: "The text that is shown on the button",
|
||||
},
|
||||
],
|
||||
needsUrls: [],
|
||||
constr(
|
||||
|
|
@ -148,7 +148,7 @@ export class ReviewSpecialVisualisations {
|
|||
): SvelteUIElement {
|
||||
const [text] = argument
|
||||
return new SvelteUIElement(ImportReviewIdentity, { state, text })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "reviews",
|
||||
|
|
@ -161,16 +161,16 @@ export class ReviewSpecialVisualisations {
|
|||
{
|
||||
name: "subjectKey",
|
||||
defaultValue: "name",
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>"
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>",
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value"
|
||||
doc: "The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value",
|
||||
},
|
||||
{
|
||||
name: "question",
|
||||
doc: "The question to ask in the review form. Optional"
|
||||
}
|
||||
doc: "The question to ask in the review form. Optional",
|
||||
},
|
||||
],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
|
|
@ -182,10 +182,10 @@ export class ReviewSpecialVisualisations {
|
|||
return new Combine([
|
||||
createReview.constr(state, tagSource, args, feature, layer),
|
||||
|
||||
listReviews.constr(state, tagSource, args, feature, layer)
|
||||
listReviews.constr(state, tagSource, args, feature, layer),
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,17 +24,16 @@ export class SettingsVisualisations {
|
|||
docs: "A component to set the language of the user interface",
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
const availableLanguages = Locale.showLinkToWeblate.map((showTranslations) =>
|
||||
showTranslations
|
||||
? LanguageUtils.usedLanguagesSorted
|
||||
: state.theme.language)
|
||||
showTranslations ? LanguageUtils.usedLanguagesSorted : state.theme.language
|
||||
)
|
||||
return new SvelteUIElement(LanguagePicker, {
|
||||
assignTo: state.userRelatedState.language,
|
||||
availableLanguages,
|
||||
preferredLanguages: state.osmConnection.userDetails.map(
|
||||
(ud) => ud?.languages ?? []
|
||||
)
|
||||
),
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -45,7 +44,7 @@ export class SettingsVisualisations {
|
|||
args: [],
|
||||
constr(state) {
|
||||
return new SvelteUIElement(DisabledQuestions, { state })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "gyroscope_all_tags",
|
||||
|
|
@ -54,16 +53,14 @@ export class SettingsVisualisations {
|
|||
args: [],
|
||||
constr(): SvelteUIElement {
|
||||
return new SvelteUIElement(OrientationDebugPanel, {})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "gps_all_tags",
|
||||
group: "settings",
|
||||
docs: "Shows the current tags of the GPS-representing object, used for debugging",
|
||||
args: [],
|
||||
constr(
|
||||
state: SpecialVisualizationState
|
||||
): SvelteUIElement {
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
const tags = (<ThemeViewState>(
|
||||
state
|
||||
)).geolocation.currentUserLocation.features.map(
|
||||
|
|
@ -71,25 +68,23 @@ export class SettingsVisualisations {
|
|||
)
|
||||
return new SvelteUIElement(AllTagsPanel, {
|
||||
state,
|
||||
tags
|
||||
tags,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "storage_all_tags",
|
||||
group: "settings",
|
||||
docs: "Shows the current state of storage",
|
||||
args: [],
|
||||
constr(
|
||||
state: SpecialVisualizationState
|
||||
): SvelteUIElement {
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
const data = {}
|
||||
for (const key in localStorage) {
|
||||
data[key] = localStorage[key]
|
||||
}
|
||||
const tags = new ImmutableStore(data)
|
||||
return new SvelteUIElement(AllTagsPanel, { state, tags })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "clear_caches",
|
||||
|
|
@ -98,8 +93,8 @@ export class SettingsVisualisations {
|
|||
{
|
||||
name: "text",
|
||||
required: true,
|
||||
doc: "The text to show on the button"
|
||||
}
|
||||
doc: "The text to show on the button",
|
||||
},
|
||||
],
|
||||
group: "settings",
|
||||
constr(
|
||||
|
|
@ -108,9 +103,9 @@ export class SettingsVisualisations {
|
|||
argument: string[]
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(ClearCaches, {
|
||||
msg: argument[0] ?? "Clear local caches"
|
||||
msg: argument[0] ?? "Clear local caches",
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "login_button",
|
||||
|
|
@ -120,7 +115,7 @@ export class SettingsVisualisations {
|
|||
group: "settings",
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
return new SvelteUIElement(LoginButton, { osmConnection: state.osmConnection })
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -131,7 +126,7 @@ export class SettingsVisualisations {
|
|||
group: "settings",
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "pending_changes",
|
||||
|
|
@ -140,8 +135,8 @@ export class SettingsVisualisations {
|
|||
args: [],
|
||||
constr(state: SpecialVisualizationState): SvelteUIElement {
|
||||
return new SvelteUIElement(PendingChangesIndicator, { state, compact: false })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.sve
|
|||
import Combine from "../Base/Combine"
|
||||
|
||||
class StealViz implements SpecialVisualization {
|
||||
|
||||
funcName = "steal"
|
||||
group = "tagrendering_manipulation"
|
||||
|
||||
|
|
@ -24,13 +23,13 @@ class StealViz implements SpecialVisualization {
|
|||
{
|
||||
name: "featureId",
|
||||
doc: "The key of the attribute which contains the id of the feature from which to use the tags",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "tagRenderingId",
|
||||
doc: "The layer-id and tagRenderingId to render. Can be multiple value if ';'-separated (in which case every value must also contain the layerId, e.g. `layerId.tagRendering0; layerId.tagRendering1`). Note: this can cause layer injection",
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
]
|
||||
needsUrls = []
|
||||
svelteBased = true
|
||||
|
|
@ -64,7 +63,7 @@ class StealViz implements SpecialVisualization {
|
|||
tags: otherTags,
|
||||
selectedElement: otherFeature,
|
||||
state,
|
||||
layer
|
||||
layer,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
@ -89,7 +88,6 @@ class StealViz implements SpecialVisualization {
|
|||
}
|
||||
|
||||
export default class TagrenderingManipulationSpecialVisualisations {
|
||||
|
||||
public static initList(): (SpecialVisualization & { group })[] {
|
||||
return [
|
||||
new StealViz(),
|
||||
|
|
@ -106,10 +104,10 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
type: "multi",
|
||||
key: "_doors_from_building_properties",
|
||||
tagrendering: {
|
||||
en: "The building containing this feature has a <a href='#{id}'>door</a> of width {entrance:width}"
|
||||
}
|
||||
}
|
||||
}
|
||||
en: "The building containing this feature has a <a href='#{id}'>door</a> of width {entrance:width}",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
null,
|
||||
" "
|
||||
|
|
@ -119,17 +117,17 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
{
|
||||
name: "key",
|
||||
doc: "The property to read and to interpret as a list of properties",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "tagrendering",
|
||||
doc: "An entire tagRenderingConfig",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "classes",
|
||||
doc: "CSS-classes to apply on every individual item. Seperated by `space`"
|
||||
}
|
||||
doc: "CSS-classes to apply on every individual item. Seperated by `space`",
|
||||
},
|
||||
],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
|
|
@ -147,7 +145,7 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
if (typeof tags[key] === "string") {
|
||||
properties = JSON.parse(tags[key])
|
||||
} else {
|
||||
properties = <object[]><unknown>tags[key]
|
||||
properties = <object[]>(<unknown>tags[key])
|
||||
}
|
||||
if (!properties) {
|
||||
console.debug(
|
||||
|
|
@ -165,7 +163,7 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
tags: new ImmutableStore(property),
|
||||
state,
|
||||
feature,
|
||||
layer
|
||||
layer,
|
||||
// clss: classes ?? "",
|
||||
}).SetClass(classes)
|
||||
elements.push(subsTr)
|
||||
|
|
@ -173,7 +171,7 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
return elements
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "group",
|
||||
|
|
@ -182,12 +180,12 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
args: [
|
||||
{
|
||||
name: "header",
|
||||
doc: "The _identifier_ of a single tagRendering. This will be used as header"
|
||||
doc: "The _identifier_ of a single tagRendering. This will be used as header",
|
||||
},
|
||||
{
|
||||
name: "labels",
|
||||
doc: "A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion"
|
||||
}
|
||||
doc: "A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion",
|
||||
},
|
||||
],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
|
|
@ -204,9 +202,9 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
selectedElement,
|
||||
layer,
|
||||
header,
|
||||
labels
|
||||
labels,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "open_in_iD",
|
||||
|
|
@ -216,9 +214,9 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
constr: (state, feature): SvelteUIElement => {
|
||||
return new SvelteUIElement(OpenIdEditor, {
|
||||
mapProperties: state.mapProperties,
|
||||
objectId: feature.data.id
|
||||
objectId: feature.data.id,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "open_in_josm",
|
||||
|
|
@ -229,9 +227,8 @@ export default class TagrenderingManipulationSpecialVisualisations {
|
|||
|
||||
constr: (state): SvelteUIElement => {
|
||||
return new SvelteUIElement(OpenJosm, { state })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ class QuestionViz implements SpecialVisualizationSvelte {
|
|||
args = [
|
||||
{
|
||||
name: "labels",
|
||||
doc: "One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown"
|
||||
doc: "One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown",
|
||||
},
|
||||
{
|
||||
name: "blacklisted-labels",
|
||||
doc: "One or more ';'-separated labels of questions which should _not_ be included"
|
||||
}
|
||||
doc: "One or more ';'-separated labels of questions which should _not_ be included",
|
||||
},
|
||||
]
|
||||
svelteBased = true
|
||||
group: "default"
|
||||
|
|
@ -42,7 +42,6 @@ class QuestionViz implements SpecialVisualizationSvelte {
|
|||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): SvelteUIElement {
|
||||
|
||||
const labels = args[0]
|
||||
?.split(";")
|
||||
?.map((s) => s.trim())
|
||||
|
|
@ -57,14 +56,15 @@ class QuestionViz implements SpecialVisualizationSvelte {
|
|||
selectedElement: feature,
|
||||
state,
|
||||
onlyForLabels: labels,
|
||||
notForLabels: blacklist
|
||||
notForLabels: blacklist,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class UISpecialVisualisations {
|
||||
public static initList(): SpecialVisualizationSvelte [] {
|
||||
return [new QuestionViz(),
|
||||
public static initList(): SpecialVisualizationSvelte[] {
|
||||
return [
|
||||
new QuestionViz(),
|
||||
{
|
||||
funcName: "minimap",
|
||||
docs: "A small map showing the selected feature.",
|
||||
|
|
@ -75,13 +75,13 @@ export class UISpecialVisualisations {
|
|||
{
|
||||
doc: "The (maximum) zoomlevel: the target zoomlevel after fitting the entire feature. The minimap will fit the entire feature, then zoom out to this zoom level. The higher, the more zoomed in with 1 being the entire world and 19 being really close",
|
||||
name: "zoomlevel",
|
||||
defaultValue: "18"
|
||||
defaultValue: "18",
|
||||
},
|
||||
{
|
||||
doc: "(Matches all resting arguments) This argument should be the key of a property of the feature. The corresponding value is interpreted as either the id or the a list of ID's. The features with these ID's will be shown on this minimap. (Note: if the key is 'id', list interpration is disabled)",
|
||||
name: "idKey",
|
||||
defaultValue: "id"
|
||||
}
|
||||
defaultValue: "id",
|
||||
},
|
||||
],
|
||||
example:
|
||||
"`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`",
|
||||
|
|
@ -93,7 +93,7 @@ export class UISpecialVisualisations {
|
|||
feature: Feature
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(MinimapViz, { state, args, feature, tagSource })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "split_button",
|
||||
|
|
@ -105,8 +105,11 @@ export class UISpecialVisualisations {
|
|||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(SplitRoadWizard, { id: tagSource.map(pr => pr.id), state })
|
||||
}
|
||||
return new SvelteUIElement(SplitRoadWizard, {
|
||||
id: tagSource.map((pr) => pr.id),
|
||||
state,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "move_button",
|
||||
|
|
@ -127,9 +130,9 @@ export class UISpecialVisualisations {
|
|||
return new SvelteUIElement(MoveWizard, {
|
||||
state,
|
||||
featureToMove: feature,
|
||||
layer
|
||||
layer,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "delete_button",
|
||||
|
|
@ -152,9 +155,9 @@ export class UISpecialVisualisations {
|
|||
deleteConfig: layer.deletion,
|
||||
state,
|
||||
feature,
|
||||
layer
|
||||
layer,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "qr_code",
|
||||
|
|
@ -168,7 +171,7 @@ export class UISpecialVisualisations {
|
|||
feature: Feature
|
||||
): SvelteUIElement {
|
||||
return new SvelteUIElement(QrCode, { state, tags, feature })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "if_nothing_known",
|
||||
|
|
@ -176,9 +179,9 @@ export class UISpecialVisualisations {
|
|||
{
|
||||
name: "text",
|
||||
doc: "Text to show",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{ name: "cssClasses", doc: "Classes to apply onto the text" }
|
||||
{ name: "cssClasses", doc: "Classes to apply onto the text" },
|
||||
],
|
||||
group: "default",
|
||||
docs: "Shows a 'nothing is currently known-message if there is at least one unanswered question and no known (answerable) question",
|
||||
|
|
@ -196,9 +199,9 @@ export class UISpecialVisualisations {
|
|||
tags: tagSource,
|
||||
layer,
|
||||
text,
|
||||
cssClasses
|
||||
cssClasses,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
new ShareLinkViz(),
|
||||
{
|
||||
|
|
@ -210,10 +213,10 @@ export class UISpecialVisualisations {
|
|||
const [lon, lat] = GeoOperations.centerpointCoordinates(feature)
|
||||
return new SvelteUIElement(AddNewPoint, {
|
||||
state,
|
||||
coordinate: { lon, lat }
|
||||
coordinate: { lon, lat },
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import SendEmail from "../Popup/SendEmail.svelte"
|
|||
import DynLink from "../Base/DynLink.svelte"
|
||||
|
||||
export class WebAndCommunicationSpecialVisualisations {
|
||||
public static initList(): (SpecialVisualization & { group }) [] {
|
||||
public static initList(): (SpecialVisualization & { group })[] {
|
||||
return [
|
||||
|
||||
{
|
||||
funcName: "fediverse_link",
|
||||
group: "web_and_communication",
|
||||
|
|
@ -25,8 +24,8 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
{
|
||||
name: "key",
|
||||
doc: "The attribute-name containing the link",
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
|
||||
constr(
|
||||
|
|
@ -36,7 +35,7 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
): BaseUIElement {
|
||||
const key = argument[0]
|
||||
return new SvelteUIElement(FediverseLink, { key, tags, state })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "wikipedia",
|
||||
|
|
@ -46,8 +45,8 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
{
|
||||
name: "keyToShowWikipediaFor",
|
||||
doc: "Use the wikidata entry from this key to show the wikipedia article for. Multiple keys can be given (separated by ';'), in which case the first matching value is used",
|
||||
defaultValue: "wikidata;wikipedia"
|
||||
}
|
||||
defaultValue: "wikidata;wikipedia",
|
||||
},
|
||||
],
|
||||
needsUrls: [...Wikidata.neededUrls, ...Wikipedia.neededUrls],
|
||||
|
||||
|
|
@ -60,9 +59,9 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
return tags[key]?.split(";")?.map((id) => id.trim()) ?? []
|
||||
})
|
||||
return new SvelteUIElement(WikipediaPanel, {
|
||||
wikiIds
|
||||
wikiIds,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "wikidata_label",
|
||||
|
|
@ -73,8 +72,8 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
{
|
||||
name: "keyToShowWikidataFor",
|
||||
doc: "Use the wikidata entry from this key to show the label",
|
||||
defaultValue: "wikidata"
|
||||
}
|
||||
defaultValue: "wikidata",
|
||||
},
|
||||
],
|
||||
needsUrls: Wikidata.neededUrls,
|
||||
example:
|
||||
|
|
@ -98,7 +97,7 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
),
|
||||
},
|
||||
new MapillaryLinkVis(),
|
||||
{
|
||||
|
|
@ -109,29 +108,29 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
{
|
||||
name: "to",
|
||||
doc: "Who to send the email to?",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "subject",
|
||||
doc: "The subject of the email",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "body",
|
||||
doc: "The text in the email",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "button_text",
|
||||
doc: "The text shown on the button in the UI",
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
|
||||
constr(__, tags, args) {
|
||||
return new SvelteUIElement(SendEmail, { args, tags })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "link",
|
||||
|
|
@ -141,29 +140,29 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
{
|
||||
name: "text",
|
||||
doc: "Text to be shown",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "href",
|
||||
doc: "The URL to link to. Note that this will be URI-encoded before ",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "class",
|
||||
doc: "CSS-classes to add to the element"
|
||||
doc: "CSS-classes to add to the element",
|
||||
},
|
||||
{
|
||||
name: "download",
|
||||
doc: "Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button."
|
||||
doc: "Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button.",
|
||||
},
|
||||
{
|
||||
name: "arialabel",
|
||||
doc: "If set, this text will be used as aria-label"
|
||||
doc: "If set, this text will be used as aria-label",
|
||||
},
|
||||
{
|
||||
name: "icon",
|
||||
doc: "If set, show this icon next to the link. You might want to combine this with `class: button`"
|
||||
}
|
||||
doc: "If set, show this icon next to the link. You might want to combine this with `class: button`",
|
||||
},
|
||||
],
|
||||
|
||||
constr(
|
||||
|
|
@ -185,10 +184,10 @@ export class WebAndCommunicationSpecialVisualisations {
|
|||
download: tagSource.map((tags) => Utils.SubstituteKeys(download, tags)),
|
||||
ariaLabel: tagSource.map((tags) => Utils.SubstituteKeys(ariaLabel, tags)),
|
||||
newTab: new ImmutableStore(newTab),
|
||||
icon: tagSource.map((tags) => Utils.SubstituteKeys(icon, tags))
|
||||
icon: tagSource.map((tags) => Utils.SubstituteKeys(icon, tags)),
|
||||
}).setSpan()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue