Hook deleteWizard into the specialVisualisations (WIP)
This commit is contained in:
parent
5d3365afb8
commit
de5f8f95bb
3 changed files with 61 additions and 21 deletions
|
@ -10,10 +10,12 @@ export default class DeleteAction {
|
||||||
public readonly canBeDeleted: UIEventSource<{ canBeDeleted?: boolean, reason: Translation }>;
|
public readonly canBeDeleted: UIEventSource<{ canBeDeleted?: boolean, reason: Translation }>;
|
||||||
public readonly isDeleted = new UIEventSource<boolean>(false);
|
public readonly isDeleted = new UIEventSource<boolean>(false);
|
||||||
private readonly _id: string;
|
private readonly _id: string;
|
||||||
|
private readonly _allowDeletionAtChangesetCount: number;
|
||||||
|
|
||||||
|
|
||||||
constructor(id: string) {
|
constructor(id: string, allowDeletionAtChangesetCount?: number) {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
|
this._allowDeletionAtChangesetCount = allowDeletionAtChangesetCount ?? Number.MAX_VALUE;
|
||||||
|
|
||||||
this.canBeDeleted = new UIEventSource<{ canBeDeleted?: boolean; reason: Translation }>({
|
this.canBeDeleted = new UIEventSource<{ canBeDeleted?: boolean; reason: Translation }>({
|
||||||
canBeDeleted: undefined,
|
canBeDeleted: undefined,
|
||||||
|
@ -104,7 +106,7 @@ export default class DeleteAction {
|
||||||
if (!ud.loggedIn) {
|
if (!ud.loggedIn) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ud.csCount >= Constants.userJourney.deletePointsOfOthersUnlock;
|
return ud.csCount >= Math.min(Constants.userJourney.deletePointsOfOthersUnlock, this._allowDeletionAtChangesetCount);
|
||||||
})
|
})
|
||||||
|
|
||||||
const previousEditors = new UIEventSource<number[]>(undefined)
|
const previousEditors = new UIEventSource<number[]>(undefined)
|
||||||
|
|
|
@ -41,11 +41,12 @@ export default class DeleteWizard extends Toggle {
|
||||||
constructor(id: string,
|
constructor(id: string,
|
||||||
options?: {
|
options?: {
|
||||||
noDeleteOptions?: { if: Tag[], then: Translation }[]
|
noDeleteOptions?: { if: Tag[], then: Translation }[]
|
||||||
softDeletionTags?: Tag[]
|
softDeletionTags?: Tag[],
|
||||||
|
neededChangesets?: number
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
options = options ?? {}
|
options = options ?? {}
|
||||||
const deleteAction = new DeleteAction(id);
|
const deleteAction = new DeleteAction(id, options.neededChangesets);
|
||||||
const tagsSource = State.state.allElements.getEventSourceById(id)
|
const tagsSource = State.state.allElements.getEventSourceById(id)
|
||||||
|
|
||||||
let softDeletionTags = options.softDeletionTags ?? []
|
let softDeletionTags = options.softDeletionTags ?? []
|
||||||
|
|
|
@ -24,8 +24,10 @@ import Histogram from "./BigComponents/Histogram";
|
||||||
import Loc from "../Models/Loc";
|
import Loc from "../Models/Loc";
|
||||||
import {Utils} from "../Utils";
|
import {Utils} from "../Utils";
|
||||||
import BaseLayer from "../Models/BaseLayer";
|
import BaseLayer from "../Models/BaseLayer";
|
||||||
|
import DeleteWizard from "./Popup/DeleteWizard";
|
||||||
|
import Constants from "../Models/Constants";
|
||||||
|
|
||||||
export interface SpecialVisualization{
|
export interface SpecialVisualization {
|
||||||
funcName: string,
|
funcName: string,
|
||||||
constr: ((state: State, tagSource: UIEventSource<any>, argument: string[]) => BaseUIElement),
|
constr: ((state: State, tagSource: UIEventSource<any>, argument: string[]) => BaseUIElement),
|
||||||
docs: string,
|
docs: string,
|
||||||
|
@ -36,6 +38,14 @@ export interface SpecialVisualization{
|
||||||
export default class SpecialVisualizations {
|
export default class SpecialVisualizations {
|
||||||
|
|
||||||
|
|
||||||
|
public static specialVisualisationsByName: Map<string, SpecialVisualization> = SpecialVisualizations.byName();
|
||||||
|
static HelpMessage: BaseUIElement = SpecialVisualizations.GenHelpMessage();
|
||||||
|
static constructMiniMap: (options?: {
|
||||||
|
background?: UIEventSource<BaseLayer>,
|
||||||
|
location?: UIEventSource<Loc>,
|
||||||
|
allowMoving?: boolean
|
||||||
|
}) => BaseUIElement;
|
||||||
|
static constructShowDataLayer: (features: UIEventSource<{ feature: any; freshness: Date }[]>, leafletMap: UIEventSource<any>, layoutToUse: UIEventSource<any>, enablePopups?: boolean, zoomToFeatures?: boolean) => any;
|
||||||
public static specialVisualizations: SpecialVisualization[] =
|
public static specialVisualizations: SpecialVisualization[] =
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -137,7 +147,7 @@ export default class SpecialVisualizations {
|
||||||
zoom = parsed;
|
zoom = parsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const locationSource =new UIEventSource<Loc>({
|
const locationSource = new UIEventSource<Loc>({
|
||||||
lat: Number(properties._lat),
|
lat: Number(properties._lat),
|
||||||
lon: Number(properties._lon),
|
lon: Number(properties._lon),
|
||||||
zoom: zoom
|
zoom: zoom
|
||||||
|
@ -149,9 +159,9 @@ export default class SpecialVisualizations {
|
||||||
allowMoving: false
|
allowMoving: false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
locationSource.addCallback(loc => {
|
locationSource.addCallback(loc => {
|
||||||
if(loc.zoom > zoom){
|
if (loc.zoom > zoom) {
|
||||||
// We zoom back
|
// We zoom back
|
||||||
locationSource.data.zoom = zoom;
|
locationSource.data.zoom = zoom;
|
||||||
locationSource.ping();
|
locationSource.ping();
|
||||||
|
@ -370,29 +380,56 @@ export default class SpecialVisualizations {
|
||||||
[state.layoutToUse])
|
[state.layoutToUse])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
funcName: "delete",
|
||||||
|
docs: `Offers a dialog to (soft) delete the point. The dialog is built to be user friendly and to prevent mistakes. If deletion is not possible, the dialog will hide itself.
|
||||||
|
|
||||||
|
#### Hard deletion if enough experience
|
||||||
|
|
||||||
|
A feature can only be deleted by mapcomplete if:
|
||||||
|
|
||||||
|
- It is a node
|
||||||
|
- No ways or relations use the node
|
||||||
|
- The logged-in user has enough experience (at least ${Constants.userJourney.deletePointsOfOthersUnlock} changesets) OR the user is the only one to have edited the point previously
|
||||||
|
- The user did not select one of the 'non-delete-options' (see below)
|
||||||
|
|
||||||
|
In all other cases, a 'soft deletion' is used.
|
||||||
|
|
||||||
|
#### Soft deletion
|
||||||
|
|
||||||
|
A 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.
|
||||||
|
This makes it look like it was deleted, without doing damage. A fixme will be added to the point.
|
||||||
|
|
||||||
|
Note that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme
|
||||||
|
|
||||||
|
#### No-delete options
|
||||||
|
|
||||||
|
In some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed "because the path is on their private property").
|
||||||
|
However, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice "hey, there is a path missing here! Let me redraw it in OSM!)
|
||||||
|
|
||||||
|
The correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.
|
||||||
|
A no-delete option is offered as 'reason to delete it', but secretly retags.
|
||||||
|
|
||||||
|
`,
|
||||||
|
args: [],
|
||||||
|
constr: (state, tagSource, args) => {
|
||||||
|
return new VariableUiElement(tagSource.map(tags => tags.id).map(id =>
|
||||||
|
new DeleteWizard(id)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
private static byName() : Map<string, SpecialVisualization>{
|
private static byName(): Map<string, SpecialVisualization> {
|
||||||
const result = new Map<string, SpecialVisualization>();
|
const result = new Map<string, SpecialVisualization>();
|
||||||
|
|
||||||
for (const specialVisualization of SpecialVisualizations.specialVisualizations) {
|
for (const specialVisualization of SpecialVisualizations.specialVisualizations) {
|
||||||
result.set(specialVisualization.funcName, specialVisualization)
|
result.set(specialVisualization.funcName, specialVisualization)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static specialVisualisationsByName: Map<string, SpecialVisualization> = SpecialVisualizations.byName();
|
|
||||||
|
|
||||||
static HelpMessage: BaseUIElement = SpecialVisualizations.GenHelpMessage();
|
|
||||||
static constructMiniMap: (options?: {
|
|
||||||
background?: UIEventSource<BaseLayer>,
|
|
||||||
location?: UIEventSource<Loc>,
|
|
||||||
allowMoving?: boolean
|
|
||||||
}) => BaseUIElement;
|
|
||||||
static constructShowDataLayer: (features: UIEventSource<{ feature: any; freshness: Date }[]>, leafletMap: UIEventSource<any>, layoutToUse: UIEventSource<any>, enablePopups?: boolean, zoomToFeatures?: boolean) => any;
|
|
||||||
|
|
||||||
private static GenHelpMessage() {
|
private static GenHelpMessage() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue