Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
b010e97b42
Prototype for Conflict editor/tagmerge 2022-07-20 11:57:01 +02:00
4 changed files with 163 additions and 2 deletions

View file

@ -83,6 +83,10 @@ Instead of using `{"render": {"en": "{some_special_visualisation(some_arg, some
* [Example usage of nearby_images](#example-usage-of-nearby_images)
+ [mapillary_link](#mapillary_link)
* [Example usage of mapillary_link](#example-usage-of-mapillary_link)
+ [maproulette_task](#maproulette_task)
* [Example usage of maproulette_task](#example-usage-of-maproulette_task)
+ [tag_merge](#tag_merge)
* [Example usage of tag_merge](#example-usage-of-tag_merge)
+ [auto_apply](#auto_apply)
* [Example usage of auto_apply](#example-usage-of-auto_apply)
@ -696,11 +700,39 @@ zoom | 18 | The startzoom of mapillary
### maproulette_task
Show details of a MapRoulette task
#### Example usage of maproulette_task
`{maproulette_task()}`
### tag_merge
Shows a comparison between the current tags and the new tags, allowing the user to select what the new tags should be.
name | default | description
------ | --------- | -------------
new_tags | _undefined_ | The new tags to show in the comparison, if the field starts with '$' it will be looked up in the tag source
message | _undefined_ | The text to show to the contributor
image | _undefined_ | An image to show to the contributor on the button
id_of_object_to_apply_this_one | _undefined_ | If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element
#### Example usage of tag_merge
### auto_apply
A button to run many actions for many features at once. To effectively use this button, you'll need some ingredients:
- A target layer with features for which an action is defined in a tag rendering. The following special visualisations support an autoAction: import_way_button, tag_apply
- A target layer with features for which an action is defined in a tag rendering. The following special visualisations support an autoAction: import_way_button, tag_apply, tag_merge
- A host feature to place the auto-action on. This can be a big outline (such as a city). Another good option for this is the layer
- [current_view](./BuiltinLayers.md#current_view)
- Then, use a calculated tag on the host feature to determine the overlapping object ids

122
UI/Popup/TagMergeButton.ts Normal file
View file

@ -0,0 +1,122 @@
import { Changes } from "../../Logic/Osm/Changes";
import FeaturePipelineState from "../../Logic/State/FeaturePipelineState";
import { UIEventSource } from "../../Logic/UIEventSource";
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import Combine from "../Base/Combine";
import { SubtleButton } from "../Base/SubtleButton";
import Table from "../Base/Table";
import { VariableUiElement } from "../Base/VariableUIElement";
import BaseUIElement from "../BaseUIElement";
import { DefaultGuiState } from "../DefaultGuiState";
import Translations from "../i18n/Translations";
import { DropDown } from "../Input/DropDown";
import { AutoAction } from "./AutoApplyButton";
import TagApplyButton from "./TagApplyButton";
export default class TagMergeButton implements AutoAction {
public readonly funcName = "tag_merge";
public readonly docs =
"Shows a comparison between the current tags and the new tags, allowing the user to select what the new tags should be.";
public readonly supportsAutoAction = true;
public readonly args = [
{
name: "new_tags",
doc: "The new tags to show in the comparison, if the field starts with '$' it will be looked up in the tag source",
},
{
name: "message",
doc: "The text to show to the contributor",
},
{
name: "image",
defaultValue: "./assets/svg/addSmall.svg",
doc: "An image to show to the contributor on the button",
},
{
name: "id_of_object_to_apply_this_one",
defaultValue: undefined,
doc: "If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element",
},
];
public readonly example = "";
async applyActionOn(
state: {
layoutToUse: LayoutConfig;
changes: Changes;
},
tags: UIEventSource<any>,
args: string[]
): Promise<void> {}
public updateView(
state: FeaturePipelineState,
tagSource: UIEventSource<any>,
argument: string[],
guistate: DefaultGuiState
): BaseUIElement {
return this.constr(state, tagSource, argument, guistate);
}
public constr(
state: FeaturePipelineState,
tagSource: UIEventSource<any>,
argument: string[],
guistate: DefaultGuiState
): BaseUIElement {
const newTags = TagApplyButton.generateTagsToApply(argument[0], tagSource);
const otherId = tagSource.data[argument[3]];
const otherElement = state.allElements.getEventSourceById(otherId);
const t = Translations.t.general.merge_button;
otherElement.addCallback(this.updateView.bind(this, state, tagSource, argument, guistate));
let table = [];
for (const tag of newTags.data) {
if (tag.value !== otherElement.data[tag.key]) {
const otherTag = new Combine([
`${tag.key}=`,
new VariableUiElement(
otherElement.map((otherElement) => {
return otherElement[tag.key];
})
),
]);
let items = [
{
value: tag.value,
shown: tag.value,
}
];
if (
otherElement.data[tag.key] !== undefined &&
otherElement.data[tag.key] !== tag.value
) {
items.push({
value: otherElement.data[tag.key],
shown: otherElement.data[tag.key],
});
}
if (items.length == 1) {
// If there is only one item, we don't need to show the dropdown
table.push([
`${tag.key}=${tag.value}`,
tag.value,
otherTag,
]);
} else {
// There is more than one choice, so we need to show the dropdown
const dropdown = new DropDown("", items);
table.push([`${tag.key}=${tag.value}`, dropdown, otherTag]);
}
}
}
return new Combine([
new Table([t.new_tags, t.result, t.current_tags], table),
new SubtleButton(argument[2], argument[1]),
]);
}
}

View file

@ -58,6 +58,7 @@ import {MapillaryLink} from "./BigComponents/MapillaryLink";
import {CheckBox} from "./Input/Checkboxes";
import Slider from "./Input/Slider";
import List from "./Base/List";
import TagMergeButton from "./Popup/TagMergeButton";
export interface SpecialVisualization {
funcName: string,
@ -1125,7 +1126,8 @@ export default class SpecialVisualizations {
return details;
},
docs: "Show details of a MapRoulette task"
}
},
new TagMergeButton()
]
specialVisualizations.push(new AutoApplyButton(specialVisualizations))

View file

@ -147,6 +147,11 @@
"loginToStart": "Log in to answer this question",
"loginWithOpenStreetMap": "Login with OpenStreetMap",
"logout": "Log out",
"merge_button": {
"current_tags": "Current tags",
"new_tags": "Suggested new tags",
"result": "Resulting tags"
},
"morescreen": {
"createYourOwnTheme": "Create your own MapComplete theme from scratch",
"hiddenExplanation": "These themes are only accessible to those with the link. You have discovered {hidden_discovered} of {total_hidden} hidden themes.",