Fix changeset reuse for automaton

This commit is contained in:
pietervdvn 2021-12-17 19:28:05 +01:00
parent 90fc0e0840
commit 0ae78f19f3
4 changed files with 50 additions and 49 deletions

View file

@ -105,7 +105,9 @@ export default class OsmFeatureSource {
// We only keep what is needed // We only keep what is needed
geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties)) geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties))
geojson.features.forEach(f => f.properties["_backend"] = this._backend) geojson.features.forEach(f => {
f.properties["_backend"] = this._backend
})
const index = Tiles.tile_index(z, x, y); const index = Tiles.tile_index(z, x, y);
new PerLayerFeatureSourceSplitter(this.filteredLayers, new PerLayerFeatureSourceSplitter(this.filteredLayers,

View file

@ -107,7 +107,7 @@ export class Changes {
* Uploads all the pending changes in one go. * Uploads all the pending changes in one go.
* Triggered by the 'PendingChangeUploader'-actor in Actors * Triggered by the 'PendingChangeUploader'-actor in Actors
*/ */
public async flushChanges(flushreason: string = undefined) : Promise<void>{ public async flushChanges(flushreason: string = undefined, openChangeset: UIEventSource<number>) : Promise<void>{
if (this.pendingChanges.data.length === 0) { if (this.pendingChanges.data.length === 0) {
return; return;
} }
@ -115,12 +115,14 @@ export class Changes {
console.log("Is already uploading... Abort") console.log("Is already uploading... Abort")
return; return;
} }
console.log("Uploading changes due to: ", flushreason) console.log("Uploading changes due to: ", flushreason)
this.isUploading.setData(true) this.isUploading.setData(true)
try { try {
const csNumber = await this.flushChangesAsync() const csNumber = await this.flushChangesAsync(openChangeset)
this.isUploading.setData(false) this.isUploading.setData(false)
console.log("Changes flushed!"); console.log("Changes flushed. Your changeset is "+csNumber);
} catch (e) { } catch (e) {
this.isUploading.setData(false) this.isUploading.setData(false)
console.error("Flushing changes failed due to", e); console.error("Flushing changes failed due to", e);
@ -207,10 +209,8 @@ export class Changes {
/** /**
* UPload the selected changes to OSM. * UPload the selected changes to OSM.
* Returns 'true' if successfull and if they can be removed * Returns 'true' if successfull and if they can be removed
* @param pending
* @private
*/ */
private async flushSelectChanges(pending: ChangeDescription[]): Promise<boolean> { private async flushSelectChanges(pending: ChangeDescription[], openChangeset: UIEventSource<number>): Promise<boolean> {
const self = this; const self = this;
const neededIds = Changes.GetNeededIds(pending) const neededIds = Changes.GetNeededIds(pending)
@ -304,14 +304,15 @@ export class Changes {
await this.state.osmConnection.changesetHandler.UploadChangeset( await this.state.osmConnection.changesetHandler.UploadChangeset(
(csId) => Changes.createChangesetFor("" + csId, changes), (csId) => Changes.createChangesetFor("" + csId, changes),
metatags metatags,
openChangeset
) )
console.log("Upload successfull!") console.log("Upload successfull!")
return true; return true;
} }
private async flushChangesAsync(): Promise<void> { private async flushChangesAsync(openChangeset: UIEventSource<number>): Promise<void> {
const self = this; const self = this;
try { try {
// At last, we build the changeset and upload // At last, we build the changeset and upload
@ -326,10 +327,23 @@ export class Changes {
pendingPerTheme.get(theme).push(changeDescription) pendingPerTheme.get(theme).push(changeDescription)
} }
const successes = await Promise.all(Array.from(pendingPerTheme, ([_, value]) => value) const successes = await Promise.all(Array.from(pendingPerTheme,
.map(async pendingChanges => { async ([theme, pendingChanges]) => {
try { try {
return await self.flushSelectChanges(pendingChanges); if(openChangeset === undefined){
openChangeset = this.state.osmConnection.GetPreference("current-open-changeset-" + theme).map(
str => {
const n = Number(str);
if (isNaN(n)) {
return undefined
}
return n
}, [], n => "" + n
);
console.log("Using current-open-changeset-"+theme+" from the preferences, got "+openChangeset.data)
}
return await self.flushSelectChanges(pendingChanges, openChangeset);
} catch (e) { } catch (e) {
console.error("Could not upload some changes:", e) console.error("Could not upload some changes:", e)
return false return false

View file

@ -15,7 +15,6 @@ export interface ChangesetTag {
export class ChangesetHandler { export class ChangesetHandler {
public readonly currentChangeset: UIEventSource<number>;
private readonly allElements: ElementStorage; private readonly allElements: ElementStorage;
private osmConnection: OsmConnection; private osmConnection: OsmConnection;
private readonly changes: Changes; private readonly changes: Changes;
@ -24,7 +23,8 @@ export class ChangesetHandler {
private readonly auth: any; private readonly auth: any;
private readonly backend: string; private readonly backend: string;
constructor(layoutName: string, dryRun: boolean, constructor(layoutName: string,
dryRun: boolean,
osmConnection: OsmConnection, osmConnection: OsmConnection,
allElements: ElementStorage, allElements: ElementStorage,
changes: Changes, changes: Changes,
@ -36,19 +36,11 @@ export class ChangesetHandler {
this.userDetails = osmConnection.userDetails; this.userDetails = osmConnection.userDetails;
this.backend = osmConnection._oauth_config.url this.backend = osmConnection._oauth_config.url
this.auth = auth; this.auth = auth;
this.currentChangeset = osmConnection.GetPreference("current-open-changeset-" + layoutName).map(
str => {
const n = Number(str);
if (isNaN(n)) {
return undefined
}
return n
}, [], n => "" + n
);
if (dryRun) { if (dryRun) {
console.log("DRYRUN ENABLED"); console.log("DRYRUN ENABLED");
} }
} }
/** /**
@ -63,7 +55,8 @@ export class ChangesetHandler {
*/ */
public async UploadChangeset( public async UploadChangeset(
generateChangeXML: (csid: number) => string, generateChangeXML: (csid: number) => string,
extraMetaTags: ChangesetTag[]): Promise<void> { extraMetaTags: ChangesetTag[],
openChangeset: UIEventSource<number>): Promise<void> {
if (!extraMetaTags.some(tag => tag.key === "comment") || !extraMetaTags.some(tag => tag.key === "theme")) { if (!extraMetaTags.some(tag => tag.key === "comment") || !extraMetaTags.some(tag => tag.key === "theme")) {
throw "The meta tags should at least contain a `comment` and a `theme`" throw "The meta tags should at least contain a `comment` and a `theme`"
@ -81,30 +74,30 @@ export class ChangesetHandler {
return; return;
} }
if (this.currentChangeset.data === undefined) { if (openChangeset.data === undefined) {
// We have to open a new changeset // We have to open a new changeset
try { try {
const csId = await this.OpenChangeset(extraMetaTags) const csId = await this.OpenChangeset(extraMetaTags)
this.currentChangeset.setData(csId); openChangeset.setData(csId);
const changeset = generateChangeXML(csId); const changeset = generateChangeXML(csId);
console.log("Current changeset is:", changeset); console.trace("Opened a new changeset (openChangeset.data is undefined):", changeset);
await this.AddChange(csId, changeset) await this.AddChange(csId, changeset)
} catch (e) { } catch (e) {
console.error("Could not open/upload changeset due to ", e) console.error("Could not open/upload changeset due to ", e)
this.currentChangeset.setData(undefined) openChangeset.setData(undefined)
} }
} else { } else {
// There still exists an open changeset (or at least we hope so) // There still exists an open changeset (or at least we hope so)
// Let's check! // Let's check!
const csId = this.currentChangeset.data; const csId = openChangeset.data;
try { try {
const oldChangesetMeta = await this.GetChangesetMeta(csId) const oldChangesetMeta = await this.GetChangesetMeta(csId)
if (!oldChangesetMeta.open) { if (!oldChangesetMeta.open) {
// Mark the CS as closed... // Mark the CS as closed...
this.currentChangeset.setData(undefined); console.log("Could not fetch the metadata from the already open changeset")
openChangeset.setData(undefined);
// ... and try again. As the cs is closed, no recursive loop can exist // ... and try again. As the cs is closed, no recursive loop can exist
await this.UploadChangeset(generateChangeXML, extraMetaTags) await this.UploadChangeset(generateChangeXML, extraMetaTags, openChangeset)
return; return;
} }
@ -146,7 +139,7 @@ export class ChangesetHandler {
} catch (e) { } catch (e) {
console.warn("Could not upload, changeset is probably closed: ", e); console.warn("Could not upload, changeset is probably closed: ", e);
this.currentChangeset.setData(undefined); openChangeset.setData(undefined);
} }
} }
} }
@ -209,14 +202,10 @@ export class ChangesetHandler {
private async CloseChangeset(changesetId: number = undefined): Promise<void> { private async CloseChangeset(changesetId: number = undefined): Promise<void> {
const self = this const self = this
return new Promise<void>(function (resolve, reject) { return new Promise<void>(function (resolve, reject) {
if (changesetId === undefined) {
changesetId = self.currentChangeset.data;
}
if (changesetId === undefined) { if (changesetId === undefined) {
return; return;
} }
console.log("closing changeset", changesetId); console.log("closing changeset", changesetId);
self.currentChangeset.setData(undefined);
self.auth.xhr({ self.auth.xhr({
method: 'PUT', method: 'PUT',
path: '/api/0.6/changeset/' + changesetId + '/close', path: '/api/0.6/changeset/' + changesetId + '/close',

View file

@ -30,6 +30,7 @@ import DynamicGeoJsonTileSource from "../Logic/FeatureSource/TiledFeatureSource/
class AutomationPanel extends Combine{ class AutomationPanel extends Combine{
private static readonly openChangeset = new UIEventSource<number>(undefined);
constructor(layoutToUse: LayoutConfig, indices: number[], extraCommentText: UIEventSource<string>, tagRenderingToAutomate: { layer: LayerConfig, tagRendering: TagRenderingConfig }) { constructor(layoutToUse: LayoutConfig, indices: number[], extraCommentText: UIEventSource<string>, tagRenderingToAutomate: { layer: LayerConfig, tagRendering: TagRenderingConfig }) {
const layerId = tagRenderingToAutomate.layer.id const layerId = tagRenderingToAutomate.layer.id
@ -39,8 +40,9 @@ class AutomationPanel extends Combine{
if (indices === undefined) { if (indices === undefined) {
throw ("No tiles loaded - can not automate") throw ("No tiles loaded - can not automate")
} }
const openChangeset = new UIEventSource<string>(undefined); const openChangeset = AutomationPanel.openChangeset;
openChangeset.addCallbackAndRun(cs => console.log("Sync current open changeset to:", cs))
openChangeset.addCallbackAndRun(cs => console.trace("Sync current open changeset to:", cs))
const nextTileToHandle = tileState.map(handledTiles => { const nextTileToHandle = tileState.map(handledTiles => {
for (const index of indices) { for (const index of indices) {
@ -115,7 +117,7 @@ class AutomationPanel extends Combine{
} }
private static TileHandler(layoutToUse: LayoutConfig, tileIndex: number, targetLayer: string, targetAction: TagRenderingConfig, extraCommentText: UIEventSource<string>, private static TileHandler(layoutToUse: LayoutConfig, tileIndex: number, targetLayer: string, targetAction: TagRenderingConfig, extraCommentText: UIEventSource<string>,
openChangeset: UIEventSource<string>, openChangeset: UIEventSource<number>,
whenDone: ((result: string, logMessage?: string) => void)): BaseUIElement { whenDone: ((result: string, logMessage?: string) => void)): BaseUIElement {
const state = new MapState(layoutToUse, {attemptLogin: false}) const state = new MapState(layoutToUse, {attemptLogin: false})
@ -203,13 +205,7 @@ class AutomationPanel extends Combine{
whenDone("no-action","Inspected "+inspected+" elements: "+log.join("; ")) whenDone("no-action","Inspected "+inspected+" elements: "+log.join("; "))
}else{ }else{
state.osmConnection.AttemptLogin() state.osmConnection.AttemptLogin()
const openCS = state.osmConnection.GetPreference("current-open-changeset-"+layoutToUse.id) state.changes.flushChanges("handled tile automatically, time to flush!", openChangeset)
openCS.addCallbackAndRun(cs => {
console.log("Current open Changeset is now: ", cs)
openChangeset.setData(cs)
})
openCS.setData(openChangeset.data)
state.changes.flushChanges("handled tile automatically, time to flush!")
whenDone("fixed", "Updated " + handled+" elements, inspected "+inspected+": "+log.join("; ")) whenDone("fixed", "Updated " + handled+" elements, inspected "+inspected+": "+log.join("; "))
} }
return true; return true;