forked from MapComplete/MapComplete
135 lines
5 KiB
TypeScript
135 lines
5 KiB
TypeScript
import { UIEventSource } from "../../Logic/UIEventSource"
|
|
import Translations from "../i18n/Translations"
|
|
import { Translation } from "../i18n/Translation"
|
|
import BaseUIElement from "../BaseUIElement"
|
|
import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction"
|
|
import MoveConfig from "../../Models/ThemeConfig/MoveConfig"
|
|
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction"
|
|
import { And } from "../../Logic/Tags/And"
|
|
import { Tag } from "../../Logic/Tags/Tag"
|
|
import { SpecialVisualizationState } from "../SpecialVisualization"
|
|
import { Feature, Point } from "geojson"
|
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
|
import Relocation from "../../assets/svg/Relocation.svelte"
|
|
import Location from "../../assets/svg/Location.svelte"
|
|
|
|
export interface MoveReason {
|
|
text: Translation | string
|
|
invitingText: Translation | string
|
|
icon: BaseUIElement
|
|
changesetCommentValue: string
|
|
lockBounds: true | boolean
|
|
includeSearch: false | boolean
|
|
background: undefined | "map" | "photo" | string | string[]
|
|
startZoom: number
|
|
minZoom: number
|
|
eraseAddressFields: false | boolean
|
|
}
|
|
|
|
export class MoveWizardState {
|
|
public readonly reasons: ReadonlyArray<MoveReason>
|
|
|
|
public readonly moveDisallowedReason = new UIEventSource<Translation>(undefined)
|
|
private readonly _state: SpecialVisualizationState
|
|
|
|
constructor(id: string, options: MoveConfig, state: SpecialVisualizationState) {
|
|
this._state = state
|
|
this.reasons = MoveWizardState.initReasons(options)
|
|
if (this.reasons.length > 0) {
|
|
this.checkIsAllowed(id)
|
|
}
|
|
}
|
|
|
|
private static initReasons(options: MoveConfig): MoveReason[] {
|
|
const t = Translations.t.move
|
|
|
|
const reasons: MoveReason[] = []
|
|
if (options.enableRelocation) {
|
|
reasons.push({
|
|
text: t.reasons.reasonRelocation,
|
|
invitingText: t.inviteToMove.reasonRelocation,
|
|
icon: new SvelteUIElement(Relocation),
|
|
changesetCommentValue: "relocated",
|
|
lockBounds: false,
|
|
background: undefined,
|
|
includeSearch: true,
|
|
startZoom: 12,
|
|
minZoom: 6,
|
|
eraseAddressFields: true,
|
|
})
|
|
}
|
|
if (options.enableImproveAccuracy) {
|
|
reasons.push({
|
|
text: t.reasons.reasonInaccurate,
|
|
invitingText: t.inviteToMove.reasonInaccurate,
|
|
icon: new SvelteUIElement(Location),
|
|
changesetCommentValue: "improve_accuracy",
|
|
lockBounds: true,
|
|
includeSearch: false,
|
|
background: "photo",
|
|
startZoom: 18,
|
|
minZoom: 16,
|
|
eraseAddressFields: false,
|
|
})
|
|
}
|
|
return reasons
|
|
}
|
|
|
|
public async moveFeature(
|
|
loc: { lon: number; lat: number },
|
|
reason: MoveReason,
|
|
featureToMove: Feature<Point>
|
|
) {
|
|
const state = this._state
|
|
await state.changes.applyAction(
|
|
new ChangeLocationAction(featureToMove.properties.id, [loc.lon, loc.lat], {
|
|
reason: reason.changesetCommentValue,
|
|
theme: state.layout.id,
|
|
})
|
|
)
|
|
featureToMove.properties._lat = loc.lat
|
|
featureToMove.properties._lon = loc.lon
|
|
featureToMove.geometry.coordinates = [loc.lon, loc.lat]
|
|
if (reason.eraseAddressFields) {
|
|
await state.changes.applyAction(
|
|
new ChangeTagAction(
|
|
featureToMove.properties.id,
|
|
new And([
|
|
new Tag("addr:housenumber", ""),
|
|
new Tag("addr:street", ""),
|
|
new Tag("addr:city", ""),
|
|
new Tag("addr:postcode", ""),
|
|
]),
|
|
featureToMove.properties,
|
|
{
|
|
changeType: "relocated",
|
|
theme: state.layout.id,
|
|
}
|
|
)
|
|
)
|
|
}
|
|
|
|
state.featureProperties.getStore(featureToMove.properties.id)?.ping()
|
|
state.mapProperties.location.setData(loc)
|
|
}
|
|
|
|
private checkIsAllowed(id: string) {
|
|
const t = Translations.t.move
|
|
if (id.startsWith("way")) {
|
|
this.moveDisallowedReason.setData(t.isWay)
|
|
} else if (id.startsWith("relation")) {
|
|
this.moveDisallowedReason.setData(t.isRelation)
|
|
} else if (id.indexOf("-") < 0) {
|
|
this._state.osmObjectDownloader.DownloadReferencingWays(id).then((referencing) => {
|
|
if (referencing.length > 0) {
|
|
this.moveDisallowedReason.setData(t.partOfAWay)
|
|
}
|
|
})
|
|
this._state.osmObjectDownloader.DownloadReferencingRelations(id).then((partOf) => {
|
|
if (partOf.length > 0) {
|
|
this.moveDisallowedReason.setData(t.partOfRelation)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|