Use dismissible alerts instead of dialogs to notify about errors
This commit is contained in:
parent
22c68454ec
commit
14e28694e0
@ -57,7 +57,7 @@
|
||||
</div>
|
||||
</v-toolbar>
|
||||
<v-content>
|
||||
<ReportErrorModal v-model="hasReportError"></ReportErrorModal>
|
||||
<Alert :error="$t('reportDialog.unableToSendDescription')" :onDismiss="dismissError" v-if="hasReportError"></Alert>
|
||||
<ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal>
|
||||
<ReportIssueModal v-model="isReportIssueModalShown"></ReportIssueModal>
|
||||
<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 ReportErrorModal from '@/components/ReportErrorModal.vue';
|
||||
import Alert from '@/components/Alert.vue';
|
||||
import ReportIssueModal from '@/components/ReportIssueModal.vue';
|
||||
import SearchModal from '@/components/SearchModal.vue';
|
||||
import ShareMapViewModal from '@/components/ShareMapViewModal.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ReportErrorModal,
|
||||
Alert,
|
||||
ReportIssueModal,
|
||||
SearchModal,
|
||||
ShareMapViewModal,
|
||||
@ -111,6 +111,9 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
dismissError() {
|
||||
this.hasReportError = false;
|
||||
},
|
||||
exportGPX() {
|
||||
import('@/tools/exportGPX' /* webpackChunkName: "MapView" */).then((module) => {
|
||||
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>
|
||||
<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-card>
|
||||
<v-container fluid>
|
||||
@ -25,7 +25,7 @@
|
||||
import { REPORT_TYPES_ORDER } from '@/constants';
|
||||
import REPORT_TYPES from '@/report-types';
|
||||
|
||||
import ReportErrorModal from '@/components/ReportErrorModal.vue';
|
||||
import Alert from '@/components/Alert.vue';
|
||||
import ReportTile from './ReportTile.vue';
|
||||
|
||||
export default {
|
||||
@ -33,7 +33,7 @@ export default {
|
||||
window.removeEventListener('keydown', this.hideReportDialogOnEsc);
|
||||
},
|
||||
components: {
|
||||
ReportErrorModal,
|
||||
Alert,
|
||||
ReportTile,
|
||||
},
|
||||
computed: {
|
||||
@ -57,6 +57,9 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
dismissError() {
|
||||
this.hasError = false;
|
||||
},
|
||||
hideReportDialogOnEsc(event) {
|
||||
let isEscape = false;
|
||||
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-layout row wrap fill-height>
|
||||
<ReportCard></ReportCard>
|
||||
<Alert :error="error" v-if="error" :onDismiss="clearError"></Alert>
|
||||
<v-flex xs12 fill-height v-if="mapCenter">
|
||||
<Map
|
||||
:accuracy="currentLocation.hdop"
|
||||
@ -36,10 +37,6 @@
|
||||
</v-btn>
|
||||
<ReportDialog v-model="isReportDialogVisible" :latLng="reportLatLng" :onHide="resetReportLatLng"></ReportDialog>
|
||||
</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-container>
|
||||
</template>
|
||||
@ -47,7 +44,7 @@
|
||||
<script>
|
||||
import NoSleep from 'nosleep.js';
|
||||
|
||||
import LocationError from '@/components/LocationError.vue';
|
||||
import Alert from '@/components/Alert.vue';
|
||||
import Map from '@/components/Map.vue';
|
||||
import ReportCard from '@/components/ReportCard.vue';
|
||||
import ReportDialog from '@/components/ReportDialog/index.vue';
|
||||
@ -82,7 +79,7 @@ export default {
|
||||
this.$store.dispatch('hideReportDetails');
|
||||
},
|
||||
components: {
|
||||
LocationError,
|
||||
Alert,
|
||||
Map,
|
||||
ReportCard,
|
||||
ReportDialog,
|
||||
@ -181,6 +178,9 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
clearError() {
|
||||
store.dispatch('setLocationError', { error: null });
|
||||
},
|
||||
createNotification() {
|
||||
const $t = this.$t.bind(this);
|
||||
this.notification = new Notification(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify/es5/components/Vuetify';
|
||||
import VAlert from 'vuetify/es5/components/VAlert';
|
||||
import VApp from 'vuetify/es5/components/VApp';
|
||||
import VBadge from 'vuetify/es5/components/VBadge';
|
||||
import VBottomSheet from 'vuetify/es5/components/VBottomSheet';
|
||||
@ -22,6 +23,7 @@ import VToolbar from 'vuetify/es5/components/VToolbar';
|
||||
|
||||
Vue.use(Vuetify, {
|
||||
components: {
|
||||
VAlert,
|
||||
VApp,
|
||||
VBadge,
|
||||
VBottomSheet,
|
||||
|
Loading…
Reference in New Issue
Block a user