forked from MapComplete/MapComplete
Merge branch 'feature/move-flox' into develop
This commit is contained in:
commit
43f73947c9
47 changed files with 2139 additions and 786 deletions
|
@ -16,7 +16,7 @@ export interface ChangeDescription {
|
|||
/**
|
||||
* The type of the change
|
||||
*/
|
||||
changeType: "answer" | "create" | "split" | "delete" | string
|
||||
changeType: "answer" | "create" | "split" | "delete" | "move" | string
|
||||
/**
|
||||
* THe motivation for the change, e.g. 'deleted because does not exist anymore'
|
||||
*/
|
||||
|
|
41
Logic/Osm/Actions/ChangeLocationAction.ts
Normal file
41
Logic/Osm/Actions/ChangeLocationAction.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import {ChangeDescription} from "./ChangeDescription";
|
||||
import OsmChangeAction from "./OsmChangeAction";
|
||||
import {Changes} from "../Changes";
|
||||
|
||||
export default class ChangeLocationAction extends OsmChangeAction {
|
||||
private readonly _id: number;
|
||||
private readonly _newLonLat: [number, number];
|
||||
private readonly _meta: { theme: string; reason: string };
|
||||
|
||||
constructor(id: string, newLonLat: [number, number], meta: {
|
||||
theme: string,
|
||||
reason: string
|
||||
}) {
|
||||
super();
|
||||
if (!id.startsWith("node/")) {
|
||||
throw "Invalid ID: only 'node/number' is accepted"
|
||||
}
|
||||
this._id = Number(id.substring("node/".length))
|
||||
this._newLonLat = newLonLat;
|
||||
this._meta = meta;
|
||||
}
|
||||
|
||||
protected async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
|
||||
const d: ChangeDescription = {
|
||||
changes: {
|
||||
lat: this._newLonLat[1],
|
||||
lon: this._newLonLat[0]
|
||||
},
|
||||
type: "node",
|
||||
id: this._id, meta: {
|
||||
changeType: "move",
|
||||
theme: this._meta.theme,
|
||||
specialMotivation: this._meta.reason
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [d]
|
||||
}
|
||||
}
|
|
@ -59,14 +59,13 @@ export abstract class OsmObject {
|
|||
|
||||
static async DownloadPropertiesOf(id: string): Promise<any> {
|
||||
const splitted = id.split("/");
|
||||
const type = splitted[0];
|
||||
const idN = Number(splitted[1]);
|
||||
if (idN < 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const url = `${OsmObject.backendURL}api/0.6/${id}`;
|
||||
const rawData = await Utils.downloadJson(url)
|
||||
const rawData = await Utils.downloadJsonCached(url, 1000)
|
||||
return rawData.elements[0].tags
|
||||
}
|
||||
|
||||
|
@ -80,7 +79,7 @@ export abstract class OsmObject {
|
|||
|
||||
const full = (id.startsWith("way")) ? "/full" : "";
|
||||
const url = `${OsmObject.backendURL}api/0.6/${id}${full}`;
|
||||
const rawData = await Utils.downloadJson(url)
|
||||
const rawData = await Utils.downloadJsonCached(url, 1000)
|
||||
// A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way)
|
||||
const parsed = OsmObject.ParseObjects(rawData.elements);
|
||||
// Lets fetch the object we need
|
||||
|
@ -105,7 +104,7 @@ export abstract class OsmObject {
|
|||
* Beware: their geometry will be incomplete!
|
||||
*/
|
||||
public static DownloadReferencingWays(id: string): Promise<OsmWay[]> {
|
||||
return Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${id}/ways`).then(
|
||||
return Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${id}/ways`, 60 * 1000).then(
|
||||
data => {
|
||||
return data.elements.map(wayInfo => {
|
||||
const way = new OsmWay(wayInfo.id)
|
||||
|
@ -121,7 +120,7 @@ export abstract class OsmObject {
|
|||
* Beware: their geometry will be incomplete!
|
||||
*/
|
||||
public static async DownloadReferencingRelations(id: string): Promise<OsmRelation[]> {
|
||||
const data = await Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${id}/relations`)
|
||||
const data = await Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${id}/relations`, 60 * 1000)
|
||||
return data.elements.map(wayInfo => {
|
||||
const rel = new OsmRelation(wayInfo.id)
|
||||
rel.LoadData(wayInfo)
|
||||
|
@ -139,7 +138,7 @@ export abstract class OsmObject {
|
|||
const idN = Number(splitted[1]);
|
||||
const src = new UIEventSource<OsmObject[]>([]);
|
||||
OsmObject.historyCache.set(id, src);
|
||||
Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${type}/${idN}/history`).then(data => {
|
||||
Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${type}/${idN}/history`, 10 * 60 * 1000).then(data => {
|
||||
const elements: any[] = data.elements;
|
||||
const osmObjects: OsmObject[] = []
|
||||
for (const element of elements) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import {TagRenderingConfigJson} from "./TagRenderingConfigJson";
|
|||
import FilterConfigJson from "./FilterConfigJson";
|
||||
import {DeleteConfigJson} from "./DeleteConfigJson";
|
||||
import UnitConfigJson from "./UnitConfigJson";
|
||||
import MoveConfigJson from "./MoveConfigJson";
|
||||
|
||||
/**
|
||||
* Configuration for a single layer
|
||||
|
@ -314,6 +315,18 @@ export interface LayerConfigJson {
|
|||
*/
|
||||
deletion?: boolean | DeleteConfigJson
|
||||
|
||||
/**
|
||||
* Indicates if a point can be moved and configures the modalities.
|
||||
*
|
||||
* A feature can be moved by MapComplete if:
|
||||
*
|
||||
* - It is a point
|
||||
* - The point is _not_ part of a way or a a relation.
|
||||
*
|
||||
* Off by default. Can be enabled by setting this flag or by configuring.
|
||||
*/
|
||||
allowMove?: boolean | MoveConfigJson
|
||||
|
||||
/**
|
||||
* IF set, a 'split this road' button is shown
|
||||
*/
|
||||
|
|
12
Models/ThemeConfig/Json/MoveConfigJson.ts
Normal file
12
Models/ThemeConfig/Json/MoveConfigJson.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
export default interface MoveConfigJson {
|
||||
/**
|
||||
* One default reason to move a point is to improve accuracy.
|
||||
* Set to false to disable this reason
|
||||
*/
|
||||
enableImproveAccuracy?: true | boolean
|
||||
/**
|
||||
* One default reason to move a point is because it has relocated
|
||||
* Set to false to disable this reason
|
||||
*/
|
||||
enableRelocation?: true | boolean
|
||||
}
|
|
@ -19,6 +19,7 @@ import {Unit} from "../Unit";
|
|||
import DeleteConfig from "./DeleteConfig";
|
||||
import Svg from "../../Svg";
|
||||
import Img from "../../UI/Base/Img";
|
||||
import MoveConfig from "./MoveConfig";
|
||||
|
||||
export default class LayerConfig {
|
||||
static WAYHANDLING_DEFAULT = 0;
|
||||
|
@ -49,6 +50,7 @@ export default class LayerConfig {
|
|||
wayHandling: number;
|
||||
public readonly units: Unit[];
|
||||
public readonly deletion: DeleteConfig | null;
|
||||
public readonly allowMove: MoveConfig | null
|
||||
public readonly allowSplit: boolean
|
||||
|
||||
presets: PresetConfig[];
|
||||
|
@ -67,7 +69,7 @@ export default class LayerConfig {
|
|||
this.id = json.id;
|
||||
this.allowSplit = json.allowSplit ?? false;
|
||||
this.name = Translations.T(json.name, context + ".name");
|
||||
this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`)))
|
||||
this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`)))
|
||||
|
||||
if (json.description !== undefined) {
|
||||
if (Object.keys(json.description).length === 0) {
|
||||
|
@ -138,11 +140,11 @@ export default class LayerConfig {
|
|||
const key = kv.substring(0, index);
|
||||
const code = kv.substring(index + 1);
|
||||
|
||||
try{
|
||||
|
||||
new Function("feat", "return " + code + ";");
|
||||
}catch(e){
|
||||
throw `Invalid function definition: code ${code} is invalid:${e} (at ${context})`
|
||||
try {
|
||||
|
||||
new Function("feat", "return " + code + ";");
|
||||
} catch (e) {
|
||||
throw `Invalid function definition: code ${code} is invalid:${e} (at ${context})`
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,8 +157,8 @@ export default class LayerConfig {
|
|||
this.minzoom = json.minzoom ?? 0;
|
||||
this.minzoomVisible = json.minzoomVisible ?? this.minzoom;
|
||||
this.wayHandling = json.wayHandling ?? 0;
|
||||
if(json.presets !== undefined && json.presets?.map === undefined){
|
||||
throw "Presets should be a list of items (at "+context+")"
|
||||
if (json.presets !== undefined && json.presets?.map === undefined) {
|
||||
throw "Presets should be a list of items (at " + context + ")"
|
||||
}
|
||||
this.presets = (json.presets ?? []).map((pr, i) => {
|
||||
|
||||
|
@ -291,21 +293,21 @@ export default class LayerConfig {
|
|||
}
|
||||
|
||||
this.tagRenderings = trs(json.tagRenderings, false);
|
||||
|
||||
const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? [];
|
||||
|
||||
if(missingIds.length > 0 && official){
|
||||
console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds)
|
||||
throw "Missing ids in tagrenderings"
|
||||
}
|
||||
|
||||
const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? [];
|
||||
|
||||
if (missingIds.length > 0 && official) {
|
||||
console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds)
|
||||
throw "Missing ids in tagrenderings"
|
||||
}
|
||||
|
||||
this.filters = (json.filter ?? []).map((option, i) => {
|
||||
return new FilterConfig(option, `${context}.filter-[${i}]`)
|
||||
});
|
||||
|
||||
if(json["filters"] !== undefined){
|
||||
throw "Error in "+context+": use 'filter' instead of 'filters'"
|
||||
}
|
||||
|
||||
if (json["filters"] !== undefined) {
|
||||
throw "Error in " + context + ": use 'filter' instead of 'filters'"
|
||||
}
|
||||
|
||||
const titleIcons = [];
|
||||
const defaultIcons = [
|
||||
|
@ -369,6 +371,16 @@ export default class LayerConfig {
|
|||
this.deletion = new DeleteConfig(json.deletion, `${context}.deletion`);
|
||||
}
|
||||
|
||||
this.allowMove = null
|
||||
if (json.allowMove === false) {
|
||||
this.allowMove = null;
|
||||
} else if (json.allowMove === true) {
|
||||
this.allowMove = new MoveConfig({}, context + ".allowMove")
|
||||
} else if (json.allowMove !== undefined && json.allowMove !== false) {
|
||||
this.allowMove = new MoveConfig(json.allowMove, context + ".allowMove")
|
||||
}
|
||||
|
||||
|
||||
if (json["showIf"] !== undefined) {
|
||||
throw (
|
||||
"Invalid key on layerconfig " +
|
||||
|
|
17
Models/ThemeConfig/MoveConfig.ts
Normal file
17
Models/ThemeConfig/MoveConfig.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import MoveConfigJson from "./Json/MoveConfigJson";
|
||||
|
||||
export default class MoveConfig {
|
||||
|
||||
public readonly enableImproveAccuracy: boolean
|
||||
public readonly enableRelocation: boolean
|
||||
|
||||
constructor(json: MoveConfigJson, context: string) {
|
||||
this.enableImproveAccuracy = json.enableImproveAccuracy ?? true
|
||||
this.enableRelocation = json.enableRelocation ?? true
|
||||
if (!(this.enableRelocation || this.enableImproveAccuracy)) {
|
||||
throw "At least one default move reason should be allowed (at " + context + ")"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -153,6 +153,7 @@ export default class SimpleAddUI extends Toggle {
|
|||
maxSnapDistance: preset.preciseInput.maxSnapDistance,
|
||||
bounds: mapBounds
|
||||
})
|
||||
preciseInput.installBounds(0.15, true)
|
||||
preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {InputElement} from "./InputElement";
|
||||
import Loc from "../../Models/Loc";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Minimap from "../Base/Minimap";
|
||||
import Minimap, {MinimapObj} from "../Base/Minimap";
|
||||
import BaseLayer from "../../Models/BaseLayer";
|
||||
import Combine from "../Base/Combine";
|
||||
import Svg from "../../Svg";
|
||||
|
@ -14,8 +14,10 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
|||
import {BBox} from "../../Logic/BBox";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
import ShowDataLayer from "../ShowDataLayer/ShowDataLayer";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Toggle from "./Toggle";
|
||||
|
||||
export default class LocationInput extends InputElement<Loc> {
|
||||
export default class LocationInput extends InputElement<Loc> implements MinimapObj {
|
||||
|
||||
private static readonly matchLayer = new LayerConfig(
|
||||
{
|
||||
|
@ -41,8 +43,14 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
private readonly _snappedPointTags: any;
|
||||
private readonly _bounds: UIEventSource<BBox>;
|
||||
public readonly _matching_layer: LayerConfig;
|
||||
private readonly map: BaseUIElement & MinimapObj;
|
||||
public readonly leafletMap: UIEventSource<any>
|
||||
|
||||
private readonly clickLocation: UIEventSource<Loc>;
|
||||
private readonly _minZoom: number;
|
||||
|
||||
constructor(options: {
|
||||
minZoom?: number,
|
||||
mapBackground?: UIEventSource<BaseLayer>,
|
||||
snapTo?: UIEventSource<{ feature: any }[]>,
|
||||
maxSnapDistance?: number,
|
||||
|
@ -57,6 +65,7 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
this._centerLocation = options.centerLocation;
|
||||
this._snappedPointTags = options.snappedPointTags
|
||||
this._bounds = options.bounds;
|
||||
this._minZoom = options.minZoom
|
||||
if (this._snapTo === undefined) {
|
||||
this._value = this._centerLocation;
|
||||
} else {
|
||||
|
@ -127,6 +136,19 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
}
|
||||
this.mapBackground = options.mapBackground ?? State.state?.backgroundLayer ?? new UIEventSource(AvailableBaseLayers.osmCarto)
|
||||
this.SetClass("block h-full")
|
||||
|
||||
|
||||
this.clickLocation = new UIEventSource<Loc>(undefined);
|
||||
this.map = Minimap.createMiniMap(
|
||||
{
|
||||
location: this._centerLocation,
|
||||
background: this.mapBackground,
|
||||
attribution: this.mapBackground !== State.state?.backgroundLayer,
|
||||
lastClickLocation: this.clickLocation,
|
||||
bounds: this._bounds
|
||||
}
|
||||
)
|
||||
this.leafletMap = this.map.leafletMap
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<Loc> {
|
||||
|
@ -136,31 +158,24 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
IsValid(t: Loc): boolean {
|
||||
return t !== undefined;
|
||||
}
|
||||
|
||||
|
||||
protected InnerConstructElement(): HTMLElement {
|
||||
try {
|
||||
const clickLocation = new UIEventSource<Loc>(undefined);
|
||||
const map = Minimap.createMiniMap(
|
||||
{
|
||||
location: this._centerLocation,
|
||||
background: this.mapBackground,
|
||||
attribution: this.mapBackground !== State.state?.backgroundLayer,
|
||||
lastClickLocation: clickLocation,
|
||||
bounds: this._bounds
|
||||
}
|
||||
)
|
||||
clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location))
|
||||
|
||||
map.installBounds(0.15, true);
|
||||
|
||||
if (this._snapTo !== undefined) {
|
||||
const self = this;
|
||||
const hasMoved = new UIEventSource(false)
|
||||
this.GetValue().addCallbackAndRunD(_ => {
|
||||
hasMoved.setData(true)
|
||||
return true;
|
||||
})
|
||||
this.clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location))
|
||||
if (this._snapTo !== undefined) {
|
||||
|
||||
// Show the lines to snap to
|
||||
new ShowDataMultiLayer({
|
||||
features: new StaticFeatureSource(this._snapTo, true),
|
||||
enablePopups: false,
|
||||
zoomToFeatures: false,
|
||||
leafletMap: map.leafletMap,
|
||||
leafletMap: this.map.leafletMap,
|
||||
layers: State.state.filteredLayers
|
||||
}
|
||||
)
|
||||
|
@ -175,22 +190,22 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
features: new StaticFeatureSource(matchPoint, true),
|
||||
enablePopups: false,
|
||||
zoomToFeatures: false,
|
||||
leafletMap: map.leafletMap,
|
||||
leafletMap: this.map.leafletMap,
|
||||
layerToShow: this._matching_layer
|
||||
})
|
||||
|
||||
}
|
||||
this.mapBackground.map(layer => {
|
||||
const leaflet = map.leafletMap.data
|
||||
const leaflet = this.map.leafletMap.data
|
||||
if (leaflet === undefined || layer === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
leaflet.setMaxZoom(layer.max_zoom)
|
||||
leaflet.setMinZoom(layer.max_zoom - 2)
|
||||
leaflet.setMinZoom(self._minZoom ?? layer.max_zoom - 2)
|
||||
leaflet.setZoom(layer.max_zoom - 1)
|
||||
|
||||
}, [map.leafletMap])
|
||||
}, [this.map.leafletMap])
|
||||
|
||||
const animatedHand = Svg.hand_ui()
|
||||
.SetStyle("width: 2rem; height: unset;")
|
||||
|
@ -204,12 +219,12 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
]).SetClass("block w-0 h-0 z-10 relative")
|
||||
.SetStyle("background: rgba(255, 128, 128, 0.21); left: 50%; top: 50%; opacity: 0.5"),
|
||||
|
||||
new Combine([
|
||||
animatedHand])
|
||||
new Toggle(undefined,
|
||||
animatedHand, hasMoved)
|
||||
.SetClass("block w-0 h-0 z-10 relative")
|
||||
.SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"),
|
||||
|
||||
map
|
||||
this.map
|
||||
.SetClass("z-0 relative block w-full h-full bg-gray-100")
|
||||
|
||||
]).ConstructElement();
|
||||
|
@ -219,4 +234,9 @@ export default class LocationInput extends InputElement<Loc> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
installBounds(factor: number | BBox, showRange?: boolean): void {
|
||||
this.map.installBounds(factor, showRange)
|
||||
}
|
||||
|
||||
}
|
|
@ -93,12 +93,12 @@ export default class DeleteWizard extends Toggle {
|
|||
* The button which is shown first. Opening it will trigger the check for deletions
|
||||
*/
|
||||
const deleteButton = new SubtleButton(
|
||||
Svg.delete_icon_ui().SetStyle("width: 2rem; height: 2rem;"), t.delete.Clone()).onClick(
|
||||
Svg.delete_icon_ui().SetStyle("width: auto; height: 1.5rem;"), t.delete.Clone()).onClick(
|
||||
() => {
|
||||
deleteAbility.CheckDeleteability(true)
|
||||
confirm.setData(true);
|
||||
}
|
||||
).SetClass("w-1/2 float-right");
|
||||
)
|
||||
|
||||
const isShown = new UIEventSource<boolean>(id.indexOf("-") < 0)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
|||
import {Translation} from "../i18n/Translation";
|
||||
import {Utils} from "../../Utils";
|
||||
import {SubstitutedTranslation} from "../SubstitutedTranslation";
|
||||
import MoveWizard from "./MoveWizard";
|
||||
|
||||
export default class FeatureInfoBox extends ScrollableFullScreen {
|
||||
|
||||
|
@ -72,6 +73,19 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
editElements.push(questionBox);
|
||||
}
|
||||
|
||||
if(layerConfig.allowMove) {
|
||||
editElements.push(
|
||||
new VariableUiElement(tags.map(tags => tags.id).map(id => {
|
||||
const feature = State.state.allElements.ContainingFeatures.get(id)
|
||||
return new MoveWizard(
|
||||
feature,
|
||||
State.state,
|
||||
layerConfig.allowMove
|
||||
);
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (layerConfig.deletion) {
|
||||
editElements.push(
|
||||
|
|
221
UI/Popup/MoveWizard.ts
Normal file
221
UI/Popup/MoveWizard.ts
Normal file
|
@ -0,0 +1,221 @@
|
|||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
import Combine from "../Base/Combine";
|
||||
import Svg from "../../Svg";
|
||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||
import Toggle from "../Input/Toggle";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Translations from "../i18n/Translations";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import {Translation} from "../i18n/Translation";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import LocationInput from "../Input/LocationInput";
|
||||
import Loc from "../../Models/Loc";
|
||||
import {GeoOperations} from "../../Logic/GeoOperations";
|
||||
import {OsmObject} from "../../Logic/Osm/OsmObject";
|
||||
import {Changes} from "../../Logic/Osm/Changes";
|
||||
import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import MoveConfig from "../../Models/ThemeConfig/MoveConfig";
|
||||
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
|
||||
import {ElementStorage} from "../../Logic/ElementStorage";
|
||||
import Img from "../Base/Img";
|
||||
|
||||
interface MoveReason {
|
||||
text: Translation | string,
|
||||
invitingText: Translation | string,
|
||||
icon: BaseUIElement,
|
||||
changesetCommentValue: string,
|
||||
lockBounds: true | boolean,
|
||||
background: undefined | "map" | "photo" | string | string[],
|
||||
startZoom: number,
|
||||
minZoom: number
|
||||
}
|
||||
|
||||
export default class MoveWizard extends Toggle {
|
||||
/**
|
||||
* The UI-element which helps moving a point
|
||||
*/
|
||||
constructor(
|
||||
featureToMove: any,
|
||||
state: {
|
||||
osmConnection: OsmConnection,
|
||||
featureSwitchUserbadge: UIEventSource<boolean>,
|
||||
changes: Changes,
|
||||
layoutToUse: LayoutConfig,
|
||||
allElements: ElementStorage
|
||||
}, options : MoveConfig) {
|
||||
|
||||
const t = Translations.t.move
|
||||
const loginButton = new Toggle(
|
||||
t.loginToMove.Clone().SetClass("btn").onClick(() => state.osmConnection.AttemptLogin()),
|
||||
undefined,
|
||||
state.featureSwitchUserbadge
|
||||
)
|
||||
|
||||
const reasons: MoveReason[] = []
|
||||
if (options.enableRelocation) {
|
||||
reasons.push({
|
||||
text: t.reasons.reasonRelocation.Clone(),
|
||||
invitingText: t.inviteToMove.reasonRelocation.Clone(),
|
||||
icon: Svg.relocation_svg(),
|
||||
changesetCommentValue: "relocated",
|
||||
lockBounds: false,
|
||||
background: undefined,
|
||||
startZoom: 12,
|
||||
minZoom: 6
|
||||
})
|
||||
}
|
||||
if(options.enableImproveAccuracy){
|
||||
reasons.push({
|
||||
text: t.reasons.reasonInaccurate.Clone(),
|
||||
invitingText: t.inviteToMove.reasonInaccurate,
|
||||
icon: Svg.crosshair_svg(),
|
||||
changesetCommentValue: "improve_accuracy",
|
||||
lockBounds: true,
|
||||
background: "photo",
|
||||
startZoom: 17,
|
||||
minZoom: 16
|
||||
})
|
||||
}
|
||||
|
||||
const currentStep = new UIEventSource<"start" | "reason" | "pick_location" | "moved">("start")
|
||||
const moveReason = new UIEventSource<MoveReason>(undefined)
|
||||
let moveButton : BaseUIElement;
|
||||
if(reasons.length === 1){
|
||||
const reason = reasons[0]
|
||||
moveReason.setData(reason)
|
||||
moveButton = new SubtleButton(
|
||||
reason.icon.SetStyle("height: 1.5rem; width: auto;"),
|
||||
Translations.WT(reason.invitingText).Clone()
|
||||
).onClick(() => {
|
||||
currentStep.setData("pick_location")
|
||||
})
|
||||
}else{
|
||||
moveButton = new SubtleButton(
|
||||
Svg.move_ui().SetStyle("height: 1.5rem; width: auto"),
|
||||
t.inviteToMove.generic.Clone()
|
||||
).onClick(() => {
|
||||
currentStep.setData("reason")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const moveAgainButton = new SubtleButton(
|
||||
Svg.move_ui(),
|
||||
t.inviteToMoveAgain.Clone()
|
||||
).onClick(() => {
|
||||
currentStep.setData("reason")
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
const selectReason = new Combine(reasons.map(r => new SubtleButton(r.icon, r.text).onClick(() => {
|
||||
moveReason.setData(r)
|
||||
currentStep.setData("pick_location")
|
||||
})))
|
||||
|
||||
const cancelButton = new SubtleButton(Svg.close_svg(), t.cancel).onClick(() => currentStep.setData("start"))
|
||||
|
||||
|
||||
const [lon, lat] = GeoOperations.centerpointCoordinates(featureToMove)
|
||||
const locationInput = moveReason.map(reason => {
|
||||
if (reason === undefined) {
|
||||
return undefined
|
||||
}
|
||||
const loc = new UIEventSource<Loc>({
|
||||
lon: lon,
|
||||
lat: lat,
|
||||
zoom: reason?.startZoom ?? 16
|
||||
})
|
||||
|
||||
|
||||
const locationInput = new LocationInput({
|
||||
minZoom: reason.minZoom,
|
||||
centerLocation: loc,
|
||||
mapBackground: AvailableBaseLayers.SelectBestLayerAccordingTo(loc, new UIEventSource(reason.background))
|
||||
})
|
||||
|
||||
if (reason.lockBounds) {
|
||||
locationInput.installBounds(0.05, true)
|
||||
}
|
||||
|
||||
locationInput.SetStyle("height: 17.5rem")
|
||||
|
||||
const confirmMove = new SubtleButton(Svg.move_confirm_svg(), t.confirmMove)
|
||||
confirmMove.onClick(() => {
|
||||
const loc = locationInput.GetValue().data
|
||||
state.changes.applyAction(new ChangeLocationAction(featureToMove.properties.id, [loc.lon, loc.lat], {
|
||||
reason: Translations.WT(reason.text).textFor("en"),
|
||||
theme: state.layoutToUse.id
|
||||
}))
|
||||
featureToMove.properties._lat = loc.lat
|
||||
featureToMove.properties._lon = loc.lon
|
||||
state.allElements.getEventSourceById(id).ping()
|
||||
currentStep.setData("moved")
|
||||
})
|
||||
const zoomInFurhter = t.zoomInFurther.Clone().SetClass("alert block m-6")
|
||||
return new Combine([
|
||||
locationInput,
|
||||
new Toggle(confirmMove, zoomInFurhter, locationInput.GetValue().map(l => l.zoom >= 19))
|
||||
]).SetClass("flex flex-col")
|
||||
});
|
||||
|
||||
const dialogClasses = "p-2 md:p-4 m-2 border border-gray-400 rounded-xl flex flex-col"
|
||||
|
||||
const moveFlow = new Toggle(
|
||||
new VariableUiElement(currentStep.map(currentStep => {
|
||||
switch (currentStep) {
|
||||
case "start":
|
||||
return moveButton;
|
||||
case "reason":
|
||||
return new Combine([t.whyMove.Clone().SetClass("text-lg font-bold"), selectReason, cancelButton]).SetClass(dialogClasses);
|
||||
case "pick_location":
|
||||
return new Combine([t.moveTitle.Clone().SetClass("text-lg font-bold"), new VariableUiElement(locationInput), cancelButton]).SetClass(dialogClasses)
|
||||
case "moved":
|
||||
return new Combine([t.pointIsMoved.Clone().SetClass("thanks"), moveAgainButton]).SetClass("flex flex-col");
|
||||
|
||||
}
|
||||
|
||||
|
||||
})),
|
||||
loginButton,
|
||||
state.osmConnection.isLoggedIn
|
||||
)
|
||||
let id = featureToMove.properties.id
|
||||
const backend = state.osmConnection._oauth_config.url
|
||||
if (id.startsWith(backend)) {
|
||||
id = id.substring(backend.length)
|
||||
}
|
||||
|
||||
const moveDisallowedReason = new UIEventSource<BaseUIElement>(undefined)
|
||||
if (id.startsWith("way")) {
|
||||
moveDisallowedReason.setData(t.isWay.Clone())
|
||||
} else if (id.startsWith("relation")) {
|
||||
moveDisallowedReason.setData(t.isRelation.Clone())
|
||||
} else {
|
||||
|
||||
OsmObject.DownloadReferencingWays(id).then(referencing => {
|
||||
if (referencing.length > 0) {
|
||||
console.log("Got a referencing way, move not allowed")
|
||||
moveDisallowedReason.setData(t.partOfAWay.Clone())
|
||||
}
|
||||
})
|
||||
OsmObject.DownloadReferencingRelations(id).then(partOf => {
|
||||
if(partOf.length > 0){
|
||||
moveDisallowedReason.setData(t.partOfRelation.Clone())
|
||||
}
|
||||
})
|
||||
}
|
||||
super(
|
||||
moveFlow,
|
||||
new Combine([
|
||||
Svg.move_not_allowed_svg().SetStyle("height: 2rem"),
|
||||
new Combine([t.cannotBeMoved.Clone(),
|
||||
new VariableUiElement(moveDisallowedReason).SetClass("subtle")
|
||||
]).SetClass("flex flex-col")
|
||||
]).SetClass("flex"),
|
||||
moveDisallowedReason.map(r => r === undefined)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -120,7 +120,7 @@ export default class SplitRoadWizard extends Toggle {
|
|||
}))
|
||||
|
||||
// Toggle between splitmap
|
||||
const splitButton = new SubtleButton(Svg.scissors_ui(), t.inviteToSplit.Clone().SetClass("text-lg font-bold"));
|
||||
const splitButton = new SubtleButton(Svg.scissors_ui().SetStyle("height: 1.5rem; width: auto"), t.inviteToSplit.Clone().SetClass("text-lg font-bold"));
|
||||
splitButton.onClick(
|
||||
() => {
|
||||
splitClicked.setData(true)
|
||||
|
|
13
Utils.ts
13
Utils.ts
|
@ -320,6 +320,19 @@ export class Utils {
|
|||
)
|
||||
}
|
||||
|
||||
private static _download_cache = new Map<string, {promise: Promise<any>, timestamp: number}>()
|
||||
public static async downloadJsonCached(url: string, maxCacheTimeMs: number, headers?: any): Promise<any> {
|
||||
const cached = Utils._download_cache.get(url)
|
||||
if(cached !== undefined){
|
||||
if((new Date().getTime() - cached.timestamp) <= maxCacheTimeMs){
|
||||
return cached.promise
|
||||
}
|
||||
}
|
||||
const promise = Utils.downloadJson(url, headers)
|
||||
Utils._download_cache.set(url, {promise, timestamp: new Date().getTime()})
|
||||
return await promise
|
||||
}
|
||||
|
||||
public static async downloadJson(url: string, headers?: any): Promise<any> {
|
||||
const injected = Utils.injectedDownloads[url]
|
||||
if (injected !== undefined) {
|
||||
|
|
398
assets/layers/artwork/artwork.json
Normal file
398
assets/layers/artwork/artwork.json
Normal file
|
@ -0,0 +1,398 @@
|
|||
{
|
||||
"id": "artwork",
|
||||
"name": {
|
||||
"en": "Artworks",
|
||||
"nl": "Kunstwerken",
|
||||
"fr": "Œuvres d'art",
|
||||
"de": "Kunstwerke",
|
||||
"id": "Karya seni",
|
||||
"it": "Opere d’arte",
|
||||
"ru": "Произведения искусства",
|
||||
"es": "Obras de arte",
|
||||
"ja": "美術品",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
},
|
||||
"source": {
|
||||
"osmTags": "tourism=artwork"
|
||||
},
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Artwork",
|
||||
"nl": "Kunstwerk",
|
||||
"fr": "Œuvre d'art",
|
||||
"de": "Kunstwerk",
|
||||
"id": "Karya seni",
|
||||
"it": "Opera d’arte",
|
||||
"ru": "Художественная работа",
|
||||
"es": "Obra de arte",
|
||||
"ja": "アートワーク",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "name~*",
|
||||
"then": {
|
||||
"en": "Artwork <i>{name}</i>",
|
||||
"nl": "Kunstwerk <i>{name}</i>",
|
||||
"fr": "Œuvre d'art <i>{name}</i>",
|
||||
"de": "Kunstwerk <i>{name}</i>",
|
||||
"id": "Karya seni <i>{name}</i>",
|
||||
"it": "Opera <i>{name}</i>",
|
||||
"ru": "Художественная работа <i>{name}</i>",
|
||||
"es": "Obra de arte <i>{nombre}</i>",
|
||||
"ja": "アートワーク <i>{name}</i>",
|
||||
"zh_Hant": "藝術品<i>{name}</i>"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"icon": {
|
||||
"render": "./assets/themes/artwork/artwork.svg"
|
||||
},
|
||||
"color": {
|
||||
"render": "#0000ff"
|
||||
},
|
||||
"width": {
|
||||
"render": "10"
|
||||
},
|
||||
"description": {
|
||||
"en": "Diverse pieces of artwork",
|
||||
"nl": "Verschillende soorten kunstwerken",
|
||||
"fr": "Diverses œuvres d'art",
|
||||
"de": "Verschiedene Kunstwerke",
|
||||
"it": "Diverse opere d’arte",
|
||||
"ru": "Разнообразные произведения искусства",
|
||||
"es": "Diversas piezas de obras de arte",
|
||||
"ja": "多様な作品",
|
||||
"zh_Hant": "不同類型的藝術品"
|
||||
},
|
||||
"minzoom": 12,
|
||||
"wayHandling": 2,
|
||||
"presets": [
|
||||
{
|
||||
"tags": [
|
||||
"tourism=artwork"
|
||||
],
|
||||
"title": {
|
||||
"en": "Artwork",
|
||||
"nl": "Kunstwerk",
|
||||
"fr": "Œuvre d'art",
|
||||
"de": "Kunstwerk",
|
||||
"it": "Opera d’arte",
|
||||
"ru": "Художественная работа",
|
||||
"es": "Obra de arte",
|
||||
"ja": "アートワーク",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"render": {
|
||||
"en": "This is a {artwork_type}",
|
||||
"nl": "Dit is een {artwork_type}",
|
||||
"fr": "Type d'œuvre : {artwork_type}",
|
||||
"de": "Dies ist ein {artwork_type}",
|
||||
"it": "Si tratta di un {artwork_type}",
|
||||
"ru": "Это {artwork_type}",
|
||||
"es": "Esta es un {artwork_type}",
|
||||
"ja": "これは{artwork_type}です",
|
||||
"zh_Hant": "這是 {artwork_type}",
|
||||
"nb_NO": "Dette er et kunstverk av typen {artwork_type}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the type of this artwork?",
|
||||
"nl": "Wat voor soort kunstwerk is dit?",
|
||||
"fr": "Quel est le type de cette œuvre d'art?",
|
||||
"de": "Was ist die Art dieses Kunstwerks?",
|
||||
"it": "Che tipo di opera d’arte è questo?",
|
||||
"ru": "К какому типу относится эта работа?",
|
||||
"es": "Cuál es el tipo de esta obra de arte?",
|
||||
"ja": "この作品の種類は何ですか?",
|
||||
"zh_Hant": "這是什麼類型的藝術品?",
|
||||
"nb_NO": "Hvilken type kunstverk er dette?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "artwork_type",
|
||||
"addExtraTags": [
|
||||
"fixme=Artowrk type was added with the freeform, might need another check"
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "artwork_type=architecture",
|
||||
"then": {
|
||||
"en": "Architecture",
|
||||
"nl": "Architectuur",
|
||||
"fr": "Architecture",
|
||||
"de": "Architektur",
|
||||
"it": "Architettura",
|
||||
"ru": "Архитектура",
|
||||
"ja": "建物",
|
||||
"zh_Hant": "建築物",
|
||||
"nb_NO": "Arkitektur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=mural",
|
||||
"then": {
|
||||
"en": "Mural",
|
||||
"nl": "Muurschildering",
|
||||
"fr": "Peinture murale",
|
||||
"de": "Wandbild",
|
||||
"it": "Murale",
|
||||
"ru": "Фреска",
|
||||
"ja": "壁画",
|
||||
"zh_Hant": "壁畫",
|
||||
"nb_NO": "Veggmaleri"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=painting",
|
||||
"then": {
|
||||
"en": "Painting",
|
||||
"nl": "Schilderij",
|
||||
"fr": "Peinture",
|
||||
"de": "Malerei",
|
||||
"it": "Dipinto",
|
||||
"ru": "Живопись",
|
||||
"ja": "絵画",
|
||||
"zh_Hant": "繪畫",
|
||||
"nb_NO": "Maleri"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=sculpture",
|
||||
"then": {
|
||||
"en": "Sculpture",
|
||||
"nl": "Beeldhouwwerk",
|
||||
"fr": "Sculpture",
|
||||
"de": "Skulptur",
|
||||
"it": "Scultura",
|
||||
"ru": "Скульптура",
|
||||
"ja": "彫刻",
|
||||
"zh_Hant": "雕塑",
|
||||
"nb_NO": "Skulptur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=statue",
|
||||
"then": {
|
||||
"en": "Statue",
|
||||
"nl": "Standbeeld",
|
||||
"fr": "Statue",
|
||||
"de": "Statue",
|
||||
"it": "Statua",
|
||||
"ru": "Статуя",
|
||||
"ja": "彫像",
|
||||
"zh_Hant": "雕像",
|
||||
"nb_NO": "Statue"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=bust",
|
||||
"then": {
|
||||
"en": "Bust",
|
||||
"nl": "Buste",
|
||||
"fr": "Buste",
|
||||
"de": "Büste",
|
||||
"it": "Busto",
|
||||
"ru": "Бюст",
|
||||
"ja": "胸像",
|
||||
"zh_Hant": "半身像",
|
||||
"nb_NO": "Byste"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=stone",
|
||||
"then": {
|
||||
"en": "Stone",
|
||||
"nl": "Steen",
|
||||
"fr": "Rocher",
|
||||
"de": "Stein",
|
||||
"it": "Masso",
|
||||
"ru": "Камень",
|
||||
"ja": "石",
|
||||
"zh_Hant": "石頭",
|
||||
"nb_NO": "Stein"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=installation",
|
||||
"then": {
|
||||
"en": "Installation",
|
||||
"nl": "Installatie",
|
||||
"fr": "Installation",
|
||||
"de": "Installation",
|
||||
"it": "Istallazione",
|
||||
"ru": "Инсталляция",
|
||||
"ja": "インスタレーション",
|
||||
"zh_Hant": "安裝",
|
||||
"nb_NO": "Installasjon"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=graffiti",
|
||||
"then": {
|
||||
"en": "Graffiti",
|
||||
"nl": "Graffiti",
|
||||
"fr": "Graffiti",
|
||||
"de": "Graffiti",
|
||||
"it": "Graffiti",
|
||||
"ru": "Граффити",
|
||||
"ja": "落書き",
|
||||
"zh_Hant": "塗鴨",
|
||||
"nb_NO": "Graffiti"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=relief",
|
||||
"then": {
|
||||
"en": "Relief",
|
||||
"nl": "Reliëf",
|
||||
"fr": "Relief",
|
||||
"de": "Relief",
|
||||
"it": "Rilievo",
|
||||
"ru": "Рельеф",
|
||||
"ja": "レリーフ",
|
||||
"zh_Hant": "寬慰",
|
||||
"nb_NO": "Relieff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=azulejo",
|
||||
"then": {
|
||||
"en": "Azulejo (Spanish decorative tilework)",
|
||||
"nl": "Azulejo (Spaanse siertegels)",
|
||||
"fr": "Azulejo (faïence latine)",
|
||||
"de": "Azulejo (spanische dekorative Fliesenarbeit)",
|
||||
"it": "Azulejo (ornamento decorativo piastrellato spagnolo)",
|
||||
"ru": "Азуле́жу (испанская роспись глазурованной керамической плитки)",
|
||||
"ja": "Azulejo (スペインの装飾タイル)",
|
||||
"zh_Hant": "Azulejo (西班牙雕塑作品名稱)",
|
||||
"nb_NO": "Azulejo (Spansk dekorativt flisverk)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=tilework",
|
||||
"then": {
|
||||
"en": "Tilework",
|
||||
"nl": "Tegelwerk",
|
||||
"fr": "Carrelage",
|
||||
"de": "Fliesenarbeit",
|
||||
"it": "Mosaico di piastrelle",
|
||||
"ru": "Плитка (мозаика)",
|
||||
"ja": "タイルワーク",
|
||||
"zh_Hant": "瓷磚",
|
||||
"nb_NO": "Flisarbeid"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "artwork-artwork_type"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Which artist created this?",
|
||||
"nl": "Welke kunstenaar creëerde dit kunstwerk?",
|
||||
"fr": "Quel artiste a créé cette œuvre ?",
|
||||
"de": "Welcher Künstler hat das geschaffen?",
|
||||
"it": "Quale artista ha creato quest’opera?",
|
||||
"ru": "Какой художник создал это?",
|
||||
"ja": "どのアーティストが作ったんですか?",
|
||||
"zh_Hant": "創造這個的藝術家是誰?",
|
||||
"nb_NO": "Hvilken artist lagde dette?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Created by {artist_name}",
|
||||
"nl": "Gecreëerd door {artist_name}",
|
||||
"fr": "Créé par {artist_name}",
|
||||
"de": "Erstellt von {artist_name}",
|
||||
"it": "Creato da {artist_name}",
|
||||
"ru": "Создано {artist_name}",
|
||||
"ja": "作成者:{artist_name}",
|
||||
"zh_Hant": "{artist_name} 創作",
|
||||
"nb_NO": "Laget av {artist_name}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "artist_name"
|
||||
},
|
||||
"id": "artwork-artist_name"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Is there a website with more information about this artwork?",
|
||||
"nl": "Is er een website met meer informatie over dit kunstwerk?",
|
||||
"fr": "Existe-t-il un site web où trouver plus d'informations sur cette œuvre d'art ?",
|
||||
"de": "Gibt es eine Website mit weiteren Informationen über dieses Kunstwerk?",
|
||||
"it": "Esiste un sito web con maggiori informazioni su quest’opera?",
|
||||
"ru": "Есть ли сайт с более подробной информацией об этой работе?",
|
||||
"ja": "この作品についての詳しい情報はどのウェブサイトにありますか?",
|
||||
"zh_Hant": "在那個網站能夠找到更多藝術品的資訊?",
|
||||
"nb_NO": "Finnes det en nettside med mer info om dette kunstverket?"
|
||||
},
|
||||
"render": {
|
||||
"en": "More information on <a href='{website}' target='_blank'>this website</a>",
|
||||
"nl": "Meer informatie op <a href='{website}' target='_blank'>deze website</a>",
|
||||
"fr": "Plus d'info <a href='{website}' target='_blank'>sûr ce site web</a>",
|
||||
"de": "Weitere Informationen auf <a href='{website}' target='_blank'>dieser Webseite</a>",
|
||||
"id": "Info lanjut tersedia di <a href='{website}' target='_blank'>laman web</a> ini.",
|
||||
"it": "Ulteriori informazioni su <a href='{website}' target='_blank'>questo sito web</a>",
|
||||
"ru": "Больше информации на <a href='{website}' target='_blank'>этом сайте</a>",
|
||||
"ja": "<a href='{website}' target='_blank'>Webサイト</a>に詳細情報がある",
|
||||
"zh_Hant": "<a href='{website}' target='_blank'>這個網站</a>有更多資訊",
|
||||
"nb_NO": "Mer info er å finne på <a href='{website}' target='_blank'>denne nettsiden</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
"type": "url"
|
||||
},
|
||||
"id": "artwork-website"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Which Wikidata-entry corresponds with <b>this artwork</b>?",
|
||||
"nl": "Welk Wikidata-item beschrijft <b>dit kunstwerk</b>?",
|
||||
"fr": "Quelle entrée Wikidata correspond à <b>cette œuvre d'art</b> ?",
|
||||
"de": "Welcher Wikidata-Eintrag entspricht <b>diesem Kunstwerk</b>?",
|
||||
"it": "Quale elemento Wikidata corrisponde a <b>quest’opera d’arte</b>?",
|
||||
"ru": "Какая запись в Wikidata соответсвует <b>этой работе</b>?",
|
||||
"ja": "<b>このアートワーク</b>に関するWikidataのエントリーはどれですか?",
|
||||
"zh_Hant": "<b>這個藝術品</b>有那個對應的 Wikidata 項目?",
|
||||
"nb_NO": "Hvilken Wikipedia-oppføring samsvarer med <b>dette kunstverket</b>?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Corresponds with <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"nl": "Komt overeen met <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"fr": "Correspond à <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"de": "Entspricht <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"it": "Corrisponde a <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"ru": "Запись об этой работе в wikidata: <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"ja": "<a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>に関連する",
|
||||
"zh_Hant": "與 <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>對應",
|
||||
"nb_NO": "Samsvarer med <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "wikidata",
|
||||
"type": "wikidata"
|
||||
},
|
||||
"id": "artwork-wikidata"
|
||||
}
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"razed:tourism=artwork",
|
||||
"tourism="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 5
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -600,5 +600,18 @@
|
|||
"preferredBackground": "photo"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity=bench",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -255,5 +255,18 @@
|
|||
],
|
||||
"multiAnswer": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -145,5 +145,18 @@
|
|||
"roaming": false,
|
||||
"id": "bike_cleaning-charge"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -508,5 +508,18 @@
|
|||
},
|
||||
"id": "Cargo bike capacity?"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -731,5 +731,18 @@
|
|||
"service:bicycle:pump=no"
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -100,5 +100,18 @@
|
|||
"amenity=binoculars"
|
||||
]
|
||||
}
|
||||
},
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -296,5 +296,17 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
}
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -181,5 +181,11 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": ["amenity=","disused:amenity:={amenity}"]
|
||||
}
|
||||
},
|
||||
"allowMove": true
|
||||
}
|
|
@ -3655,5 +3655,18 @@
|
|||
],
|
||||
"eraseInvalidValues": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -539,5 +539,18 @@
|
|||
},
|
||||
"id": "defibrillator-fixme"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:emergency:=defibrillator}",
|
||||
"emergency="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 5
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -166,5 +166,18 @@
|
|||
},
|
||||
"condition": "_closest_other_drinking_water_id~*"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -624,5 +624,11 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": ["amenity=","disused:amenity:={amenity}"]
|
||||
}
|
||||
},
|
||||
"allowMove": true
|
||||
}
|
|
@ -187,5 +187,18 @@
|
|||
},
|
||||
"id": "ghost_bike-start_date"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"razed:memorial:=ghost_bike",
|
||||
"memorial="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 50
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -53,5 +53,20 @@
|
|||
"ru": "Информационный щит"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:tourism:=information",
|
||||
"tourism=" ,
|
||||
"razed:information=board",
|
||||
"information="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -227,5 +227,18 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"wayHandling": 2
|
||||
"wayHandling": 2,
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"razed:tourism:=information",
|
||||
"tourism="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -180,5 +180,9 @@
|
|||
],
|
||||
"eraseInvalidValues": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -81,5 +81,18 @@
|
|||
"nl": "Voeg hier een parking voor auto's toe"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -101,5 +101,18 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"wayHandling": 1
|
||||
"wayHandling": 1,
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
323
assets/layers/shops/shops.json
Normal file
323
assets/layers/shops/shops.json
Normal file
|
@ -0,0 +1,323 @@
|
|||
{
|
||||
"id": "shops",
|
||||
"name": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
"osmTags": {
|
||||
"and": [
|
||||
"shop~*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"name~*"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "{name}",
|
||||
"fr": "{name}",
|
||||
"ru": "{name}",
|
||||
"ja": "{name}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop!~yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "{shop}",
|
||||
"fr": "{shop}",
|
||||
"ru": "{shop}",
|
||||
"ja": "{shop}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"en": "A shop",
|
||||
"fr": "Un magasin",
|
||||
"ja": "ショップ",
|
||||
"nl": "Een winkel",
|
||||
"ru": "Магазин"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"question": {
|
||||
"en": "What is the name of this shop?",
|
||||
"fr": "Qu'est-ce que le nom de ce magasin?",
|
||||
"ru": "Как называется этот магазин?",
|
||||
"ja": "このお店の名前は何ですか?",
|
||||
"nl": "Wat is de naam van deze winkel?"
|
||||
},
|
||||
"render": "This shop is called <i>{name}</i>",
|
||||
"freeform": {
|
||||
"key": "name"
|
||||
},
|
||||
"id": "shops-name"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "This shop sells {shop}",
|
||||
"fr": "Ce magasin vends {shop}",
|
||||
"ja": "こちらのお店では{shop}を販売しております"
|
||||
},
|
||||
"question": {
|
||||
"en": "What does this shop sell?",
|
||||
"fr": "Que vends ce magasin ?",
|
||||
"ja": "このお店では何を売っていますか?",
|
||||
"ru": "Что продаётся в этом магазине?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "shop"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=convenience"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Convenience store",
|
||||
"fr": "Épicerie/superette",
|
||||
"ja": "コンビニエンスストア"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=supermarket"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Supermarket",
|
||||
"fr": "Supermarché",
|
||||
"ru": "Супермаркет",
|
||||
"ja": "スーパーマーケット",
|
||||
"nl": "Supermarkt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=clothes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Clothing store",
|
||||
"fr": "Magasin de vêtements",
|
||||
"ru": "Магазин одежды",
|
||||
"ja": "衣料品店"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=hairdresser"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Hairdresser",
|
||||
"fr": "Coiffeur",
|
||||
"ru": "Парикмахерская",
|
||||
"ja": "理容師",
|
||||
"nl": "Kapper"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=bakery"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Bakery",
|
||||
"fr": "Boulangerie",
|
||||
"ja": "ベーカリー",
|
||||
"nl": "Bakkerij"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=car_repair"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Car repair (garage)",
|
||||
"fr": "Garagiste",
|
||||
"ja": "自動車修理(ガレージ)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=car"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Car dealer",
|
||||
"fr": "Concessionnaire",
|
||||
"ru": "Автосалон",
|
||||
"ja": "自動車ディーラー"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "shops-shop"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"fr": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ca": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"id": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ru": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ja": "<a href='tel:{phone}'>{phone}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the phone number?",
|
||||
"fr": "Quel est le numéro de téléphone ?",
|
||||
"ja": "電話番号は何番ですか?",
|
||||
"nl": "Wat is het telefoonnummer?",
|
||||
"ru": "Какой телефон?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "phone",
|
||||
"type": "phone"
|
||||
},
|
||||
"id": "shops-phone"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='{website}'>{website}</a>",
|
||||
"fr": "<a href='{website}'>{website}</a>",
|
||||
"ca": "<a href='{website}'>{website}</a>",
|
||||
"id": "<a href='{website}'>{website}</a>",
|
||||
"ru": "<a href='{website}'>{website}</a>",
|
||||
"ja": "<a href='{website}'>{website}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the website of this shop?",
|
||||
"fr": "Quel est le site internet de ce magasin ?",
|
||||
"ja": "このお店のホームページは何ですか?",
|
||||
"nl": "Wat is de website van deze winkel?",
|
||||
"ru": "Какой веб-сайт у этого магазина?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
"type": "url"
|
||||
},
|
||||
"id": "shops-website"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='mailto:{email}'>{email}</a>",
|
||||
"fr": "<a href='mailto:{email}'>{email}</a>",
|
||||
"id": "<a href='mailto:{email}'>{email}</a>",
|
||||
"ru": "<a href='mailto:{email}'>{email}</a>",
|
||||
"ja": "<a href='mailto:{email}'>{email}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the email address of this shop?",
|
||||
"fr": "Quelle est l'adresse électronique de ce magasin ?",
|
||||
"ja": "このお店のメールアドレスは何ですか?",
|
||||
"ru": "Каков адрес электронной почты этого магазина?",
|
||||
"nl": "Wat is het e-mailadres van deze winkel?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "email",
|
||||
"type": "email"
|
||||
},
|
||||
"id": "shops-email"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "{opening_hours_table(opening_hours)}",
|
||||
"fr": "{opening_hours_table(opening_hours)}",
|
||||
"ru": "{opening_hours_table(opening_hours)}",
|
||||
"ja": "{opening_hours_table(opening_hours)}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What are the opening hours of this shop?",
|
||||
"fr": "Quels sont les horaires d'ouverture de ce magasin ?",
|
||||
"ja": "この店の営業時間は何時から何時までですか?",
|
||||
"nl": "Wat zijn de openingsuren van deze winkel?",
|
||||
"ru": "Каковы часы работы этого магазина?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "opening_hours",
|
||||
"type": "opening_hours"
|
||||
},
|
||||
"id": "shops-opening_hours"
|
||||
},
|
||||
"questions",
|
||||
"reviews"
|
||||
],
|
||||
"icon": {
|
||||
"render": "./assets/themes/shops/shop.svg"
|
||||
},
|
||||
"iconOverlays": [
|
||||
{
|
||||
"if": "opening_hours~*",
|
||||
"then": "isOpen",
|
||||
"badge": true
|
||||
}
|
||||
],
|
||||
"width": {
|
||||
"render": "8"
|
||||
},
|
||||
"iconSize": {
|
||||
"render": "40,40,center"
|
||||
},
|
||||
"color": {
|
||||
"render": "#00f"
|
||||
},
|
||||
"presets": [
|
||||
{
|
||||
"tags": [
|
||||
"shop=yes"
|
||||
],
|
||||
"title": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"description": {
|
||||
"en": "Add a new shop",
|
||||
"fr": "Ajouter un nouveau magasin",
|
||||
"ru": "Добавить новый магазин",
|
||||
"ja": "新しい店を追加する",
|
||||
"nl": "Voeg een nieuwe winkel toe"
|
||||
}
|
||||
}
|
||||
],
|
||||
"wayHandling": 2,
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": ["amenity=","disused:amenity:={amenity}"]
|
||||
}
|
||||
},
|
||||
"allowMove": true
|
||||
}
|
|
@ -498,5 +498,18 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -115,5 +115,18 @@
|
|||
"preferredBackground": "photo"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"disused:amenity:={amenity}",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
"neededChangesets": 1
|
||||
},
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuraccy": true
|
||||
}
|
||||
}
|
|
@ -955,6 +955,32 @@
|
|||
],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "move.svg",
|
||||
"license": "CC-BY-SA 3.0 Unported",
|
||||
"authors": [
|
||||
"MGalloway (WMF)"
|
||||
],
|
||||
"sources": [
|
||||
"https://commons.wikimedia.org/wiki/File:Move_icon.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "move_confirm.svg",
|
||||
"license": "CC0",
|
||||
"authors": [
|
||||
"Pieter Vander Vennet"
|
||||
],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "move_not_allowed.svg",
|
||||
"license": "CC0",
|
||||
"authors": [
|
||||
"Pieter Vander Vennet"
|
||||
],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "no_checkmark.svg",
|
||||
"license": "CC0; trivial",
|
||||
|
@ -1137,6 +1163,14 @@
|
|||
"authors": [],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "relocation.svg",
|
||||
"license": "CC0",
|
||||
"authors": [
|
||||
"Pieter Vander Vennet"
|
||||
],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "ring.svg",
|
||||
"license": "CC0; trivial",
|
||||
|
|
7
assets/svg/move.svg
Normal file
7
assets/svg/move.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||
<title>
|
||||
move
|
||||
</title>
|
||||
<path d="M19 10l-4-3v2h-4V5h2l-3-4-3 4h2v4H5V7l-4 3 4 3v-2h4v4H7l3 4 3-4h-2v-4h4v2l4-3z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 260 B |
281
assets/svg/move_confirm.svg
Normal file
281
assets/svg/move_confirm.svg
Normal file
|
@ -0,0 +1,281 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="move_confirm.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10">
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="17.436001"
|
||||
width="25.4126"
|
||||
y="52.703999"
|
||||
x="58.84"
|
||||
id="filter0_d">
|
||||
<feFlood
|
||||
id="feFlood52"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix54"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset56"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur58"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix60"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend62"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend64"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="38"
|
||||
width="38.000099"
|
||||
y="15"
|
||||
x="14"
|
||||
id="filter1_d">
|
||||
<feFlood
|
||||
id="feFlood67"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix69"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset71"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur73"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix75"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend77"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend79"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="53"
|
||||
width="53"
|
||||
y="7"
|
||||
x="39.5"
|
||||
id="filter2_d">
|
||||
<feFlood
|
||||
id="feFlood82"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix84"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset86"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur88"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix90"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend92"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend94"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="38.142899"
|
||||
width="54.766701"
|
||||
y="54"
|
||||
x="11"
|
||||
id="filter3_d">
|
||||
<feFlood
|
||||
id="feFlood97"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix99"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset101"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur103"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix105"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend107"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend109"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="29"
|
||||
width="28"
|
||||
y="64"
|
||||
x="41"
|
||||
id="filter4_d">
|
||||
<feFlood
|
||||
id="feFlood112"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix114"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset116"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur118"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix120"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend122"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend124"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<clipPath
|
||||
id="clip0">
|
||||
<rect
|
||||
style="fill:#ffffff"
|
||||
y="0"
|
||||
x="0"
|
||||
id="rect127"
|
||||
transform="rotate(-45,57.35965,-37.759145)"
|
||||
height="31.819799"
|
||||
width="31.819799" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="960"
|
||||
inkscape:window-height="1003"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.8"
|
||||
inkscape:cx="14.211286"
|
||||
inkscape:cy="-5.2054641"
|
||||
inkscape:window-x="960"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg6" />
|
||||
<title
|
||||
id="title2">
|
||||
move
|
||||
</title>
|
||||
<path
|
||||
d="M19 10l-4-3v2h-4V5h2l-3-4-3 4h2v4H5V7l-4 3 4 3v-2h4v4H7l3 4 3-4h-2v-4h4v2l4-3z"
|
||||
id="path4" />
|
||||
<g
|
||||
id="g942"
|
||||
transform="matrix(0.42132349,0,0,0.42132349,8.3654416,8.6801476)">
|
||||
<circle
|
||||
style="fill:#37d649;fill-opacity:1;stroke:none;stroke-width:0.20323335;stroke-opacity:1"
|
||||
id="circle4"
|
||||
r="9.9584341"
|
||||
cy="15.401706"
|
||||
cx="16.186441" />
|
||||
<path
|
||||
inkscape:transform-center-y="40.988227"
|
||||
inkscape:transform-center-x="14.392136"
|
||||
id="path924"
|
||||
d="m 11,15 4.5,5 6,-8"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.5 KiB |
285
assets/svg/move_not_allowed.svg
Normal file
285
assets/svg/move_not_allowed.svg
Normal file
|
@ -0,0 +1,285 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="move_not_allowed.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10">
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="17.436001"
|
||||
width="25.4126"
|
||||
y="52.703999"
|
||||
x="58.84"
|
||||
id="filter0_d">
|
||||
<feFlood
|
||||
id="feFlood52"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix54"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset56"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur58"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix60"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend62"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend64"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="38"
|
||||
width="38.000099"
|
||||
y="15"
|
||||
x="14"
|
||||
id="filter1_d">
|
||||
<feFlood
|
||||
id="feFlood67"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix69"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset71"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur73"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix75"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend77"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend79"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="53"
|
||||
width="53"
|
||||
y="7"
|
||||
x="39.5"
|
||||
id="filter2_d">
|
||||
<feFlood
|
||||
id="feFlood82"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix84"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset86"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur88"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix90"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend92"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend94"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="38.142899"
|
||||
width="54.766701"
|
||||
y="54"
|
||||
x="11"
|
||||
id="filter3_d">
|
||||
<feFlood
|
||||
id="feFlood97"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix99"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset101"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur103"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix105"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend107"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend109"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
height="29"
|
||||
width="28"
|
||||
y="64"
|
||||
x="41"
|
||||
id="filter4_d">
|
||||
<feFlood
|
||||
id="feFlood112"
|
||||
result="BackgroundImageFix"
|
||||
flood-opacity="0" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix114"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
type="matrix"
|
||||
in="SourceAlpha" />
|
||||
<feOffset
|
||||
id="feOffset116"
|
||||
dy="4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur118"
|
||||
stdDeviation="2" />
|
||||
<feColorMatrix
|
||||
id="feColorMatrix120"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
type="matrix" />
|
||||
<feBlend
|
||||
id="feBlend122"
|
||||
result="effect1_dropShadow"
|
||||
in2="BackgroundImageFix"
|
||||
mode="normal" />
|
||||
<feBlend
|
||||
id="feBlend124"
|
||||
result="shape"
|
||||
in2="effect1_dropShadow"
|
||||
in="SourceGraphic"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<clipPath
|
||||
id="clip0">
|
||||
<rect
|
||||
style="fill:#ffffff"
|
||||
y="0"
|
||||
x="0"
|
||||
id="rect127"
|
||||
transform="rotate(-45,57.35965,-37.759145)"
|
||||
height="31.819799"
|
||||
width="31.819799" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1003"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.8"
|
||||
inkscape:cx="-2.6072629"
|
||||
inkscape:cy="5.7824568"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<title
|
||||
id="title2">
|
||||
move
|
||||
</title>
|
||||
<path
|
||||
d="M19 10l-4-3v2h-4V5h2l-3-4-3 4h2v4H5V7l-4 3 4 3v-2h4v4H7l3 4 3-4h-2v-4h4v2l4-3z"
|
||||
id="path4" />
|
||||
<circle
|
||||
cx="14.76144"
|
||||
cy="14.745519"
|
||||
id="circle4"
|
||||
style="fill:#e72c44;fill-opacity:1;stroke:none;stroke-width:0.09427451;stroke-opacity:1"
|
||||
r="4.619451" />
|
||||
<g
|
||||
transform="matrix(0.20049776,0,0,0.20049776,12.17322,-42.226005)"
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path815"
|
||||
d="M 22.551907,293.60329 2.927466,273.97885 v 0"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:6.0128417;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path815-3"
|
||||
d="M 22.581499,273.88422 2.9570535,293.50867 v 0"
|
||||
style="fill:none;stroke:#fcffff;stroke-width:6.0128417;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.8 KiB |
61
assets/svg/relocation.svg
Normal file
61
assets/svg/relocation.svg
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
height="16px"
|
||||
id="Layer_1"
|
||||
style="enable-background:new 0 0 16 16;fill: #000000;"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
width="16px"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="relocation.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
|
||||
id="metadata9"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1003"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
inkscape:zoom="20.85965"
|
||||
inkscape:cx="10.143178"
|
||||
inkscape:cy="10.590388"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<path
|
||||
d="M 15.968433,9.4957631 14.991526,8.5195302 V 6.1271188 c 0,-0.3705509 -0.303177,-0.6737288 -0.673729,-0.6737288 h -0.673728 c -0.370553,0 -0.67373,0.3031779 -0.67373,0.6737288 v 0.372572 L 11.622881,5.1535806 C 11.438954,4.9797587 11.270522,4.7796611 10.949152,4.7796611 c -0.321369,0 -0.489801,0.2000976 -0.67373,0.3739195 L 5.9298726,9.4957631 c -0.2102033,0.21896 -0.3705508,0.378636 -0.3705508,0.6737279 0,0.379309 0.2910508,0.673729 0.6737289,0.673729 h 0.6737287 v 4.042372 c 0,0.370553 0.303178,0.67373 0.6737289,0.67373 h 2.0211871 v -3.368645 c 0,-0.37055 0.303178,-0.673727 0.6737266,-0.673727 h 1.347459 c 0.37055,0 0.673728,0.303177 0.673728,0.673727 v 3.368645 h 2.021188 c 0.370552,0 0.673729,-0.303177 0.673729,-0.67373 V 10.84322 h 0.673729 c 0.382678,0 0.673729,-0.29442 0.673729,-0.673729 0,-0.2950919 -0.160347,-0.4547679 -0.370551,-0.6737279 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0"
|
||||
style="stroke-width:0.67372882" />
|
||||
<path
|
||||
d="M 7.5468103,3.8654038 6.9092727,3.2283064 V 1.6669989 c 0,-0.2418245 -0.197856,-0.4396809 -0.4396814,-0.4396809 H 6.0299107 c -0.2418254,0 -0.4396815,0.1978564 -0.4396815,0.4396809 V 1.9101425 L 4.7108672,1.0316599 C 4.5908347,0.91822221 4.4809147,0.78763691 4.2711857,0.78763691 c -0.2097281,0 -0.319648,0.1305853 -0.4396814,0.24402299 L 0.99556255,3.8654038 c -0.1371804,0.1428956 -0.2418245,0.2471013 -0.2418245,0.4396805 0,0.2475406 0.1899421,0.4396815 0.43968095,0.4396815 H 1.6331 v 2.6380853 c 0,0.2418254 0.1978565,0.4396815 0.439681,0.4396815 H 3.3918246 V 5.624127 c 0,-0.2418237 0.1978561,-0.4396797 0.4396797,-0.4396797 h 0.8793629 c 0.2418236,0 0.4396805,0.197856 0.4396805,0.4396797 v 2.1984056 h 1.3190436 c 0.2418254,0 0.4396814,-0.1978561 0.4396814,-0.4396815 V 4.7447658 h 0.4396806 c 0.2497393,0 0.4396815,-0.1921409 0.4396815,-0.4396815 0,-0.1925792 -0.104644,-0.2967849 -0.2418245,-0.4396805 z"
|
||||
id="path2-3"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#808080;stroke-width:0.43968096;stroke-opacity:1" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.86116266;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.2635907,11.093613 1.7780944,1.509272 -1.7780944,1.504628"
|
||||
id="path821"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.79756224;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 5.5446079,12.650872 C 4.7207387,12.633302 2.1674541,13.155351 2.3608287,10.176205"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" /></svg>
|
After Width: | Height: | Size: 4 KiB |
|
@ -49,390 +49,6 @@
|
|||
"startLat": 0,
|
||||
"startLon": 0,
|
||||
"layers": [
|
||||
{
|
||||
"id": "artwork",
|
||||
"name": {
|
||||
"en": "Artworks",
|
||||
"nl": "Kunstwerken",
|
||||
"fr": "Œuvres d'art",
|
||||
"de": "Kunstwerke",
|
||||
"id": "Karya seni",
|
||||
"it": "Opere d’arte",
|
||||
"ru": "Произведения искусства",
|
||||
"es": "Obras de arte",
|
||||
"ja": "美術品",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
},
|
||||
"source": {
|
||||
"osmTags": "tourism=artwork"
|
||||
},
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Artwork",
|
||||
"nl": "Kunstwerk",
|
||||
"fr": "Œuvre d'art",
|
||||
"de": "Kunstwerk",
|
||||
"id": "Karya seni",
|
||||
"it": "Opera d’arte",
|
||||
"ru": "Художественная работа",
|
||||
"es": "Obra de arte",
|
||||
"ja": "アートワーク",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "name~*",
|
||||
"then": {
|
||||
"en": "Artwork <i>{name}</i>",
|
||||
"nl": "Kunstwerk <i>{name}</i>",
|
||||
"fr": "Œuvre d'art <i>{name}</i>",
|
||||
"de": "Kunstwerk <i>{name}</i>",
|
||||
"id": "Karya seni <i>{name}</i>",
|
||||
"it": "Opera <i>{name}</i>",
|
||||
"ru": "Художественная работа <i>{name}</i>",
|
||||
"es": "Obra de arte <i>{nombre}</i>",
|
||||
"ja": "アートワーク <i>{name}</i>",
|
||||
"zh_Hant": "藝術品<i>{name}</i>"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"icon": {
|
||||
"render": "./assets/themes/artwork/artwork.svg"
|
||||
},
|
||||
"color": {
|
||||
"render": "#0000ff"
|
||||
},
|
||||
"width": {
|
||||
"render": "10"
|
||||
},
|
||||
"description": {
|
||||
"en": "Diverse pieces of artwork",
|
||||
"nl": "Verschillende soorten kunstwerken",
|
||||
"fr": "Diverses œuvres d'art",
|
||||
"de": "Verschiedene Kunstwerke",
|
||||
"it": "Diverse opere d’arte",
|
||||
"ru": "Разнообразные произведения искусства",
|
||||
"es": "Diversas piezas de obras de arte",
|
||||
"ja": "多様な作品",
|
||||
"zh_Hant": "不同類型的藝術品"
|
||||
},
|
||||
"minzoom": 12,
|
||||
"wayHandling": 2,
|
||||
"presets": [
|
||||
{
|
||||
"tags": [
|
||||
"tourism=artwork"
|
||||
],
|
||||
"title": {
|
||||
"en": "Artwork",
|
||||
"nl": "Kunstwerk",
|
||||
"fr": "Œuvre d'art",
|
||||
"de": "Kunstwerk",
|
||||
"it": "Opera d’arte",
|
||||
"ru": "Художественная работа",
|
||||
"es": "Obra de arte",
|
||||
"ja": "アートワーク",
|
||||
"zh_Hant": "藝術品",
|
||||
"nb_NO": "Kunstverk"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"render": {
|
||||
"en": "This is a {artwork_type}",
|
||||
"nl": "Dit is een {artwork_type}",
|
||||
"fr": "Type d'œuvre : {artwork_type}",
|
||||
"de": "Dies ist ein {artwork_type}",
|
||||
"it": "Si tratta di un {artwork_type}",
|
||||
"ru": "Это {artwork_type}",
|
||||
"es": "Esta es un {artwork_type}",
|
||||
"ja": "これは{artwork_type}です",
|
||||
"zh_Hant": "這是 {artwork_type}",
|
||||
"nb_NO": "Dette er et kunstverk av typen {artwork_type}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the type of this artwork?",
|
||||
"nl": "Wat voor soort kunstwerk is dit?",
|
||||
"fr": "Quel est le type de cette œuvre d'art?",
|
||||
"de": "Was ist die Art dieses Kunstwerks?",
|
||||
"it": "Che tipo di opera d’arte è questo?",
|
||||
"ru": "К какому типу относится эта работа?",
|
||||
"es": "Cuál es el tipo de esta obra de arte?",
|
||||
"ja": "この作品の種類は何ですか?",
|
||||
"zh_Hant": "這是什麼類型的藝術品?",
|
||||
"nb_NO": "Hvilken type kunstverk er dette?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "artwork_type",
|
||||
"addExtraTags": [
|
||||
"fixme=Artowrk type was added with the freeform, might need another check"
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "artwork_type=architecture",
|
||||
"then": {
|
||||
"en": "Architecture",
|
||||
"nl": "Architectuur",
|
||||
"fr": "Architecture",
|
||||
"de": "Architektur",
|
||||
"it": "Architettura",
|
||||
"ru": "Архитектура",
|
||||
"ja": "建物",
|
||||
"zh_Hant": "建築物",
|
||||
"nb_NO": "Arkitektur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=mural",
|
||||
"then": {
|
||||
"en": "Mural",
|
||||
"nl": "Muurschildering",
|
||||
"fr": "Peinture murale",
|
||||
"de": "Wandbild",
|
||||
"it": "Murale",
|
||||
"ru": "Фреска",
|
||||
"ja": "壁画",
|
||||
"zh_Hant": "壁畫",
|
||||
"nb_NO": "Veggmaleri"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=painting",
|
||||
"then": {
|
||||
"en": "Painting",
|
||||
"nl": "Schilderij",
|
||||
"fr": "Peinture",
|
||||
"de": "Malerei",
|
||||
"it": "Dipinto",
|
||||
"ru": "Живопись",
|
||||
"ja": "絵画",
|
||||
"zh_Hant": "繪畫",
|
||||
"nb_NO": "Maleri"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=sculpture",
|
||||
"then": {
|
||||
"en": "Sculpture",
|
||||
"nl": "Beeldhouwwerk",
|
||||
"fr": "Sculpture",
|
||||
"de": "Skulptur",
|
||||
"it": "Scultura",
|
||||
"ru": "Скульптура",
|
||||
"ja": "彫刻",
|
||||
"zh_Hant": "雕塑",
|
||||
"nb_NO": "Skulptur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=statue",
|
||||
"then": {
|
||||
"en": "Statue",
|
||||
"nl": "Standbeeld",
|
||||
"fr": "Statue",
|
||||
"de": "Statue",
|
||||
"it": "Statua",
|
||||
"ru": "Статуя",
|
||||
"ja": "彫像",
|
||||
"zh_Hant": "雕像",
|
||||
"nb_NO": "Statue"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=bust",
|
||||
"then": {
|
||||
"en": "Bust",
|
||||
"nl": "Buste",
|
||||
"fr": "Buste",
|
||||
"de": "Büste",
|
||||
"it": "Busto",
|
||||
"ru": "Бюст",
|
||||
"ja": "胸像",
|
||||
"zh_Hant": "半身像",
|
||||
"nb_NO": "Byste"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=stone",
|
||||
"then": {
|
||||
"en": "Stone",
|
||||
"nl": "Steen",
|
||||
"fr": "Rocher",
|
||||
"de": "Stein",
|
||||
"it": "Masso",
|
||||
"ru": "Камень",
|
||||
"ja": "石",
|
||||
"zh_Hant": "石頭",
|
||||
"nb_NO": "Stein"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=installation",
|
||||
"then": {
|
||||
"en": "Installation",
|
||||
"nl": "Installatie",
|
||||
"fr": "Installation",
|
||||
"de": "Installation",
|
||||
"it": "Istallazione",
|
||||
"ru": "Инсталляция",
|
||||
"ja": "インスタレーション",
|
||||
"zh_Hant": "安裝",
|
||||
"nb_NO": "Installasjon"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=graffiti",
|
||||
"then": {
|
||||
"en": "Graffiti",
|
||||
"nl": "Graffiti",
|
||||
"fr": "Graffiti",
|
||||
"de": "Graffiti",
|
||||
"it": "Graffiti",
|
||||
"ru": "Граффити",
|
||||
"ja": "落書き",
|
||||
"zh_Hant": "塗鴨",
|
||||
"nb_NO": "Graffiti"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=relief",
|
||||
"then": {
|
||||
"en": "Relief",
|
||||
"nl": "Reliëf",
|
||||
"fr": "Relief",
|
||||
"de": "Relief",
|
||||
"it": "Rilievo",
|
||||
"ru": "Рельеф",
|
||||
"ja": "レリーフ",
|
||||
"zh_Hant": "寬慰",
|
||||
"nb_NO": "Relieff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=azulejo",
|
||||
"then": {
|
||||
"en": "Azulejo (Spanish decorative tilework)",
|
||||
"nl": "Azulejo (Spaanse siertegels)",
|
||||
"fr": "Azulejo (faïence latine)",
|
||||
"de": "Azulejo (spanische dekorative Fliesenarbeit)",
|
||||
"it": "Azulejo (ornamento decorativo piastrellato spagnolo)",
|
||||
"ru": "Азуле́жу (испанская роспись глазурованной керамической плитки)",
|
||||
"ja": "Azulejo (スペインの装飾タイル)",
|
||||
"zh_Hant": "Azulejo (西班牙雕塑作品名稱)",
|
||||
"nb_NO": "Azulejo (Spansk dekorativt flisverk)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "artwork_type=tilework",
|
||||
"then": {
|
||||
"en": "Tilework",
|
||||
"nl": "Tegelwerk",
|
||||
"fr": "Carrelage",
|
||||
"de": "Fliesenarbeit",
|
||||
"it": "Mosaico di piastrelle",
|
||||
"ru": "Плитка (мозаика)",
|
||||
"ja": "タイルワーク",
|
||||
"zh_Hant": "瓷磚",
|
||||
"nb_NO": "Flisarbeid"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "artwork-artwork_type"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Which artist created this?",
|
||||
"nl": "Welke kunstenaar creëerde dit kunstwerk?",
|
||||
"fr": "Quel artiste a créé cette œuvre ?",
|
||||
"de": "Welcher Künstler hat das geschaffen?",
|
||||
"it": "Quale artista ha creato quest’opera?",
|
||||
"ru": "Какой художник создал это?",
|
||||
"ja": "どのアーティストが作ったんですか?",
|
||||
"zh_Hant": "創造這個的藝術家是誰?",
|
||||
"nb_NO": "Hvilken artist lagde dette?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Created by {artist_name}",
|
||||
"nl": "Gecreëerd door {artist_name}",
|
||||
"fr": "Créé par {artist_name}",
|
||||
"de": "Erstellt von {artist_name}",
|
||||
"it": "Creato da {artist_name}",
|
||||
"ru": "Создано {artist_name}",
|
||||
"ja": "作成者:{artist_name}",
|
||||
"zh_Hant": "{artist_name} 創作",
|
||||
"nb_NO": "Laget av {artist_name}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "artist_name"
|
||||
},
|
||||
"id": "artwork-artist_name"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Is there a website with more information about this artwork?",
|
||||
"nl": "Is er een website met meer informatie over dit kunstwerk?",
|
||||
"fr": "Existe-t-il un site web où trouver plus d'informations sur cette œuvre d'art ?",
|
||||
"de": "Gibt es eine Website mit weiteren Informationen über dieses Kunstwerk?",
|
||||
"it": "Esiste un sito web con maggiori informazioni su quest’opera?",
|
||||
"ru": "Есть ли сайт с более подробной информацией об этой работе?",
|
||||
"ja": "この作品についての詳しい情報はどのウェブサイトにありますか?",
|
||||
"zh_Hant": "在那個網站能夠找到更多藝術品的資訊?",
|
||||
"nb_NO": "Finnes det en nettside med mer info om dette kunstverket?"
|
||||
},
|
||||
"render": {
|
||||
"en": "More information on <a href='{website}' target='_blank'>this website</a>",
|
||||
"nl": "Meer informatie op <a href='{website}' target='_blank'>deze website</a>",
|
||||
"fr": "Plus d'info <a href='{website}' target='_blank'>sûr ce site web</a>",
|
||||
"de": "Weitere Informationen auf <a href='{website}' target='_blank'>dieser Webseite</a>",
|
||||
"id": "Info lanjut tersedia di <a href='{website}' target='_blank'>laman web</a> ini.",
|
||||
"it": "Ulteriori informazioni su <a href='{website}' target='_blank'>questo sito web</a>",
|
||||
"ru": "Больше информации на <a href='{website}' target='_blank'>этом сайте</a>",
|
||||
"ja": "<a href='{website}' target='_blank'>Webサイト</a>に詳細情報がある",
|
||||
"zh_Hant": "<a href='{website}' target='_blank'>這個網站</a>有更多資訊",
|
||||
"nb_NO": "Mer info er å finne på <a href='{website}' target='_blank'>denne nettsiden</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
"type": "url"
|
||||
},
|
||||
"id": "artwork-website"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Which Wikidata-entry corresponds with <b>this artwork</b>?",
|
||||
"nl": "Welk Wikidata-item beschrijft <b>dit kunstwerk</b>?",
|
||||
"fr": "Quelle entrée Wikidata correspond à <b>cette œuvre d'art</b> ?",
|
||||
"de": "Welcher Wikidata-Eintrag entspricht <b>diesem Kunstwerk</b>?",
|
||||
"it": "Quale elemento Wikidata corrisponde a <b>quest’opera d’arte</b>?",
|
||||
"ru": "Какая запись в Wikidata соответсвует <b>этой работе</b>?",
|
||||
"ja": "<b>このアートワーク</b>に関するWikidataのエントリーはどれですか?",
|
||||
"zh_Hant": "<b>這個藝術品</b>有那個對應的 Wikidata 項目?",
|
||||
"nb_NO": "Hvilken Wikipedia-oppføring samsvarer med <b>dette kunstverket</b>?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Corresponds with <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"nl": "Komt overeen met <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"fr": "Correspond à <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"de": "Entspricht <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"it": "Corrisponde a <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"ru": "Запись об этой работе в wikidata: <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>",
|
||||
"ja": "<a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>に関連する",
|
||||
"zh_Hant": "與 <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>對應",
|
||||
"nb_NO": "Samsvarer med <a href='https://www.wikidata.org/wiki/{wikidata}' target='_blank'>{wikidata}</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "wikidata",
|
||||
"type": "wikidata"
|
||||
},
|
||||
"id": "artwork-wikidata"
|
||||
}
|
||||
]
|
||||
}
|
||||
"artwork"
|
||||
]
|
||||
}
|
|
@ -37,323 +37,6 @@
|
|||
"widenFactor": 3,
|
||||
"socialImage": "",
|
||||
"layers": [
|
||||
{
|
||||
"id": "shops",
|
||||
"name": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
"osmTags": {
|
||||
"and": [
|
||||
"shop~*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"name~*"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "{name}",
|
||||
"fr": "{name}",
|
||||
"ru": "{name}",
|
||||
"ja": "{name}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop!~yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "{shop}",
|
||||
"fr": "{shop}",
|
||||
"ru": "{shop}",
|
||||
"ja": "{shop}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"en": "A shop",
|
||||
"fr": "Un magasin",
|
||||
"ja": "ショップ",
|
||||
"nl": "Een winkel",
|
||||
"ru": "Магазин"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"question": {
|
||||
"en": "What is the name of this shop?",
|
||||
"fr": "Qu'est-ce que le nom de ce magasin?",
|
||||
"ru": "Как называется этот магазин?",
|
||||
"ja": "このお店の名前は何ですか?",
|
||||
"nl": "Wat is de naam van deze winkel?"
|
||||
},
|
||||
"render": "This shop is called <i>{name}</i>",
|
||||
"freeform": {
|
||||
"key": "name"
|
||||
},
|
||||
"id": "shops-name"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "This shop sells {shop}",
|
||||
"fr": "Ce magasin vends {shop}",
|
||||
"ja": "こちらのお店では{shop}を販売しております"
|
||||
},
|
||||
"question": {
|
||||
"en": "What does this shop sell?",
|
||||
"fr": "Que vends ce magasin ?",
|
||||
"ja": "このお店では何を売っていますか?",
|
||||
"ru": "Что продаётся в этом магазине?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "shop"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=convenience"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Convenience store",
|
||||
"fr": "Épicerie/superette",
|
||||
"ja": "コンビニエンスストア"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=supermarket"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Supermarket",
|
||||
"fr": "Supermarché",
|
||||
"ru": "Супермаркет",
|
||||
"ja": "スーパーマーケット",
|
||||
"nl": "Supermarkt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=clothes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Clothing store",
|
||||
"fr": "Magasin de vêtements",
|
||||
"ru": "Магазин одежды",
|
||||
"ja": "衣料品店"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=hairdresser"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Hairdresser",
|
||||
"fr": "Coiffeur",
|
||||
"ru": "Парикмахерская",
|
||||
"ja": "理容師",
|
||||
"nl": "Kapper"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=bakery"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Bakery",
|
||||
"fr": "Boulangerie",
|
||||
"ja": "ベーカリー",
|
||||
"nl": "Bakkerij"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=car_repair"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Car repair (garage)",
|
||||
"fr": "Garagiste",
|
||||
"ja": "自動車修理(ガレージ)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"shop=car"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Car dealer",
|
||||
"fr": "Concessionnaire",
|
||||
"ru": "Автосалон",
|
||||
"ja": "自動車ディーラー"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "shops-shop"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"fr": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ca": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"id": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ru": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ja": "<a href='tel:{phone}'>{phone}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the phone number?",
|
||||
"fr": "Quel est le numéro de téléphone ?",
|
||||
"ja": "電話番号は何番ですか?",
|
||||
"nl": "Wat is het telefoonnummer?",
|
||||
"ru": "Какой телефон?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "phone",
|
||||
"type": "phone"
|
||||
},
|
||||
"id": "shops-phone"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='{website}'>{website}</a>",
|
||||
"fr": "<a href='{website}'>{website}</a>",
|
||||
"ca": "<a href='{website}'>{website}</a>",
|
||||
"id": "<a href='{website}'>{website}</a>",
|
||||
"ru": "<a href='{website}'>{website}</a>",
|
||||
"ja": "<a href='{website}'>{website}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the website of this shop?",
|
||||
"fr": "Quel est le site internet de ce magasin ?",
|
||||
"ja": "このお店のホームページは何ですか?",
|
||||
"nl": "Wat is de website van deze winkel?",
|
||||
"ru": "Какой веб-сайт у этого магазина?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
"type": "url"
|
||||
},
|
||||
"id": "shops-website"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "<a href='mailto:{email}'>{email}</a>",
|
||||
"fr": "<a href='mailto:{email}'>{email}</a>",
|
||||
"id": "<a href='mailto:{email}'>{email}</a>",
|
||||
"ru": "<a href='mailto:{email}'>{email}</a>",
|
||||
"ja": "<a href='mailto:{email}'>{email}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the email address of this shop?",
|
||||
"fr": "Quelle est l'adresse électronique de ce magasin ?",
|
||||
"ja": "このお店のメールアドレスは何ですか?",
|
||||
"ru": "Каков адрес электронной почты этого магазина?",
|
||||
"nl": "Wat is het e-mailadres van deze winkel?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "email",
|
||||
"type": "email"
|
||||
},
|
||||
"id": "shops-email"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "{opening_hours_table(opening_hours)}",
|
||||
"fr": "{opening_hours_table(opening_hours)}",
|
||||
"ru": "{opening_hours_table(opening_hours)}",
|
||||
"ja": "{opening_hours_table(opening_hours)}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What are the opening hours of this shop?",
|
||||
"fr": "Quels sont les horaires d'ouverture de ce magasin ?",
|
||||
"ja": "この店の営業時間は何時から何時までですか?",
|
||||
"nl": "Wat zijn de openingsuren van deze winkel?",
|
||||
"ru": "Каковы часы работы этого магазина?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "opening_hours",
|
||||
"type": "opening_hours"
|
||||
},
|
||||
"id": "shops-opening_hours"
|
||||
},
|
||||
"questions",
|
||||
"reviews"
|
||||
],
|
||||
"icon": {
|
||||
"render": "./assets/themes/shops/shop.svg"
|
||||
},
|
||||
"iconOverlays": [
|
||||
{
|
||||
"if": "opening_hours~*",
|
||||
"then": "isOpen",
|
||||
"badge": true
|
||||
}
|
||||
],
|
||||
"width": {
|
||||
"render": "8"
|
||||
},
|
||||
"iconSize": {
|
||||
"render": "40,40,center"
|
||||
},
|
||||
"color": {
|
||||
"render": "#00f"
|
||||
},
|
||||
"presets": [
|
||||
{
|
||||
"tags": [
|
||||
"shop=yes"
|
||||
],
|
||||
"title": {
|
||||
"en": "Shop",
|
||||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
},
|
||||
"description": {
|
||||
"en": "Add a new shop",
|
||||
"fr": "Ajouter un nouveau magasin",
|
||||
"ru": "Добавить новый магазин",
|
||||
"ja": "新しい店を追加する",
|
||||
"nl": "Voeg een nieuwe winkel toe"
|
||||
}
|
||||
}
|
||||
],
|
||||
"wayHandling": 2
|
||||
}
|
||||
],
|
||||
"roamingRenderings": []
|
||||
"shops"
|
||||
]
|
||||
}
|
|
@ -820,6 +820,10 @@ video {
|
|||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.m-6 {
|
||||
margin: 1.5rem;
|
||||
}
|
||||
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
@ -892,6 +896,10 @@ video {
|
|||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
@ -916,10 +924,6 @@ video {
|
|||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.box-border {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -2426,6 +2430,10 @@ li::marker {
|
|||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.md\:p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.md\:p-3 {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
|
|
@ -254,5 +254,30 @@
|
|||
},
|
||||
"multi_apply": {
|
||||
"autoApply": "When changing the attributes {attr_names}, these attributes will automatically be changed on {count} other objects too"
|
||||
},
|
||||
"move": {
|
||||
"loginToMove": "You must be logged in to move a point",
|
||||
"inviteToMoveAgain": "Move this point again",
|
||||
"moveTitle": "Move this point",
|
||||
"whyMove": "Why do you want to move this point?",
|
||||
"confirmMove": "Move here",
|
||||
"pointIsMoved": "The point has been moved",
|
||||
"zoomInFurther": "Zoom in further to confirm this move",
|
||||
"selectReason": "Why do you move this object?",
|
||||
"reasons": {
|
||||
"reasonRelocation": "The object has been relocated to a totally different location",
|
||||
"reasonInaccurate": "The location of this object is inaccurate and should be moved a few meter"
|
||||
},
|
||||
"inviteToMove": {
|
||||
"generic": "Move this point",
|
||||
"reasonInaccurate": "Improve the accuracy of this point",
|
||||
"reasonRelocation": "Move this object to a another place because it has relocated"
|
||||
},
|
||||
"cannotBeMoved": "This feature cannot be moved.",
|
||||
"isWay": "This feature is a way. Use another OpenStreetMap editor to move it.",
|
||||
"isRelation": "This feature is a relation and can not be moved",
|
||||
"partOfAWay": "This feature is part of another way. Use another editor to move it",
|
||||
"partOfRelation": "This feature is part of a relation. Use another editor to move it",
|
||||
"cancel": "Cancel move"
|
||||
}
|
||||
}
|
|
@ -7,11 +7,11 @@
|
|||
"homepage": "https://mapcomplete.osm.be",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"increase-memory": "export NODE_OPTIONS=--max_old_space_size=6182",
|
||||
"increase-memory": "export NODE_OPTIONS=--max_old_space_size=8364",
|
||||
"start": "npm run start:prepare && npm-run-all --parallel start:parallel:*",
|
||||
"strt": "npm run start:prepare && npm run start:parallel:parcel",
|
||||
"start:prepare": "ts-node scripts/generateLayerOverview.ts --no-fail && npm run increase-memory",
|
||||
"start:parallel:parcel": "parcel *.html UI/** Logic/** assets/*.json assets/svg/* assets/generated/* assets/layers/*/*.svg assets/layers/*/*.jpg assets/layers/*/*.png assets/tagRenderings/*.json assets/themes/*/*.svg assets/themes/*/*.jpg assets/themes/*/*.png vendor/* vendor/*/*",
|
||||
"start:parallel:parcel": "node --max_old_space_size=8000 $(which parcel) serve *.html UI/** Logic/** assets/*.json assets/svg/* assets/generated/* assets/layers/*/*.svg assets/layers/*/*.jpg assets/layers/*/*.png assets/tagRenderings/*.json assets/themes/*/*.svg assets/themes/*/*.jpg assets/themes/*/*.png vendor/* vendor/*/*",
|
||||
"start:parallel:tailwindcli": "tailwindcss -i index.css -o css/index-tailwind-output.css --watch",
|
||||
"generate:css": "tailwindcss -i index.css -o css/index-tailwind-output.css",
|
||||
"test": "ts-node test/TestAll.ts",
|
||||
|
|
35
test.ts
35
test.ts
|
@ -1,3 +1,34 @@
|
|||
import WikipediaBox from "./UI/Wikipedia/WikipediaBox";
|
||||
import MoveWizard from "./UI/Popup/MoveWizard";
|
||||
import State from "./State";
|
||||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
||||
import MinimapImplementation from "./UI/Base/MinimapImplementation";
|
||||
import MoveConfig from "./Models/ThemeConfig/MoveConfig";
|
||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||
import Combine from "./UI/Base/Combine";
|
||||
|
||||
new WikipediaBox(["L614072"]).AttachTo("maindiv")
|
||||
|
||||
State.state = new State(AllKnownLayouts.allKnownLayouts.get("bookcases"))
|
||||
const feature = {
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
id: "node/14925464"
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
4.21875,
|
||||
50.958426723359935
|
||||
]
|
||||
}
|
||||
}
|
||||
/*
|
||||
MinimapImplementation.initialize()
|
||||
new MoveWizard(
|
||||
feature,
|
||||
State.state,
|
||||
new MoveConfig({
|
||||
enableRelocation: false,
|
||||
enableImproveAccuracy: true
|
||||
}, "test")).AttachTo("maindiv")
|
||||
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue