From 867f9e9b832e3bd54c04801fef63a11543e8f3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jovan=20Kruni=C4=87?= Date: Thu, 21 Oct 2021 06:47:40 +0000 Subject: [PATCH] feat: add feedback module --- package-lock.json | 131 ++++++++--------- package.json | 4 +- src/app/_helpers/fake-backend.interceptor.ts | 1 + src/app/app.module.ts | 7 +- .../modules/config/config.provider.spec.ts | 1 + src/app/modules/data/data.provider.ts | 10 ++ .../data/debug-data-collector.service.ts | 68 +++++++++ .../feedback/feedback-page.component.ts | 139 ++++++++++++++++++ src/app/modules/feedback/feedback-page.html | 100 +++++++++++++ src/app/modules/feedback/feedback-page.scss | 6 + src/app/modules/feedback/feedback.module.ts | 42 ++++++ src/assets/i18n/de.json | 40 ++++- src/assets/i18n/en.json | 40 ++++- 13 files changed, 509 insertions(+), 80 deletions(-) create mode 100644 src/app/modules/data/debug-data-collector.service.ts create mode 100644 src/app/modules/feedback/feedback-page.component.ts create mode 100644 src/app/modules/feedback/feedback-page.html create mode 100644 src/app/modules/feedback/feedback-page.scss create mode 100644 src/app/modules/feedback/feedback.module.ts diff --git a/package-lock.json b/package-lock.json index 1d93ba58..1d45f7ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3345,9 +3345,9 @@ "dev": true }, "@hapi/hoek": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", - "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", + "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" }, "@hapi/topo": { "version": "5.1.0", @@ -3668,9 +3668,9 @@ } }, "@krlwlfrt/async-pool": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.5.0.tgz", - "integrity": "sha512-ZwdRzVEQ89zKVsXFyM6mPwJ5NwaPwvGB5rN5VyJ7SFKBPtjZhzY2VBHLszdKC7f1lFvCXISDace6SE+O/M+4eg==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.7.0.tgz", + "integrity": "sha512-qQp9fJdPuSxhJ0aMWCJ8ZavG67GeB1ZoYfYsIooyipeXTWZ9U67uEm93Udvd6C6v1Wa6mvD8X5PBNTtth1x0LQ==" }, "@netflix/nerror": { "version": "1.1.3", @@ -3876,24 +3876,24 @@ } }, "@openstapps/api": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@openstapps/api/-/api-0.32.0.tgz", - "integrity": "sha512-udgKVJKqv6sAZLB0BBZZXx4fM3fxy/2fCqLEfo+bVFwnZHYlhwL12boUFku0NhcSXWyKOpJgAK/kSrGP7IC1tQ==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/@openstapps/api/-/api-0.35.0.tgz", + "integrity": "sha512-mZGYTN+MJouVld9gIVJD5/hLDkB9hLRamKPZywcu195kngmayIPz4AbliHd1A8Xbrp0xtyE/i/Xse/+FkQ7i/g==", "requires": { - "@krlwlfrt/async-pool": "0.5.0", - "@openstapps/core": "0.50.0", + "@krlwlfrt/async-pool": "0.7.0", + "@openstapps/core": "0.53.0", "@openstapps/core-tools": "0.25.0", "@openstapps/logger": "0.7.0", "@types/cli-progress": "3.9.2", "@types/express": "4.17.13", "@types/morgan": "1.9.3", - "@types/node": "14.17.14", + "@types/node": "14.17.27", "@types/traverse": "0.6.32", "@types/uuid": "8.3.1", "@types/wait-on": "5.3.1", "body-parser": "1.19.0", - "cli-progress": "3.9.0", - "commander": "7.2.0", + "cli-progress": "3.9.1", + "commander": "8.2.0", "express": "4.17.1", "fast-clone": "1.5.13", "got": "11.8.2", @@ -3902,43 +3902,18 @@ "morgan": "1.10.0", "traverse": "0.6.6", "uuid": "8.3.2", - "wait-on": "5.3.0" + "wait-on": "6.0.0" }, "dependencies": { - "@openstapps/core": { - "version": "0.50.0", - "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.50.0.tgz", - "integrity": "sha512-0g2YQF6j9j9Mhqsc6HkD+EbkGvjoXI9Q3+1U+B3FdSxE23ubA6Fp/DM17uN5/OvXrygjNXnU6oehwW80iKXVJw==", - "requires": { - "@openstapps/core-tools": "0.25.0", - "@types/geojson": "1.0.6", - "@types/json-patch": "0.0.30", - "@types/json-schema": "7.0.9", - "@types/node": "14.17.9", - "fast-clone": "1.5.13", - "fast-deep-equal": "3.1.3", - "http-status-codes": "2.1.4", - "json-patch": "0.7.0", - "json-schema": "0.3.0", - "ts-optchain": "0.1.8" - }, - "dependencies": { - "@types/node": { - "version": "14.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", - "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==" - } - } - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" - }, "@types/node": { - "version": "14.17.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.14.tgz", - "integrity": "sha512-rsAj2u8Xkqfc332iXV12SqIsjVi07H479bOP4q94NAcjzmAvapumEhuVIt53koEf7JFrpjgNKjBga5Pnn/GL8A==" + "version": "14.17.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz", + "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==" + }, + "commander": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.2.0.tgz", + "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA==" } } }, @@ -4066,9 +4041,9 @@ } }, "@openstapps/core": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.51.0.tgz", - "integrity": "sha512-OzO5zsUY3zLnk6X4G9K/6lkoi0z/AdNZBRVhP6nLiVKeB4Y15nMan0XQJqYa3qnTCDpCYvEMi6id7osfCXmlUg==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.53.0.tgz", + "integrity": "sha512-UglbAFLAh25uNIS3ZVJI3d9HaYJxfq41G1Rok2C0uk/bJU9V9KclK8iw+DegPlqgd9heLYD++oubA0xX38gvQw==", "requires": { "@openstapps/core-tools": "0.25.0", "@types/geojson": "1.0.6", @@ -6035,9 +6010,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "core-js": { - "version": "3.17.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.3.tgz", - "integrity": "sha512-lyvajs+wd8N1hXfzob1LdOCCHFU4bGMbqqmLn1Q4QlCpDqWPpGf+p0nj+LNrvDDG33j0hZXw2nsvvVpHysxyNw==" + "version": "3.18.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", + "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==" }, "has-flag": { "version": "3.0.0", @@ -6680,9 +6655,9 @@ } }, "cli-progress": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.9.0.tgz", - "integrity": "sha512-g7rLWfhAo/7pF+a/STFH/xPyosaL1zgADhI0OM83hl3c7S43iGvJWEAV2QuDOnQ8i6EMBj/u4+NTd0d5L+4JfA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.9.1.tgz", + "integrity": "sha512-AXxiCe2a0Lm0VN+9L0jzmfQSkcZm5EYspfqXKaSIQKqIk+0hnkZ3/v1E9B39mkD6vYhKih3c/RPsJBSwq9O99Q==", "requires": { "colors": "^1.1.2", "string-width": "^4.2.0" @@ -6894,7 +6869,8 @@ "commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true }, "comment-parser": { "version": "1.2.4", @@ -20511,9 +20487,9 @@ "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA==" }, "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -20522,11 +20498,6 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } - }, - "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==" } } }, @@ -20670,8 +20641,7 @@ "typescript": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==" }, "ua-parser-js": { "version": "0.7.28", @@ -20990,15 +20960,30 @@ "dev": true }, "wait-on": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", - "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", + "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==", "requires": { "axios": "^0.21.1", - "joi": "^17.3.0", + "joi": "^17.4.0", "lodash": "^4.17.21", "minimist": "^1.2.5", - "rxjs": "^6.6.3" + "rxjs": "^7.1.0" + }, + "dependencies": { + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "requires": { + "tslib": "~2.1.0" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } } }, "watchpack": { diff --git a/package.json b/package.json index 8ed61df0..e2c029f0 100644 --- a/package.json +++ b/package.json @@ -62,9 +62,9 @@ "@ionic/storage-angular": "3.0.6", "@ngx-translate/core": "13.0.0", "@ngx-translate/http-loader": "6.0.0", - "@openstapps/api": "0.32.0", + "@openstapps/api": "0.35.0", "@openstapps/configuration": "0.28.1", - "@openstapps/core": "0.51.0", + "@openstapps/core": "0.53.0", "cordova-android": "9.0.0", "cordova-browser": "6.0.0", "cordova-ios": "6.2.0", diff --git a/src/app/_helpers/fake-backend.interceptor.ts b/src/app/_helpers/fake-backend.interceptor.ts index 23258ebc..43d35595 100644 --- a/src/app/_helpers/fake-backend.interceptor.ts +++ b/src/app/_helpers/fake-backend.interceptor.ts @@ -38,6 +38,7 @@ import {SampleThings} from './data/sample-things'; /* eslint-disable */ export const sampleIndexResponse: SCIndexResponse = { app: { + aboutPages: {}, campusPolygon: { coordinates: [ [ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2f6b856c..1edb2ea0 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -56,6 +56,8 @@ import {UtilModule} from './util/util.module'; import {initLogger} from './_helpers/ts-logger'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {FavoritesModule} from './modules/favorites/favorites.module'; +import {FeedbackModule} from './modules/feedback/feedback.module'; +import {DebugDataCollectorService} from './modules/data/debug-data-collector.service'; registerLocaleData(localeDe); @@ -144,6 +146,7 @@ const providers: Provider[] = [ DataModule, IonicModule.forRoot(), FavoritesModule, + FeedbackModule, MapModule, MenuModule, NewsModule, @@ -171,4 +174,6 @@ const providers: Provider[] = [ ? [providers, fakeBackendProvider] : providers, }) -export class AppModule {} +export class AppModule { + constructor(public debugDataCollectorService: DebugDataCollectorService) {} +} diff --git a/src/app/modules/config/config.provider.spec.ts b/src/app/modules/config/config.provider.spec.ts index c008b5b1..4be37638 100644 --- a/src/app/modules/config/config.provider.spec.ts +++ b/src/app/modules/config/config.provider.spec.ts @@ -220,6 +220,7 @@ const scVersion = packageJson.dependencies['@openstapps/core']; const sampleIndexResponse: SCIndexResponse = { app: { + aboutPages: {}, campusPolygon: { coordinates: [[[1, 2]], [[1, 2]]], type: 'Polygon', diff --git a/src/app/modules/data/data.provider.ts b/src/app/modules/data/data.provider.ts index 73268dc8..5e802930 100644 --- a/src/app/modules/data/data.provider.ts +++ b/src/app/modules/data/data.provider.ts @@ -28,6 +28,7 @@ import { SCThingsField, SCThingType, SCSaveableThing, + SCFeedbackRequest, } from '@openstapps/core'; import {chunk, fromPairs, toPairs} from 'lodash-es'; import {environment} from '../../../environments/environment'; @@ -292,6 +293,15 @@ export class DataProvider { ); } + /** + * Send a feedback message (request) + * + * @param feedback Feedback message to be sent to the backend + */ + async sendFeedback(feedback: SCFeedbackRequest) { + return this.client.feedback(feedback); + } + /** * Searches the backend using the provided query and returns response * diff --git a/src/app/modules/data/debug-data-collector.service.ts b/src/app/modules/data/debug-data-collector.service.ts new file mode 100644 index 00000000..9a40acff --- /dev/null +++ b/src/app/modules/data/debug-data-collector.service.ts @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +import {Injectable} from '@angular/core'; +import {SCFeedbackRequestMetaData} from '@openstapps/core'; +import {Platform} from '@ionic/angular'; +import {DataProvider} from './data.provider'; +import {NavigationEnd, Router} from '@angular/router'; +import {SettingsProvider} from '../settings/settings.provider'; + +@Injectable({ + providedIn: 'root', +}) +export class DebugDataCollectorService { + /** + * Previously visited route + */ + previousRoute: string; + + /** + * Current route + */ + currentRoute: string; + + constructor( + private platform: Platform, + private dataProvider: DataProvider, + private router: Router, + private settingsProvider: SettingsProvider, + ) { + this.currentRoute = this.router.url; + router.events.subscribe(event => { + if (event instanceof NavigationEnd) { + this.previousRoute = this.currentRoute; + this.currentRoute = event.url; + } + }); + } + + /** + * Provides meta data for a feedback + */ + async getFeedbackMetaData(): Promise { + return { + debug: false, + platform: this.platform.platforms().join(','), + scope: {}, + state: { + route: this.previousRoute, + settings: await this.settingsProvider.getCache(), + }, + userAgent: window.navigator.userAgent, + version: this.dataProvider.appVersion, + sendable: true, + }; + } +} diff --git a/src/app/modules/feedback/feedback-page.component.ts b/src/app/modules/feedback/feedback-page.component.ts new file mode 100644 index 00000000..eedcc054 --- /dev/null +++ b/src/app/modules/feedback/feedback-page.component.ts @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2021 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +import {Component} from '@angular/core'; +import { + SCFeedbackRequest, + SCFeedbackRequestMetaData, + SCMessage, + SCPersonWithoutReferences, + SCThingOriginType, + SCThingType, +} from '@openstapps/core'; +import {DataProvider} from '../data/data.provider'; +import {DebugDataCollectorService} from '../data/debug-data-collector.service'; +import {AlertController, ToastController} from '@ionic/angular'; +import {TranslateService} from '@ngx-translate/core'; + +@Component({ + templateUrl: './feedback-page.html', + styleUrls: ['./feedback-page.scss'], +}) +export class FeedbackPageComponent { + constructor( + private readonly dataProvider: DataProvider, + private readonly debugDataCollector: DebugDataCollectorService, + private readonly toastController: ToastController, + private readonly alertController: AlertController, + private readonly translateService: TranslateService, + ) {} + + /** + * Sender of the feedback message + */ + author: SCPersonWithoutReferences = { + uid: '0f53f16a-e618-5ae0-a1b6-336e34f0d4d1', + name: '', + type: SCThingType.Person, + }; + + /** + * The message to be sent + */ + message: SCMessage = { + uid: '0f53f16a-e618-5ae0-a1b6-336e34f0d4d1', + name: 'Bug', + type: SCThingType.Message, + audiences: [], + categories: [], + origin: { + type: SCThingOriginType.User, + created: new Date().toISOString(), + }, + messageBody: '', + }; + + /** + * Terms of feedback accepted or not + */ + termsAgree = false; + + /** + * Show meta data or not + */ + showMetaData = false; + + /** + * Feedback successfully sent + */ + submitSuccess = false; + + /** + * Terms of feedback accepted or not + */ + metaData: SCFeedbackRequestMetaData; + + async ionViewDidEnter() { + this.metaData = await this.debugDataCollector.getFeedbackMetaData(); + } + + /** + * Assemble and send the feedback + */ + async onSubmit() { + if (this.author.name !== '') { + this.message.authors = [this.author]; + } + + const feedbackRequest: SCFeedbackRequest = { + ...this.message, + metaData: this.metaData, + }; + + try { + await this.dataProvider.sendFeedback(feedbackRequest); + void this.onSuccess(); + } catch { + void this.onError(); + } + } + + /** + * Show/hide the meta data + */ + toggleShowMetaData() { + this.showMetaData = !this.showMetaData; + } + + async onSuccess() { + this.submitSuccess = true; + const toast = await this.toastController.create({ + message: this.translateService.instant( + 'feedback.system_messages.success', + ), + duration: 2000, + }); + await toast.present(); + } + + async onError() { + const alert: HTMLIonAlertElement = await this.alertController.create({ + buttons: [this.translateService.instant('app.ui.CLOSE')], + header: this.translateService.instant('app.ui.ERROR'), + message: this.translateService.instant('app.errors.UNKNOWN'), + }); + + await alert.present(); + } +} diff --git a/src/app/modules/feedback/feedback-page.html b/src/app/modules/feedback/feedback-page.html new file mode 100644 index 00000000..2c20cdd5 --- /dev/null +++ b/src/app/modules/feedback/feedback-page.html @@ -0,0 +1,100 @@ + + + + + + + {{ 'feedback.page.TITLE' | translate }} + + + +
+ + {{ + 'feedback.form.name.label' | translate + }} + + + + {{ + 'feedback.form.type.label' | translate + }} + + {{ + 'feedback.form.type.values.comment' | translate + }} + {{ + 'feedback.form.type.values.bug' | translate + }} + + + + {{ + 'feedback.form.email.label' | translate + }} + + + + {{ + 'feedback.form.message.label' | translate + }} + + + + {{ + 'feedback.form.termsAgree' | translate + }} + + + {{ 'feedback.form.submit' | translate }} + + + + {{ + 'feedback.form.protocolData.show' | translate + }} + {{ + 'feedback.form.protocolData.hide' | translate + }} + + + +
{{ metaData | json }}
+
+
+
+
diff --git a/src/app/modules/feedback/feedback-page.scss b/src/app/modules/feedback/feedback-page.scss new file mode 100644 index 00000000..1050af59 --- /dev/null +++ b/src/app/modules/feedback/feedback-page.scss @@ -0,0 +1,6 @@ +pre { + white-space: pre-wrap; +} +ion-button { + margin: 10px; +} diff --git a/src/app/modules/feedback/feedback.module.ts b/src/app/modules/feedback/feedback.module.ts new file mode 100644 index 00000000..044accaf --- /dev/null +++ b/src/app/modules/feedback/feedback.module.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {IonicModule} from '@ionic/angular'; +import {FeedbackPageComponent} from './feedback-page.component'; +import {RouterModule, Routes} from '@angular/router'; +import {TranslateModule} from '@ngx-translate/core'; +import {MarkdownModule} from 'ngx-markdown'; + +const feedbackRoutes: Routes = [ + { + path: 'feedback', + component: FeedbackPageComponent, + }, +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(feedbackRoutes), + TranslateModule, + MarkdownModule, + ], + declarations: [FeedbackPageComponent], +}) +export class FeedbackModule {} diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index d5f55698..4b6492e7 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -3,10 +3,11 @@ "abort": "abbrechen", "app": { "ui": { - "CLOSE": "Schließen" + "CLOSE": "Schließen", + "ERROR": "Fehler" }, "errors": { - "UNKNOWN": "Unbekannter Fehler" + "UNKNOWN": "Unbekannter Fehler." } }, "common": { @@ -84,6 +85,41 @@ "TITLE": "Favoriten" } }, + "feedback": { + "page": { + "TITLE": "Feedback" + }, + "form": { + "name": { + "label": "Name", + "placeholder": "Dein Name" + }, + "type": { + "label": "Feedback-Art", + "values": { + "bug": "Fehler", + "comment": "Kommentar" + } + }, + "email": { + "label": "E-Mail", + "placeholder": "deine@mailadresse.de" + }, + "message": { + "label": "Nachricht", + "placeholder": "Deine Nachricht an uns..." + }, + "termsAgree": "Ich bin damit einverstanden, dass Protokolldaten zur Nachverfolgbarkeit von Fehlern mitversandt werden. Es erfolgt keine Weitergabe dieser Daten an Dritte.", + "submit": "Absenden", + "protocolData": { + "show": "Protokolldaten einblenden", + "hide": "Protokolldaten ausblenden" + } + }, + "system_messages": { + "success": "Danke für Dein Feedback." + } + }, "map": { "page": { "TITLE": "Karte", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index fd0e0129..92394903 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -3,10 +3,11 @@ "abort": "abort", "app": { "ui": { - "CLOSE": "Close" + "CLOSE": "Close", + "ERROR": "Error" }, "errors": { - "UNKNOWN": "Unknown problem" + "UNKNOWN": "Unknown problem." } }, "common": { @@ -84,6 +85,41 @@ "TITLE": "Favorites" } }, + "feedback": { + "page": { + "TITLE": "Feedback" + }, + "form": { + "name": { + "label": "Name", + "placeholder": "Your name" + }, + "type": { + "label": "Type of feedback", + "values": { + "bug": "Bug", + "comment": "Comment" + } + }, + "email": { + "label": "Mail", + "placeholder": "your@mailaddress.com" + }, + "message": { + "label": "Message", + "placeholder": "Your message for us..." + }, + "termsAgree": "I agree to provide the protocol data for easier traceability of errors. The data will not be forwarded to any third parties.", + "submit": "Submit", + "protocolData": { + "show": "Show protocol data", + "hide": "Hide protocol data" + } + }, + "system_messages": { + "success": "Thank you for your feedback." + } + }, "map": { "page": { "TITLE": "Map",