Add a way to report a bug, close #34
This commit is contained in:
parent
6f8b3ada2c
commit
b8ae8e9fa3
@ -6,6 +6,8 @@ locale = json.loads(sys.stdin.read())
|
||||
|
||||
nested_json = {}
|
||||
for key, value in locale.items():
|
||||
if not value:
|
||||
continue
|
||||
split_key = key.split('.')
|
||||
d = nested_json
|
||||
for key2 in split_key[:-1]:
|
||||
|
@ -41,6 +41,9 @@
|
||||
<v-list-tile @click="goToSettings">
|
||||
<v-list-tile-title>{{ $t("menu.Settings") }}</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
<v-list-tile @click="isReportIssueModalShown = true">
|
||||
<v-list-tile-title>{{ $t("menu.reportIssue") }}</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-btn icon role="button" :aria-label="$t('buttons.back')" v-else @click="goBack">
|
||||
@ -53,6 +56,7 @@
|
||||
<v-content>
|
||||
<ReportErrorModal v-model="hasReportError"></ReportErrorModal>
|
||||
<ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal>
|
||||
<ReportIssueModal v-model="isReportIssueModalShown"></ReportIssueModal>
|
||||
<router-view></router-view>
|
||||
</v-content>
|
||||
</v-app>
|
||||
@ -66,11 +70,13 @@ import moment from 'moment';
|
||||
import { DELAY_BETWEEN_API_BATCH_REQUESTS, VERSION } from '@/constants';
|
||||
|
||||
import ReportErrorModal from '@/components/ReportErrorModal.vue';
|
||||
import ReportIssueModal from '@/components/ReportIssueModal.vue';
|
||||
import ShareMapViewModal from '@/components/ShareMapViewModal.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ReportErrorModal,
|
||||
ReportIssueModal,
|
||||
ShareMapViewModal,
|
||||
},
|
||||
computed: {
|
||||
@ -90,6 +96,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
hasReportError: false,
|
||||
isReportIssueModalShown: false,
|
||||
isSendingReports: false,
|
||||
isShareMapViewModalShown: false,
|
||||
title: "Cycl'Assist",
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-dialog v-model="isModalShown" max-width="290">
|
||||
<v-dialog v-model="isModalShown" :max-width="maxWidth">
|
||||
<slot></slot>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@ -36,6 +36,10 @@ export default {
|
||||
window.addEventListener('keydown', this.hideModalOnEsc);
|
||||
},
|
||||
props: {
|
||||
maxWidth: {
|
||||
type: Number,
|
||||
default: 290,
|
||||
},
|
||||
value: Boolean,
|
||||
},
|
||||
};
|
||||
|
96
src/components/ReportIssueModal.vue
Normal file
96
src/components/ReportIssueModal.vue
Normal file
@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<Modal v-model="isActive" :maxWidth="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('reportIssueModal.reportIssue') }}</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-textarea :label="$t('reportIssueModal.description')" v-model="description"></v-textarea>
|
||||
<v-checkbox v-if="isIncludeGPXVisible" :label="$t('reportIssueModal.includeGPX')" v-model="shouldIncludeGPX"></v-checkbox>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn
|
||||
@click="sendEmail"
|
||||
color="green darken-1"
|
||||
:dark="!!description"
|
||||
:disabled="!description"
|
||||
:href="mailtoLink"
|
||||
large
|
||||
role="button"
|
||||
>
|
||||
{{ $t('reportIssueModal.send') }} <v-icon class="ml-1">email</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
{{ $t('misc.or') }}
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn
|
||||
color="grey"
|
||||
@click="isActive = false"
|
||||
dark
|
||||
large
|
||||
role="button"
|
||||
>
|
||||
{{ $t('buttons.close') }}
|
||||
</v-btn>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CONTACT_EMAIL_ADDRESS } from '@/constants';
|
||||
|
||||
import Modal from '@/components/Modal.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
},
|
||||
computed: {
|
||||
isActive: {
|
||||
get() {
|
||||
return this.value;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val);
|
||||
},
|
||||
},
|
||||
isIncludeGPXVisible() {
|
||||
return this.$store.state.location.gpx.length > 0;
|
||||
},
|
||||
mailtoLink() {
|
||||
let mailText = this.description;
|
||||
if (this.shouldIncludeGPX) {
|
||||
mailText += `\n\nGPX trace: ${JSON.stringify(this.$store.state.location.gpx)}.`;
|
||||
}
|
||||
return `mailto:${CONTACT_EMAIL_ADDRESS}?subject=Issue%20with%20Cyclassist&body=${encodeURIComponent(mailText)}`;
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
description: null,
|
||||
shouldIncludeGPX: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
sendEmail() {
|
||||
// Close modal
|
||||
this.isActive = false;
|
||||
// Reset description and checkbox
|
||||
this.description = null;
|
||||
this.shouldIncludeGPX = false;
|
||||
},
|
||||
},
|
||||
props: {
|
||||
value: Boolean,
|
||||
},
|
||||
};
|
||||
</script>
|
@ -115,3 +115,6 @@ export const DELAY_BETWEEN_API_BATCH_REQUESTS = 1000;
|
||||
|
||||
// A vibration sequence for report alarms
|
||||
export const REPORT_ALARM_VIBRATION_SEQUENCE = [500];
|
||||
|
||||
// Email address to send issues to
|
||||
export const CONTACT_EMAIL_ADDRESS = 'phyks+cyclassist@phyks.me';
|
||||
|
@ -50,6 +50,7 @@
|
||||
"About": "Help",
|
||||
"Settings": "Settings",
|
||||
"exportGPX": "Export GPX",
|
||||
"reportIssue": "Report an issue",
|
||||
"shareMapView": "Share map view"
|
||||
},
|
||||
"misc": {
|
||||
@ -57,8 +58,7 @@
|
||||
"discard": "Discard",
|
||||
"ok": "OK",
|
||||
"or": "or",
|
||||
"retry": "Retry",
|
||||
"spaceBeforeDoublePunctuations": ""
|
||||
"retry": "Retry"
|
||||
},
|
||||
"permissions": {
|
||||
"geolocation": "Geolocation",
|
||||
@ -75,6 +75,12 @@
|
||||
"unableToSendDescription": "There was a network issue preventing from sending the latest report.",
|
||||
"unableToSendTitle": "Unable to send latest report"
|
||||
},
|
||||
"reportIssueModal": {
|
||||
"description": "Description",
|
||||
"includeGPX": "Include the current GPS trace?",
|
||||
"reportIssue": "Report an issue",
|
||||
"send": "Send"
|
||||
},
|
||||
"reportLabels": {
|
||||
"accident": "Accident",
|
||||
"accidentDescription": "Any accident on the road (automatically removed after one hour).",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"availableReportsTitle": "Les signalements disponibles pour l'instant sont :",
|
||||
"lastReportAdded": "Dernier signalement ajout\u00e9 {fromNow}.",
|
||||
"license": "Licence",
|
||||
"licenseDescription": "Le code source est sous <a href=\"https://opensource.org/licenses/MIT\">licence MIT</a> (<a href=\"https://framagit.org/phyks/cyclassist\">code source</a>). Les ic\u00f4nes sont bas\u00e9es sur des travaux de Wikimedia, Vecteezy, Pixabay ou Flaticon. Les sons sont bas\u00e9s sur des \u0153uvres sous CC0 de <a href=\"https://freesound.org/\">freesound.org</a>. Les tuiles de fond de carte proviennent de chez <a href=\"https://carto.com/location-data-services/basemaps/\">Carto.com</a> ou <a href=\"http://thunderforest.com/\">Thunderforest</a>, gr\u00e2ce aux <a href=\"https://www.openstreetmap.org/copyright\">contributeurs OpenStreetMap</a> et \u00e0 <a href=\"http://openlayers.org/\">OpenLayers</a>. Les signalements sont disponibles sous <a href=\"https://opendatacommons.org/licenses/odbl/\">licence ODbL</a>. La saisie manuelle de la position utilise l'excellente API de <a href=\"https://adresse.data.gouv.fr\">adresse.data.gouv.fr</a>.",
|
||||
"licenseDescription": "Le code source est sous <a href=\"https://opensource.org/licenses/MIT\">licence MIT</a> (<a href=\"https://framagit.org/phyks/cyclassist\">code source</a>). Les ic\u00f4nes sont bas\u00e9es sur des travaux de Wikimedia, Vecteezy, Pixabay ou Flaticon. Les sons sont bas\u00e9s sur des \u0153uvres sous CC0 de <a href=\"https://freesound.org/\">freesound.org</a>. Les tuiles de fond de carte proviennent de chez <a href=\"https://carto.com/location-data-services/basemaps/\">Carto.com</a> ou <a href=\"http://thunderforest.com/\">Thunderforest</a>, gr\u00e2ce aux <a href=\"https://www.openstreetmap.org/copyright\">contributeurs OpenStreetMap</a> et \u00e0 <a href=\"http://leafletjs.com/\">Leaflet</a>. Les signalements sont disponibles sous <a href=\"https://opendatacommons.org/licenses/odbl/\">licence ODbL</a>. La saisie manuelle de la position utilise l'excellente API de <a href=\"https://adresse.data.gouv.fr\">adresse.data.gouv.fr</a>.",
|
||||
"nbActiveReports": "Aucun signalement actif. | Un signalement actif. | {nbActiveReports} signalements actifs.",
|
||||
"nbReports": "Aucun signalement. | Un signalement. | {nbReports} signalements.",
|
||||
"stats": "Statistiques",
|
||||
@ -50,6 +50,7 @@
|
||||
"About": "Aide",
|
||||
"Settings": "Pr\u00e9f\u00e9rences",
|
||||
"exportGPX": "Exporter en GPX",
|
||||
"reportIssue": "Signaler un bug",
|
||||
"shareMapView": "Partager"
|
||||
},
|
||||
"misc": {
|
||||
@ -57,8 +58,7 @@
|
||||
"discard": "Annuler",
|
||||
"ok": "OK",
|
||||
"or": "ou",
|
||||
"retry": "R\u00e9essayer",
|
||||
"spaceBeforeDoublePunctuations": " "
|
||||
"retry": "R\u00e9essayer"
|
||||
},
|
||||
"permissions": {
|
||||
"geolocation": "G\u00e9olocalisation",
|
||||
@ -75,6 +75,12 @@
|
||||
"unableToSendDescription": "Une erreur de r\u00e9seau emp\u00eache l'envoi du dernier signalement.",
|
||||
"unableToSendTitle": "Impossible d'envoyer le dernier signalement"
|
||||
},
|
||||
"reportIssueModal": {
|
||||
"description": "Description",
|
||||
"includeGPX": "Inclure la trace GPS courante",
|
||||
"reportIssue": "Signaler un bug",
|
||||
"send": "Envoyer"
|
||||
},
|
||||
"reportLabels": {
|
||||
"accident": "Accident",
|
||||
"accidentDescription": "Un accident sur la route (automatiquement supprim\u00e9 apr\u00e8s une heure).",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"availableReportsTitle": "Los senhalaments disponibles pel moment son :",
|
||||
"lastReportAdded": "Darri\u00e8ra senhalament ajustat {fromNow}.",
|
||||
"license": "Lic\u00e9ncia",
|
||||
"licenseDescription": "It is released under an <a href=\"https://opensource.org/licenses/MIT\">MIT license</a> (<a href=\"https://framagit.org/phyks/cyclassist\">source code</a>). Icons are based on creations from Wikimedia, Vecteezy, Pixabay or Flaticon. Sounds are based on CC0 works from <a href=\"https://freesound.org/\">freesound.org</a>. The map background is using tiles from <a href=\"https://carto.com/location-data-services/basemaps/\">Carto.com</a> or <a href=\"http://thunderforest.com/\">Thunderforest</a>, thanks to <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap contributors</a> and <a href=\"http://leafletjs.com/\">Leaflet</a>. Collected reports are available under <a href=\"https://opendatacommons.org/licenses/odbl/\">ODbL license</a>. Manual location picking uses the awesome API from <a href=\"https://adresse.data.gouv.fr\">adresse.data.gouv.fr</a>.",
|
||||
"licenseDescription": "Lo c\u00f2di font es jos <a href=\"https://opensource.org/licenses/MIT\">lic\u00e9ncia MIT</a> (<a href=\"https://framagit.org/phyks/cyclassist\">c\u00f2di font</a>). Las ic\u00f2nas son basadas sus d'\u00f2bras de Wikimedia, Vecteezy, Pixabay o Flaticon. Las teulas de fons venon <a href=\"https://carto.com/location-data-services/basemaps/\">Carto.com</a> o <a href=\"http://thunderforest.com/\">Thunderforest</a>, gr\u00e0cia als <a href=\"https://www.openstreetmap.org/copyright\">contributors OpenStreetMap</a> e a <a href=\"http://leafletjs.com/\">Leaflet</a>. Los senhalaments son disponibles jos <a href=\"https://opendatacommons.org/licenses/odbl/\">lic\u00e9ncia ODbL</a>. La sasida manuala de la posicion utiliza l'excellenta API de <a href=\"https://adresse.data.gouv.fr\">adresse.data.gouv.fr</a>.",
|
||||
"nbActiveReports": "Cap de senhalament actiu. |\u00a0Un senhalament actiu. | {nbActiveReports} senhalaments actius.",
|
||||
"nbReports": "Cap de senhalament. | Un senhalament. | {nbReports} senhalaments.",
|
||||
"stats": "Estatisticas",
|
||||
@ -57,8 +57,7 @@
|
||||
"discard": "Anullar",
|
||||
"ok": "D\u2019acc\u00f2rdi",
|
||||
"or": "o",
|
||||
"retry": "Ensajar tornamai",
|
||||
"spaceBeforeDoublePunctuations": " "
|
||||
"retry": "Ensajar tornamai"
|
||||
},
|
||||
"permissions": {
|
||||
"geolocation": "Geolocalizacion",
|
||||
@ -90,12 +89,9 @@
|
||||
"potholeDescription": "Un trauc per la rota."
|
||||
},
|
||||
"settings": {
|
||||
"autorotate": "",
|
||||
"customTileServer": "Servidor de teulas personalizat",
|
||||
"customTileServerURL": "URL del servidor de teulas personalizat",
|
||||
"customTileServerURLHint": "Per exemple\u00a0: http://tile.thunderforest.com/cycle/{z}/{x}/{y}.png",
|
||||
"defaultOrientationMode": "",
|
||||
"fixedNorth": "",
|
||||
"locale": "Lenga",
|
||||
"skipOnboarding": "Passar l'introduccion",
|
||||
"tileServer": "Servidor de teulas per la mapa"
|
||||
|
@ -16,6 +16,7 @@ import VProgressCircular from 'vuetify/es5/components/VProgressCircular';
|
||||
import VProgressLinear from 'vuetify/es5/components/VProgressLinear';
|
||||
import VSelect from 'vuetify/es5/components/VSelect';
|
||||
import VSwitch from 'vuetify/es5/components/VSwitch';
|
||||
import VTextarea from 'vuetify/es5/components/VTextarea';
|
||||
import VTextField from 'vuetify/es5/components/VTextField';
|
||||
import VToolbar from 'vuetify/es5/components/VToolbar';
|
||||
|
||||
@ -37,6 +38,7 @@ Vue.use(Vuetify, {
|
||||
VProgressLinear,
|
||||
VSelect,
|
||||
VSwitch,
|
||||
VTextarea,
|
||||
VTextField,
|
||||
VToolbar,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user