diff --git a/frontend/src/map/click-marker/click-marker.ts b/frontend/src/map/click-marker/click-marker.ts index b5b4128f..64d9f882 100644 --- a/frontend/src/map/click-marker/click-marker.ts +++ b/frontend/src/map/click-marker/click-marker.ts @@ -27,6 +27,7 @@ export default class ClickMarker extends Vue { results: SearchResult[] = []; layers!: SearchResultsLayer[]; // Don't make layer objects reactive + isAdding = false; mounted(): void { this.layers = []; @@ -110,6 +111,7 @@ export default class ClickMarker extends Vue { async addToMap(result: SearchResult, type: Type): Promise { this.$bvToast.hide("fm-click-marker-add-error"); + this.isAdding = true; try { const obj: Partial & LineCreate> = { @@ -142,6 +144,8 @@ export default class ClickMarker extends Vue { this.close(result); } catch (err) { showErrorToast(this, "fm-click-marker-add-error", "Error adding to map", err); + } finally { + this.isAdding = false; } } diff --git a/frontend/src/map/click-marker/click-marker.vue b/frontend/src/map/click-marker/click-marker.vue index c50a3601..6ddd21c9 100644 --- a/frontend/src/map/click-marker/click-marker.vue +++ b/frontend/src/map/click-marker/click-marker.vue @@ -8,6 +8,7 @@ = []; + isAddingType: Array = []; + get hasViews(): boolean { return this.file.views.length > 0; } @@ -49,11 +52,14 @@ export default class FileResults extends Vue { async addView(view: ViewImport): Promise { this.$bvModal.hide("fm-file-result-import-error"); - + this.isAddingView.push(view); + try { await this.client.addView(view); } catch (err) { showErrorToast(this, "fm-file-result-import-error", "Error importing view", err); + } finally { + this.isAddingView = this.isAddingView.filter((v) => v !== view); } }; @@ -63,11 +69,14 @@ export default class FileResults extends Vue { async addType(type: TypeImport): Promise { this.$bvModal.hide("fm-file-result-import-error"); + this.isAddingType.push(type); try { - this.client.addType(type); + await this.client.addType(type); } catch (err) { showErrorToast(this, "fm-file-result-import-error", "Error importing type", err); + } finally { + this.isAddingType = this.isAddingType.filter((t) => t !== type); } }; diff --git a/frontend/src/map/file-results/file-results.vue b/frontend/src/map/file-results/file-results.vue index 6252f2d9..6e10eaee 100644 --- a/frontend/src/map/file-results/file-results.vue +++ b/frontend/src/map/file-results/file-results.vue @@ -16,7 +16,8 @@ {{" "}} (View) - + + @@ -33,7 +34,8 @@ {{" "}} (Type) - + + diff --git a/frontend/src/map/history/history.ts b/frontend/src/map/history/history.ts index 9bd597eb..701dd46a 100644 --- a/frontend/src/map/history/history.ts +++ b/frontend/src/map/history/history.ts @@ -24,14 +24,22 @@ export default class History extends Vue { @Prop({ type: String, required: true }) id!: string; popover: { entry: HistoryEntryWithLabels; target: HTMLElement } | null = null; + isLoading = true; + reverting: HistoryEntryWithLabels | null = null; - async handleShow(): Promise { + handleShow(): void { + this.isLoading = true; + } + + async handleShown(): Promise { this.$bvToast.hide("fm-history-error"); try { await this.client.listenToHistory(); } catch (err) { showErrorToast(this, "fm-history-error", "Error loading history", err); + } finally { + this.isLoading = false; } } @@ -49,10 +57,14 @@ export default class History extends Vue { if (!await this.$bvModal.msgBoxConfirm(entry.labels.confirm)) return; + this.reverting = entry; + try { - this.client.revertHistoryEntry({ id: entry.id }); + await this.client.revertHistoryEntry({ id: entry.id }); } catch (err) { showErrorToast(this, "fm-history-error", "Error loading history", err); + } finally { + this.reverting = null; } } diff --git a/frontend/src/map/history/history.vue b/frontend/src/map/history/history.vue index 9799e028..9a8ac097 100644 --- a/frontend/src/map/history/history.vue +++ b/frontend/src/map/history/history.vue @@ -1,6 +1,21 @@ - +

Here you can inspect and revert the last 50 changes to the map.

- +
+ +
+ Date @@ -19,7 +34,10 @@ - {{entry.labels.button}} + + + {{entry.labels.button}} + diff --git a/frontend/src/map/line-info/line-info.ts b/frontend/src/map/line-info/line-info.ts index 752b630a..3c8d2591 100644 --- a/frontend/src/map/line-info/line-info.ts +++ b/frontend/src/map/line-info/line-info.ts @@ -31,6 +31,7 @@ export default class LineInfo extends Vue { @Prop({ type: Boolean, default: false }) showBackButton!: boolean; isDeleting = false; + isExporting = false; showElevationPlot = false; isMoving = false; @@ -45,6 +46,7 @@ export default class LineInfo extends Vue { return; this.isDeleting = true; + try { await this.client.deleteLine({ id: this.lineId }); } catch (err) { @@ -64,12 +66,15 @@ export default class LineInfo extends Vue { return; this.$bvToast.hide("fm-line-info-export-error"); + this.isExporting = true; try { const exported = await this.client.exportLine({ id: this.line.id, format }); saveAs(new Blob([exported], { type: "application/gpx+xml" }), `${this.line.name}.gpx`); } catch(err) { showErrorToast(this, "fm-line-info-export-error", "Error exporting line", err); + } finally { + this.isExporting = false; } } diff --git a/frontend/src/map/line-info/line-info.vue b/frontend/src/map/line-info/line-info.vue index 33a21d67..3da61b8f 100644 --- a/frontend/src/map/line-info/line-info.vue +++ b/frontend/src/map/line-info/line-info.vue @@ -36,7 +36,12 @@ - + + + { - Vue.set(this.isDeleting, view.id, true); this.$bvToast.hide(`fm-save-view-error-${view.id}`); try { if (!await this.$bvModal.msgBoxConfirm(`Do you really want to delete the view “${view.name}”?`)) return; + Vue.set(this.isDeleting, view.id, true); + await this.client.deleteView({ id: view.id }); } catch (err) { showErrorToast(this, `fm-save-view-error-${view.id}`, `Error deleting view “${view.name}”`, err); diff --git a/frontend/src/map/marker-info/marker-info.ts b/frontend/src/map/marker-info/marker-info.ts index 9a96f121..b470b16a 100644 --- a/frontend/src/map/marker-info/marker-info.ts +++ b/frontend/src/map/marker-info/marker-info.ts @@ -48,6 +48,7 @@ export default class MarkerInfo extends Vue { return; this.isDeleting = true; + try { await this.client.deleteMarker({ id: this.markerId }); } catch (err) { diff --git a/frontend/src/map/multiple-info/multiple-info.ts b/frontend/src/map/multiple-info/multiple-info.ts index a5f9bb3f..21eed7e7 100644 --- a/frontend/src/map/multiple-info/multiple-info.ts +++ b/frontend/src/map/multiple-info/multiple-info.ts @@ -75,6 +75,7 @@ export default class MultipleInfo extends Vue { return; this.isDeleting = true; + try { for (const object of this.objects) { if (isMarker(object)) diff --git a/frontend/src/map/pad-settings/pad-settings.ts b/frontend/src/map/pad-settings/pad-settings.ts index 10336e80..e90fdd46 100644 --- a/frontend/src/map/pad-settings/pad-settings.ts +++ b/frontend/src/map/pad-settings/pad-settings.ts @@ -43,6 +43,7 @@ export default class PadSettings extends Vue { @Prop({ type: Boolean }) readonly isCreate?: boolean; isSaving = false; + isDeleting = false; deleteConfirmation = ""; padData: PadDataCreate | PadDataUpdate = null as any; @@ -88,23 +89,6 @@ export default class PadSettings extends Vue { this.padDataValidationProvider?.validate({ ...padData }); } - /* - $scope.copyPadId = fmUtils.generateRandomPadId(); - $scope.copyPad = function() { - socket.copyPad({ toId: $scope.copyPadId }, function(err) { - if(err) { - $scope.dialogError = err; - return; - } - - $scope.closeDialog(); - var url = $scope.urlPrefix + $scope.copyPadId; - $scope.showMessage("success", "The pad has been copied to", [ { label: url, url: url } ]); - $scope.copyPadId = fmUtils.generateRandomPadId(); - }); - }; - */ - async save(): Promise { this.isSaving = true; this.$bvToast.hide("fm-pad-settings-error"); @@ -112,7 +96,6 @@ export default class PadSettings extends Vue { try { if(this.isCreate) await this.client.createPad(this.padData as PadDataCreate); - // this.client.updateBbox(leafletToFmBbox(map.map.getBounds(), map.map.getZoom())); else await this.client.editPad(this.padData); @@ -129,19 +112,20 @@ export default class PadSettings extends Vue { } async deletePad(): Promise { - this.isSaving = true; this.$bvToast.hide("fm-pad-settings-error"); - try { - if (!await this.$bvModal.msgBoxConfirm(`Are you sure you want to delete the map “${this.padData.name}”? Deleted maps cannot be restored!`)) + if (!await this.$bvModal.msgBoxConfirm(`Are you sure you want to delete the map “${this.padData.name}”? Deleted maps cannot be restored!`)) return; + this.isDeleting = true; + + try { await this.client.deletePad(); this.$bvModal.hide(this.id); } catch (err) { showErrorToast(this, "fm-pad-settings-error", "Error deleting map", err); } finally { - this.isSaving = false; + this.isDeleting = false; } }; } diff --git a/frontend/src/map/pad-settings/pad-settings.vue b/frontend/src/map/pad-settings/pad-settings.vue index 2206a396..883afb23 100644 --- a/frontend/src/map/pad-settings/pad-settings.vue +++ b/frontend/src/map/pad-settings/pad-settings.vue @@ -4,6 +4,7 @@ dialog-class="fm-pad-settings" :no-cancel="noCancel" :is-saving="isSaving" + :is-busy="isDeleting" :is-create="isCreate" :is-modified="isModified" @submit="save" @@ -105,7 +106,10 @@ - Delete map + + + Delete map +