Add a way to report a bug, close #34

This commit is contained in:
Lucas Verney 2018-08-25 18:15:19 +02:00
parent 6f8b3ada2c
commit b8ae8e9fa3
10 changed files with 135 additions and 13 deletions

View File

@ -6,6 +6,8 @@ locale = json.loads(sys.stdin.read())
nested_json = {} nested_json = {}
for key, value in locale.items(): for key, value in locale.items():
if not value:
continue
split_key = key.split('.') split_key = key.split('.')
d = nested_json d = nested_json
for key2 in split_key[:-1]: for key2 in split_key[:-1]:

View File

@ -41,6 +41,9 @@
<v-list-tile @click="goToSettings"> <v-list-tile @click="goToSettings">
<v-list-tile-title>{{ $t("menu.Settings") }}</v-list-tile-title> <v-list-tile-title>{{ $t("menu.Settings") }}</v-list-tile-title>
</v-list-tile> </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-list>
</v-menu> </v-menu>
<v-btn icon role="button" :aria-label="$t('buttons.back')" v-else @click="goBack"> <v-btn icon role="button" :aria-label="$t('buttons.back')" v-else @click="goBack">
@ -53,6 +56,7 @@
<v-content> <v-content>
<ReportErrorModal v-model="hasReportError"></ReportErrorModal> <ReportErrorModal v-model="hasReportError"></ReportErrorModal>
<ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal> <ShareMapViewModal v-model="isShareMapViewModalShown"></ShareMapViewModal>
<ReportIssueModal v-model="isReportIssueModalShown"></ReportIssueModal>
<router-view></router-view> <router-view></router-view>
</v-content> </v-content>
</v-app> </v-app>
@ -66,11 +70,13 @@ import moment from 'moment';
import { DELAY_BETWEEN_API_BATCH_REQUESTS, VERSION } from '@/constants'; import { DELAY_BETWEEN_API_BATCH_REQUESTS, VERSION } from '@/constants';
import ReportErrorModal from '@/components/ReportErrorModal.vue'; import ReportErrorModal from '@/components/ReportErrorModal.vue';
import ReportIssueModal from '@/components/ReportIssueModal.vue';
import ShareMapViewModal from '@/components/ShareMapViewModal.vue'; import ShareMapViewModal from '@/components/ShareMapViewModal.vue';
export default { export default {
components: { components: {
ReportErrorModal, ReportErrorModal,
ReportIssueModal,
ShareMapViewModal, ShareMapViewModal,
}, },
computed: { computed: {
@ -90,6 +96,7 @@ export default {
data() { data() {
return { return {
hasReportError: false, hasReportError: false,
isReportIssueModalShown: false,
isSendingReports: false, isSendingReports: false,
isShareMapViewModalShown: false, isShareMapViewModalShown: false,
title: "Cycl'Assist", title: "Cycl'Assist",

View File

@ -1,5 +1,5 @@
<template> <template>
<v-dialog v-model="isModalShown" max-width="290"> <v-dialog v-model="isModalShown" :max-width="maxWidth">
<slot></slot> <slot></slot>
</v-dialog> </v-dialog>
</template> </template>
@ -36,6 +36,10 @@ export default {
window.addEventListener('keydown', this.hideModalOnEsc); window.addEventListener('keydown', this.hideModalOnEsc);
}, },
props: { props: {
maxWidth: {
type: Number,
default: 290,
},
value: Boolean, value: Boolean,
}, },
}; };

View 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>

View File

@ -115,3 +115,6 @@ export const DELAY_BETWEEN_API_BATCH_REQUESTS = 1000;
// A vibration sequence for report alarms // A vibration sequence for report alarms
export const REPORT_ALARM_VIBRATION_SEQUENCE = [500]; export const REPORT_ALARM_VIBRATION_SEQUENCE = [500];
// Email address to send issues to
export const CONTACT_EMAIL_ADDRESS = 'phyks+cyclassist@phyks.me';

View File

@ -50,6 +50,7 @@
"About": "Help", "About": "Help",
"Settings": "Settings", "Settings": "Settings",
"exportGPX": "Export GPX", "exportGPX": "Export GPX",
"reportIssue": "Report an issue",
"shareMapView": "Share map view" "shareMapView": "Share map view"
}, },
"misc": { "misc": {
@ -57,8 +58,7 @@
"discard": "Discard", "discard": "Discard",
"ok": "OK", "ok": "OK",
"or": "or", "or": "or",
"retry": "Retry", "retry": "Retry"
"spaceBeforeDoublePunctuations": ""
}, },
"permissions": { "permissions": {
"geolocation": "Geolocation", "geolocation": "Geolocation",
@ -75,6 +75,12 @@
"unableToSendDescription": "There was a network issue preventing from sending the latest report.", "unableToSendDescription": "There was a network issue preventing from sending the latest report.",
"unableToSendTitle": "Unable to send latest report" "unableToSendTitle": "Unable to send latest report"
}, },
"reportIssueModal": {
"description": "Description",
"includeGPX": "Include the current GPS trace?",
"reportIssue": "Report an issue",
"send": "Send"
},
"reportLabels": { "reportLabels": {
"accident": "Accident", "accident": "Accident",
"accidentDescription": "Any accident on the road (automatically removed after one hour).", "accidentDescription": "Any accident on the road (automatically removed after one hour).",

View File

@ -3,7 +3,7 @@
"availableReportsTitle": "Les signalements disponibles pour l'instant sont :", "availableReportsTitle": "Les signalements disponibles pour l'instant sont :",
"lastReportAdded": "Dernier signalement ajout\u00e9 {fromNow}.", "lastReportAdded": "Dernier signalement ajout\u00e9 {fromNow}.",
"license": "Licence", "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.", "nbActiveReports": "Aucun signalement actif. | Un signalement actif. | {nbActiveReports} signalements actifs.",
"nbReports": "Aucun signalement. | Un signalement. | {nbReports} signalements.", "nbReports": "Aucun signalement. | Un signalement. | {nbReports} signalements.",
"stats": "Statistiques", "stats": "Statistiques",
@ -50,6 +50,7 @@
"About": "Aide", "About": "Aide",
"Settings": "Pr\u00e9f\u00e9rences", "Settings": "Pr\u00e9f\u00e9rences",
"exportGPX": "Exporter en GPX", "exportGPX": "Exporter en GPX",
"reportIssue": "Signaler un bug",
"shareMapView": "Partager" "shareMapView": "Partager"
}, },
"misc": { "misc": {
@ -57,8 +58,7 @@
"discard": "Annuler", "discard": "Annuler",
"ok": "OK", "ok": "OK",
"or": "ou", "or": "ou",
"retry": "R\u00e9essayer", "retry": "R\u00e9essayer"
"spaceBeforeDoublePunctuations": " "
}, },
"permissions": { "permissions": {
"geolocation": "G\u00e9olocalisation", "geolocation": "G\u00e9olocalisation",
@ -75,6 +75,12 @@
"unableToSendDescription": "Une erreur de r\u00e9seau emp\u00eache l'envoi du dernier signalement.", "unableToSendDescription": "Une erreur de r\u00e9seau emp\u00eache l'envoi du dernier signalement.",
"unableToSendTitle": "Impossible d'envoyer le 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": { "reportLabels": {
"accident": "Accident", "accident": "Accident",
"accidentDescription": "Un accident sur la route (automatiquement supprim\u00e9 apr\u00e8s une heure).", "accidentDescription": "Un accident sur la route (automatiquement supprim\u00e9 apr\u00e8s une heure).",

View File

@ -3,7 +3,7 @@
"availableReportsTitle": "Los senhalaments disponibles pel moment son :", "availableReportsTitle": "Los senhalaments disponibles pel moment son :",
"lastReportAdded": "Darri\u00e8ra senhalament ajustat {fromNow}.", "lastReportAdded": "Darri\u00e8ra senhalament ajustat {fromNow}.",
"license": "Lic\u00e9ncia", "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.", "nbActiveReports": "Cap de senhalament actiu. |\u00a0Un senhalament actiu. | {nbActiveReports} senhalaments actius.",
"nbReports": "Cap de senhalament. | Un senhalament. | {nbReports} senhalaments.", "nbReports": "Cap de senhalament. | Un senhalament. | {nbReports} senhalaments.",
"stats": "Estatisticas", "stats": "Estatisticas",
@ -57,8 +57,7 @@
"discard": "Anullar", "discard": "Anullar",
"ok": "D\u2019acc\u00f2rdi", "ok": "D\u2019acc\u00f2rdi",
"or": "o", "or": "o",
"retry": "Ensajar tornamai", "retry": "Ensajar tornamai"
"spaceBeforeDoublePunctuations": " "
}, },
"permissions": { "permissions": {
"geolocation": "Geolocalizacion", "geolocation": "Geolocalizacion",
@ -90,12 +89,9 @@
"potholeDescription": "Un trauc per la rota." "potholeDescription": "Un trauc per la rota."
}, },
"settings": { "settings": {
"autorotate": "",
"customTileServer": "Servidor de teulas personalizat", "customTileServer": "Servidor de teulas personalizat",
"customTileServerURL": "URL del servidor de teulas personalizat", "customTileServerURL": "URL del servidor de teulas personalizat",
"customTileServerURLHint": "Per exemple\u00a0: http://tile.thunderforest.com/cycle/{z}/{x}/{y}.png", "customTileServerURLHint": "Per exemple\u00a0: http://tile.thunderforest.com/cycle/{z}/{x}/{y}.png",
"defaultOrientationMode": "",
"fixedNorth": "",
"locale": "Lenga", "locale": "Lenga",
"skipOnboarding": "Passar l'introduccion", "skipOnboarding": "Passar l'introduccion",
"tileServer": "Servidor de teulas per la mapa" "tileServer": "Servidor de teulas per la mapa"

View File

@ -16,6 +16,7 @@ import VProgressCircular from 'vuetify/es5/components/VProgressCircular';
import VProgressLinear from 'vuetify/es5/components/VProgressLinear'; import VProgressLinear from 'vuetify/es5/components/VProgressLinear';
import VSelect from 'vuetify/es5/components/VSelect'; import VSelect from 'vuetify/es5/components/VSelect';
import VSwitch from 'vuetify/es5/components/VSwitch'; import VSwitch from 'vuetify/es5/components/VSwitch';
import VTextarea from 'vuetify/es5/components/VTextarea';
import VTextField from 'vuetify/es5/components/VTextField'; import VTextField from 'vuetify/es5/components/VTextField';
import VToolbar from 'vuetify/es5/components/VToolbar'; import VToolbar from 'vuetify/es5/components/VToolbar';
@ -37,6 +38,7 @@ Vue.use(Vuetify, {
VProgressLinear, VProgressLinear,
VSelect, VSelect,
VSwitch, VSwitch,
VTextarea,
VTextField, VTextField,
VToolbar, VToolbar,
}, },