forked from MapComplete/MapComplete
Huge refactoring: split readonly and writable stores
This commit is contained in:
parent
0946d8ac9c
commit
4283b76f36
95 changed files with 819 additions and 625 deletions
|
@ -1,7 +1,7 @@
|
|||
import {SpecialVisualization} from "../SpecialVisualizations";
|
||||
import FeaturePipelineState from "../../Logic/State/FeaturePipelineState";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Stores, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {DefaultGuiState} from "../DefaultGuiState";
|
||||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
import Img from "../Base/Img";
|
||||
|
@ -97,7 +97,7 @@ class ApplyButton extends UIElement {
|
|||
new ShowDataLayer({
|
||||
leafletMap: previewMap.leafletMap,
|
||||
zoomToFeatures: true,
|
||||
features: new StaticFeatureSource(features, false),
|
||||
features: StaticFeatureSource.fromGeojson(features),
|
||||
state: this.state,
|
||||
layerToShow: this.layer.layerDef,
|
||||
})
|
||||
|
@ -218,7 +218,7 @@ export default class AutoApplyButton implements SpecialVisualization {
|
|||
return new Lazy(() => {
|
||||
const to_parse = new UIEventSource(undefined)
|
||||
// Very ugly hack: read the value every 500ms
|
||||
UIEventSource.Chronic(500, () => to_parse.data === undefined).addCallback(() => {
|
||||
Stores.Chronic(500, () => to_parse.data === undefined).addCallback(() => {
|
||||
const applicable = tagSource.data[argument[1]]
|
||||
to_parse.setData(applicable)
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import Toggle from "../Input/Toggle";
|
|||
import Translations from "../i18n/Translations";
|
||||
import Svg from "../../Svg";
|
||||
import DeleteAction from "../../Logic/Osm/Actions/DeleteAction";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
||||
import Combine from "../Base/Combine";
|
||||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
|
@ -106,7 +106,7 @@ export default class DeleteWizard extends Toggle {
|
|||
}
|
||||
)
|
||||
|
||||
const isShown: UIEventSource<boolean> = tagsSource.map(tgs => tgs.id.indexOf("-") < 0)
|
||||
const isShown: Store<boolean> = tagsSource.map(tgs => tgs.id.indexOf("-") < 0)
|
||||
|
||||
const deleteOptionPicker = DeleteWizard.constructMultipleChoice(options, tagsSource, state);
|
||||
const deleteDialog = new Combine([
|
||||
|
@ -350,8 +350,10 @@ class DeleteabilityChecker {
|
|||
|
||||
if (allByMyself.data === null && useTheInternet) {
|
||||
// We kickoff the download here as it hasn't yet been downloaded. Note that this is mapped onto 'all by myself' above
|
||||
OsmObject.DownloadHistory(id).map(versions => versions.map(version => version.tags["_last_edit:contributor:uid"])).syncWith(previousEditors)
|
||||
const hist = OsmObject.DownloadHistory(id).map(versions => versions.map(version => version.tags["_last_edit:contributor:uid"]))
|
||||
hist.addCallbackAndRunD(hist => previousEditors.setData(hist))
|
||||
}
|
||||
|
||||
if (allByMyself.data === true) {
|
||||
// Yay! We can download!
|
||||
return true;
|
||||
|
|
|
@ -241,7 +241,7 @@ ${Utils.special_visualizations_importRequirementDocs}
|
|||
new ShowDataMultiLayer({
|
||||
leafletMap: confirmationMap.leafletMap,
|
||||
zoomToFeatures: true,
|
||||
features: new StaticFeatureSource([feature], false),
|
||||
features: StaticFeatureSource.fromGeojson([feature]),
|
||||
state: state,
|
||||
layers: state.filteredLayers
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store} from "../../Logic/UIEventSource";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Combine from "../Base/Combine";
|
||||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
|
@ -16,12 +16,12 @@ import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
|||
|
||||
|
||||
export interface MultiApplyParams {
|
||||
featureIds: UIEventSource<string[]>,
|
||||
featureIds: Store<string[]>,
|
||||
keysToApply: string[],
|
||||
text: string,
|
||||
autoapply: boolean,
|
||||
overwrite: boolean,
|
||||
tagsSource: UIEventSource<any>,
|
||||
tagsSource: Store<any>,
|
||||
state: {
|
||||
changes: Changes,
|
||||
allElements: ElementStorage,
|
||||
|
@ -145,7 +145,7 @@ export default class MultiApply extends Toggle {
|
|||
}
|
||||
|
||||
|
||||
const isShown: UIEventSource<boolean> = p.state.osmConnection.isLoggedIn.map(loggedIn => {
|
||||
const isShown: Store<boolean> = p.state.osmConnection.isLoggedIn.map(loggedIn => {
|
||||
return loggedIn && p.featureIds.data.length > 0
|
||||
}, [p.featureIds])
|
||||
super(new Combine(elems), undefined, isShown);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Combine from "../Base/Combine";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, Stores, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {SlideShow} from "../Image/SlideShow";
|
||||
import Toggle from "../Input/Toggle";
|
||||
import {ClickableToggle} from "../Input/Toggle";
|
||||
import Loading from "../Base/Loading";
|
||||
import {AttributedImage} from "../Image/AttributedImage";
|
||||
import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders";
|
||||
|
@ -15,8 +15,6 @@ import {SubtleButton} from "../Base/SubtleButton";
|
|||
import {GeoOperations} from "../../Logic/GeoOperations";
|
||||
import {ElementStorage} from "../../Logic/ElementStorage";
|
||||
import Lazy from "../Base/Lazy";
|
||||
import {Utils} from "../../Utils";
|
||||
import beginningOfLine = Mocha.reporters.Base.cursor.beginningOfLine;
|
||||
|
||||
export interface P4CPicture {
|
||||
pictureUrl: string,
|
||||
|
@ -42,7 +40,7 @@ export interface NearbyImageOptions {
|
|||
// Radius of the upstream search
|
||||
searchRadius?: 500 | number,
|
||||
maxDaysOld?: 1095 | number,
|
||||
blacklist: UIEventSource<{ url: string }[]>,
|
||||
blacklist: Store<{ url: string }[]>,
|
||||
shownImagesCount?: UIEventSource<number>,
|
||||
towardscenter?: UIEventSource<boolean>;
|
||||
allowSpherical?: UIEventSource<boolean>
|
||||
|
@ -173,7 +171,7 @@ export default class NearbyImages extends Lazy {
|
|||
const nearbyImages = state !== undefined ? new ImagesInLoadedDataFetcher(state).fetchAround(options) : []
|
||||
|
||||
|
||||
return UIEventSource.FromPromise<P4CPicture[]>(
|
||||
return Stores.FromPromise<P4CPicture[]>(
|
||||
picManager.startPicsRetrievalAround(new P4C.LatLng(options.lat, options.lon), options.searchRadius ?? 500, {
|
||||
mindate: new Date().getTime() - (options.maxDaysOld ?? (3 * 365)) * 24 * 60 * 60 * 1000,
|
||||
towardscenter: false
|
||||
|
@ -234,7 +232,7 @@ export default class NearbyImages extends Lazy {
|
|||
return new AttributedImage({url: info.thumbUrl, provider, date: new Date(info.date)})
|
||||
}
|
||||
|
||||
protected asToggle(info: P4CPicture): Toggle {
|
||||
protected asToggle(info: P4CPicture): ClickableToggle {
|
||||
const imgNonSelected = NearbyImages.asAttributedImage(info);
|
||||
const imageSelected = NearbyImages.asAttributedImage(info);
|
||||
|
||||
|
@ -246,7 +244,7 @@ export default class NearbyImages extends Lazy {
|
|||
hoveringCheckmark,
|
||||
]).SetClass("relative block")
|
||||
|
||||
return new Toggle(selected, nonSelected).SetClass("").ToggleOnClick();
|
||||
return new ClickableToggle(selected, nonSelected).SetClass("").ToggleOnClick();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ import Translations from "../i18n/Translations";
|
|||
import {Utils} from "../../Utils";
|
||||
import Img from "../Base/Img";
|
||||
import {SlideShow} from "../Image/SlideShow";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Stores, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||
import {UIElement} from "../UIElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
|
||||
export default class NoteCommentElement extends Combine {
|
||||
|
@ -25,7 +24,7 @@ export default class NoteCommentElement extends Combine {
|
|||
}) {
|
||||
const t = Translations.t.notes;
|
||||
|
||||
let actionIcon: BaseUIElement = undefined;
|
||||
let actionIcon: BaseUIElement;
|
||||
if (comment.action === "opened" || comment.action === "reopened") {
|
||||
actionIcon = Svg.note_svg()
|
||||
} else if (comment.action === "closed") {
|
||||
|
@ -41,7 +40,7 @@ export default class NoteCommentElement extends Combine {
|
|||
user = new Link(comment.user, comment.user_url ?? "", true)
|
||||
}
|
||||
|
||||
let userinfo = UIEventSource.FromPromise( Utils.downloadJsonCached("https://www.openstreetmap.org/api/0.6/user/"+comment.uid, 24*60*60*1000))
|
||||
let userinfo = Stores.FromPromise( Utils.downloadJsonCached("https://www.openstreetmap.org/api/0.6/user/"+comment.uid, 24*60*60*1000))
|
||||
let userImg = new VariableUiElement( userinfo.map(userinfo => {
|
||||
const href = userinfo?.user?.img?.href;
|
||||
if(href !== undefined){
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import TagRenderingQuestion from "./TagRenderingQuestion";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Combine from "../Base/Combine";
|
||||
|
@ -14,7 +14,7 @@ import Lazy from "../Base/Lazy";
|
|||
*/
|
||||
export default class QuestionBox extends VariableUiElement {
|
||||
public readonly skippedQuestions: UIEventSource<number[]>;
|
||||
public readonly restingQuestions: UIEventSource<BaseUIElement[]>;
|
||||
public readonly restingQuestions: Store<BaseUIElement[]>;
|
||||
|
||||
constructor(state, options: {
|
||||
tagsSource: UIEventSource<any>,
|
||||
|
@ -81,7 +81,7 @@ export default class QuestionBox extends VariableUiElement {
|
|||
return undefined; // The questions are depleted
|
||||
}, [skippedQuestions]);
|
||||
|
||||
const questionsToAsk: UIEventSource<BaseUIElement[]> = tagsSource.map(tags => {
|
||||
const questionsToAsk: Store<BaseUIElement[]> = tagsSource.map(tags => {
|
||||
if (tags === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Translations from "../i18n/Translations";
|
||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||
import Toggle from "../Input/Toggle";
|
||||
|
@ -6,7 +6,7 @@ import BaseUIElement from "../BaseUIElement";
|
|||
|
||||
export class SaveButton extends Toggle {
|
||||
|
||||
constructor(value: UIEventSource<any>, osmConnection: OsmConnection, textEnabled ?: BaseUIElement, textDisabled ?: BaseUIElement) {
|
||||
constructor(value: Store<any>, osmConnection: OsmConnection, textEnabled ?: BaseUIElement, textDisabled ?: BaseUIElement) {
|
||||
if (value === undefined) {
|
||||
throw "No event source for savebutton, something is wrong"
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ export default class SplitRoadWizard extends Toggle {
|
|||
|
||||
// Datalayer displaying the road and the cut points (if any)
|
||||
new ShowDataMultiLayer({
|
||||
features: new StaticFeatureSource([roadElement], false),
|
||||
features: StaticFeatureSource.fromGeojson([roadElement]),
|
||||
layers: state.filteredLayers,
|
||||
leafletMap: miniMap.leafletMap,
|
||||
zoomToFeatures: true,
|
||||
|
@ -86,7 +86,7 @@ export default class SplitRoadWizard extends Toggle {
|
|||
})
|
||||
|
||||
new ShowDataLayer({
|
||||
features: new StaticFeatureSource(splitPoints, true),
|
||||
features: new StaticFeatureSource(splitPoints),
|
||||
leafletMap: miniMap.leafletMap,
|
||||
zoomToFeatures: false,
|
||||
layerToShow: SplitRoadWizard.splitLayerStyling,
|
||||
|
|
|
@ -3,7 +3,7 @@ import Translations from "../i18n/Translations";
|
|||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
import Combine from "../Base/Combine";
|
||||
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
|
||||
|
@ -40,7 +40,7 @@ export default class TagApplyButton implements AutoAction {
|
|||
];
|
||||
public readonly example = "`{tag_apply(survey_date=$_now:date, Surveyed today!)}`, `{tag_apply(addr:street=$addr:street, Apply the address, apply_icon.svg, _closest_osm_id)";
|
||||
|
||||
public static generateTagsToApply(spec: string, tagSource: UIEventSource<any>): UIEventSource<Tag[]> {
|
||||
public static generateTagsToApply(spec: string, tagSource: Store<any>): Store<Tag[]> {
|
||||
|
||||
const tgsSpec = spec.split(";").map(spec => {
|
||||
const kv = spec.split("=").map(s => s.trim());
|
||||
|
|
|
@ -2,7 +2,6 @@ import {UIEventSource} from "../../Logic/UIEventSource";
|
|||
import {Utils} from "../../Utils";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import List from "../Base/List";
|
||||
import {SubstitutedTranslation} from "../SubstitutedTranslation";
|
||||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import Combine from "../Base/Combine";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {Store, Stores, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Combine from "../Base/Combine";
|
||||
import {InputElement} from "../Input/InputElement";
|
||||
import {InputElement, ReadonlyInputElement} from "../Input/InputElement";
|
||||
import ValidatedTextField from "../Input/ValidatedTextField";
|
||||
import {FixedInputElement} from "../Input/FixedInputElement";
|
||||
import {RadioButton} from "../Input/RadioButton";
|
||||
|
@ -45,14 +45,14 @@ export default class TagRenderingQuestion extends Combine {
|
|||
units?: Unit[],
|
||||
afterSave?: () => void,
|
||||
cancelButton?: BaseUIElement,
|
||||
saveButtonConstr?: (src: UIEventSource<TagsFilter>) => BaseUIElement,
|
||||
bottomText?: (src: UIEventSource<TagsFilter>) => BaseUIElement
|
||||
saveButtonConstr?: (src: Store<TagsFilter>) => BaseUIElement,
|
||||
bottomText?: (src: Store<TagsFilter>) => BaseUIElement
|
||||
}
|
||||
) {
|
||||
|
||||
|
||||
const applicableMappingsSrc =
|
||||
UIEventSource.ListStabilized(tags.map(tags => {
|
||||
Stores.ListStabilized(tags.map(tags => {
|
||||
const applicableMappings: { if: TagsFilter, icon?: string, then: TypedTranslation<object>, ifnot?: TagsFilter, addExtraTags: Tag[] }[] = []
|
||||
for (const mapping of configuration.mappings ?? []) {
|
||||
if (mapping.hideInAnswer === true) {
|
||||
|
@ -81,7 +81,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
|
||||
|
||||
const feedback = new UIEventSource<Translation>(undefined)
|
||||
const inputElement: InputElement<TagsFilter> =
|
||||
const inputElement: ReadonlyInputElement<TagsFilter> =
|
||||
new VariableInputElement(applicableMappingsSrc.map(applicableMappings =>
|
||||
TagRenderingQuestion.GenerateInputElement(state, configuration, applicableMappings, applicableUnit, tags, feedback)
|
||||
))
|
||||
|
@ -452,8 +452,8 @@ export default class TagRenderingQuestion extends Combine {
|
|||
|
||||
}
|
||||
|
||||
public static CreateTagExplanation(selectedValue: UIEventSource<TagsFilter>,
|
||||
tags: UIEventSource<object>,
|
||||
public static CreateTagExplanation(selectedValue: Store<TagsFilter>,
|
||||
tags: Store<object>,
|
||||
state?: {osmConnection?: OsmConnection}){
|
||||
return new VariableUiElement(
|
||||
selectedValue.map(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue