Use dismissible alerts instead of dialogs to notify about errors
This commit is contained in:
parent
22c68454ec
commit
14e28694e0
@ -57,7 +57,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
<v-content>
|
<v-content>
|
||||||
<ReportErrorModal v-model="hasReportError"></ReportErrorModal>
|
<Alert :error="$t('reportDialog.unableToSendDescription')" :onDismiss="dismissError" v-if="hasReportError"></Alert>
|
||||||
<ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal>
|
<ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal>
|
||||||
<ReportIssueModal v-model="isReportIssueModalShown"></ReportIssueModal>
|
<ReportIssueModal v-model="isReportIssueModalShown"></ReportIssueModal>
|
||||||
<SearchModal v-model="isSearchModalShown"></SearchModal>
|
<SearchModal v-model="isSearchModalShown"></SearchModal>
|
||||||
@ -71,14 +71,14 @@ import runtime from 'serviceworker-webpack-plugin/lib/runtime';
|
|||||||
|
|
||||||
import { DELAY_BETWEEN_API_BATCH_REQUESTS } from '@/constants';
|
import { DELAY_BETWEEN_API_BATCH_REQUESTS } from '@/constants';
|
||||||
|
|
||||||
import ReportErrorModal from '@/components/ReportErrorModal.vue';
|
import Alert from '@/components/Alert.vue';
|
||||||
import ReportIssueModal from '@/components/ReportIssueModal.vue';
|
import ReportIssueModal from '@/components/ReportIssueModal.vue';
|
||||||
import SearchModal from '@/components/SearchModal.vue';
|
import SearchModal from '@/components/SearchModal.vue';
|
||||||
import ShareMapViewModal from '@/components/ShareMapViewModal.vue';
|
import ShareMapViewModal from '@/components/ShareMapViewModal.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ReportErrorModal,
|
Alert,
|
||||||
ReportIssueModal,
|
ReportIssueModal,
|
||||||
SearchModal,
|
SearchModal,
|
||||||
ShareMapViewModal,
|
ShareMapViewModal,
|
||||||
@ -111,6 +111,9 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
dismissError() {
|
||||||
|
this.hasReportError = false;
|
||||||
|
},
|
||||||
exportGPX() {
|
exportGPX() {
|
||||||
import('@/tools/exportGPX' /* webpackChunkName: "MapView" */).then((module) => {
|
import('@/tools/exportGPX' /* webpackChunkName: "MapView" */).then((module) => {
|
||||||
const activityName = this.$t('misc.activityName');
|
const activityName = this.$t('misc.activityName');
|
||||||
|
78
src/components/Alert.vue
Normal file
78
src/components/Alert.vue
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<div class="alert-wrapper">
|
||||||
|
<v-alert class="alert" type="error" v-model="showAlert" :dismissible="true" transition="slide-y-transition">
|
||||||
|
{{ error }}
|
||||||
|
<v-progress-linear
|
||||||
|
class="progress"
|
||||||
|
v-model="progressValue"
|
||||||
|
background-opacity="0"
|
||||||
|
color="rgba(0,0,0,0.3)"
|
||||||
|
></v-progress-linear>
|
||||||
|
</v-alert>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
beforeDestroy() {
|
||||||
|
this.clearTimer();
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
interval: null,
|
||||||
|
progressValue: 100,
|
||||||
|
showAlert: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clearTimer() {
|
||||||
|
if (this.interval !== null) {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.progressValue -= 4;
|
||||||
|
if (this.progressValue < 0) {
|
||||||
|
this.showAlert = false;
|
||||||
|
this.clearTimer();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
error: String,
|
||||||
|
onDismiss: Function,
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showAlert(newAlert) {
|
||||||
|
if (!newAlert && this.onDismiss) {
|
||||||
|
this.onDismiss();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.alert-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 0;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,43 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<p class="text-xs-center">{{ error }}</p>
|
|
||||||
<p class="text-xs-center">
|
|
||||||
<v-btn role="button" color="blue" dark @click="retryFunction">{{ $t('misc.retry') }}</v-btn>
|
|
||||||
</p>
|
|
||||||
<p>{{ $t('misc.or') }}</p>
|
|
||||||
<p>
|
|
||||||
<AddressInput
|
|
||||||
:label="$t('locationPicker.pickALocationManually')"
|
|
||||||
:onInput="onManualLocationPicker"
|
|
||||||
></AddressInput>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { DEFAULT_ZOOM } from '@/constants';
|
|
||||||
|
|
||||||
import AddressInput from '@/components/AddressInput.vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
AddressInput,
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onManualLocationPicker(value) {
|
|
||||||
this.$router.push({
|
|
||||||
name: 'SharedMap',
|
|
||||||
params: {
|
|
||||||
lat: value.latlng.lat,
|
|
||||||
lng: value.latlng.lng,
|
|
||||||
zoom: DEFAULT_ZOOM,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
error: String,
|
|
||||||
retryFunction: Function,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<ReportErrorModal v-model="hasError"></ReportErrorModal>
|
<Alert :error="$t('reportDialog.unableToSendDescription')" :onDismiss="dismissError" v-if="hasError"></Alert>
|
||||||
<v-bottom-sheet v-model="isActive" id="reportCardSheet">
|
<v-bottom-sheet v-model="isActive" id="reportCardSheet">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
import { REPORT_TYPES_ORDER } from '@/constants';
|
import { REPORT_TYPES_ORDER } from '@/constants';
|
||||||
import REPORT_TYPES from '@/report-types';
|
import REPORT_TYPES from '@/report-types';
|
||||||
|
|
||||||
import ReportErrorModal from '@/components/ReportErrorModal.vue';
|
import Alert from '@/components/Alert.vue';
|
||||||
import ReportTile from './ReportTile.vue';
|
import ReportTile from './ReportTile.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -33,7 +33,7 @@ export default {
|
|||||||
window.removeEventListener('keydown', this.hideReportDialogOnEsc);
|
window.removeEventListener('keydown', this.hideReportDialogOnEsc);
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ReportErrorModal,
|
Alert,
|
||||||
ReportTile,
|
ReportTile,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -57,6 +57,9 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
dismissError() {
|
||||||
|
this.hasError = false;
|
||||||
|
},
|
||||||
hideReportDialogOnEsc(event) {
|
hideReportDialogOnEsc(event) {
|
||||||
let isEscape = false;
|
let isEscape = false;
|
||||||
if ('key' in event) {
|
if ('key' in event) {
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Modal v-model="hasError">
|
|
||||||
<v-card>
|
|
||||||
<v-card-title class="subheading">{{ $t('reportDialog.unableToSendTitle') }}</v-card-title>
|
|
||||||
|
|
||||||
<v-card-text>{{ $t('reportDialog.unableToSendDescription') }} </v-card-text>
|
|
||||||
|
|
||||||
<v-card-actions>
|
|
||||||
<v-spacer></v-spacer>
|
|
||||||
|
|
||||||
<v-btn @click="hasError = false" large role="button">
|
|
||||||
{{ $t('misc.ok') }}
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-spacer></v-spacer>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Modal from '@/components/Modal.vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Modal,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hasError: {
|
|
||||||
get() {
|
|
||||||
return this.value;
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$emit('input', val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
value: Boolean,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
@ -2,6 +2,7 @@
|
|||||||
<v-container fluid fill-height class="no-padding">
|
<v-container fluid fill-height class="no-padding">
|
||||||
<v-layout row wrap fill-height>
|
<v-layout row wrap fill-height>
|
||||||
<ReportCard></ReportCard>
|
<ReportCard></ReportCard>
|
||||||
|
<Alert :error="error" v-if="error" :onDismiss="clearError"></Alert>
|
||||||
<v-flex xs12 fill-height v-if="mapCenter">
|
<v-flex xs12 fill-height v-if="mapCenter">
|
||||||
<Map
|
<Map
|
||||||
:accuracy="currentLocation.hdop"
|
:accuracy="currentLocation.hdop"
|
||||||
@ -36,10 +37,6 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
<ReportDialog v-model="isReportDialogVisible" :latLng="reportLatLng" :onHide="resetReportLatLng"></ReportDialog>
|
<ReportDialog v-model="isReportDialogVisible" :latLng="reportLatLng" :onHide="resetReportLatLng"></ReportDialog>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
<v-flex xs12 sm6 offset-sm3 md4 offset-md4 fill-height v-else class="pa-3">
|
|
||||||
<LocationError :error="error" :retryFunction="initializePositionWatching" v-if="error"></LocationError>
|
|
||||||
<p class="text-xs-center" v-else>{{ $t('geolocation.fetching') }}</p>
|
|
||||||
</v-flex>
|
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
@ -47,7 +44,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import NoSleep from 'nosleep.js';
|
import NoSleep from 'nosleep.js';
|
||||||
|
|
||||||
import LocationError from '@/components/LocationError.vue';
|
import Alert from '@/components/Alert.vue';
|
||||||
import Map from '@/components/Map.vue';
|
import Map from '@/components/Map.vue';
|
||||||
import ReportCard from '@/components/ReportCard.vue';
|
import ReportCard from '@/components/ReportCard.vue';
|
||||||
import ReportDialog from '@/components/ReportDialog/index.vue';
|
import ReportDialog from '@/components/ReportDialog/index.vue';
|
||||||
@ -82,7 +79,7 @@ export default {
|
|||||||
this.$store.dispatch('hideReportDetails');
|
this.$store.dispatch('hideReportDetails');
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
LocationError,
|
Alert,
|
||||||
Map,
|
Map,
|
||||||
ReportCard,
|
ReportCard,
|
||||||
ReportDialog,
|
ReportDialog,
|
||||||
@ -181,6 +178,9 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
clearError() {
|
||||||
|
store.dispatch('setLocationError', { error: null });
|
||||||
|
},
|
||||||
createNotification() {
|
createNotification() {
|
||||||
const $t = this.$t.bind(this);
|
const $t = this.$t.bind(this);
|
||||||
this.notification = new Notification(
|
this.notification = new Notification(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuetify from 'vuetify/es5/components/Vuetify';
|
import Vuetify from 'vuetify/es5/components/Vuetify';
|
||||||
|
import VAlert from 'vuetify/es5/components/VAlert';
|
||||||
import VApp from 'vuetify/es5/components/VApp';
|
import VApp from 'vuetify/es5/components/VApp';
|
||||||
import VBadge from 'vuetify/es5/components/VBadge';
|
import VBadge from 'vuetify/es5/components/VBadge';
|
||||||
import VBottomSheet from 'vuetify/es5/components/VBottomSheet';
|
import VBottomSheet from 'vuetify/es5/components/VBottomSheet';
|
||||||
@ -22,6 +23,7 @@ import VToolbar from 'vuetify/es5/components/VToolbar';
|
|||||||
|
|
||||||
Vue.use(Vuetify, {
|
Vue.use(Vuetify, {
|
||||||
components: {
|
components: {
|
||||||
|
VAlert,
|
||||||
VApp,
|
VApp,
|
||||||
VBadge,
|
VBadge,
|
||||||
VBottomSheet,
|
VBottomSheet,
|
||||||
|
Loading…
Reference in New Issue
Block a user