diff --git a/backend/index.js b/backend/index.js index 4a264a0..1c31c91 100644 --- a/backend/index.js +++ b/backend/index.js @@ -24,6 +24,7 @@ app.use("/api/v1/usercontent", require("./routes/usercontent.js")) app.use("/api/v1/mediaproxy", require("./routes/mediaproxy.js")) app.use("/api/v1/associations", require("./routes/associations.js")) app.use("/api/v1/polls", require("./routes/polls.js")) +app.use("/api/v1/feedback", require("./routes/feedback.js")) app.get("/api/v1/state", async (req, res) => { res.json({ release: req.app.locals.config.release, diff --git a/backend/migrations/20220831101545-feedback.js b/backend/migrations/20220831101545-feedback.js new file mode 100644 index 0000000..44cb6b9 --- /dev/null +++ b/backend/migrations/20220831101545-feedback.js @@ -0,0 +1,42 @@ +"use strict" +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable("Feedbacks", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.BIGINT + }, + feedbackText: { + type: Sequelize.TEXT + }, + starRating: { + type: Sequelize.INTEGER + }, + route: { + type: Sequelize.STRING + }, + debug: { + type: Sequelize.JSON + }, + userId: { + type: Sequelize.BIGINT + }, + tenant: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable("Feedbacks") + } +} diff --git a/backend/models/feedback.js b/backend/models/feedback.js index 53d831e..829ae2a 100644 --- a/backend/models/feedback.js +++ b/backend/models/feedback.js @@ -20,7 +20,7 @@ module.exports = (sequelize, DataTypes) => { feedbackText: DataTypes.TEXT, starRating: DataTypes.BIGINT, route: DataTypes.STRING, - userId: DataTypes.STRING, + userId: DataTypes.BIGINT, tenant: DataTypes.STRING, debug: DataTypes.JSON }, diff --git a/backend/routes/admin.js b/backend/routes/admin.js index 361bb6b..a2e8140 100644 --- a/backend/routes/admin.js +++ b/backend/routes/admin.js @@ -2,7 +2,7 @@ const express = require("express") const router = express.Router() const Errors = require("../lib/errors.js") const auth = require("../lib/authorize.js") -const { User, Theme, Message } = require("../models") +const { User, Theme, Message, Feedback } = require("../models") const { Op } = require("sequelize") const dayjs = require("dayjs") const fs = require("fs") @@ -33,6 +33,23 @@ router.all("*", auth, async (req, res, next) => { } }) +router.get("/feedback", auth, async (req, res, next) => { + try { + const feedback = await Feedback.findAndCountAll({ + order: [["createdAt", "DESC"]], + include: [ + { + model: User, + as: "user" + } + ] + }) + res.json(feedback) + } catch (err) { + return next(err) + } +}) + router.get("/", auth, async (req, res, next) => { try { res.json({ diff --git a/backend/routes/feedback.js b/backend/routes/feedback.js new file mode 100644 index 0000000..5b3485d --- /dev/null +++ b/backend/routes/feedback.js @@ -0,0 +1,25 @@ +const express = require("express") +const router = express.Router() +const Errors = require("../lib/errors.js") +const auth = require("../lib/authorize.js") +const { Feedback } = require("../models") + +router.post("/", auth, async (req, res, next) => { + try { + await Feedback.create({ + feedbackText: req.body.text, + starRating: req.body.starRating, + debug: { + client: req.body.debug + }, + route: req.body.route, + userId: req.user.id, + tenant: "colubrina" + }) + res.sendStatus(204) + } catch (e) { + next(e) + } +}) + +module.exports = router diff --git a/frontend/package.json b/frontend/package.json index 25f7dba..1164d3d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "colubrina", - "version": "1.0.25", + "version": "1.0.26", "description": "Simple instant communication.", "private": true, "author": "Troplo ", diff --git a/frontend/src/components/Header.vue b/frontend/src/components/Header.vue index 204d1e8..d4db8a1 100644 --- a/frontend/src/components/Header.vue +++ b/frontend/src/components/Header.vue @@ -357,6 +357,139 @@ + + + + Shortcuts + + + + + + QuickSwitcher + + CTRL + K + + + + RouteSwitcher + + CTRL + B + + + + Shortcuts + + CTRL + / + + + + Toggle CSS + + F9 + or + CTRL + ALT + D + + + + + + + + + + + Provide Feedback + + + + + + Rating: + + + + + + Your feedback will be used to make + {{ $store.state.site.name }} even better. + + + + + + + Close + + + Submit + + + + + + + + Go to Route + + + + + + + + + + Close + + + Go + + + + Debug + + { + this.feedback.text = "" + this.feedback.rating = 0 + this.feedback.modal = false + this.$toast.success("Thank you for making a better Colubrina.") + }) + .catch(() => { + this.$toast.error( + "Something went wrong while submitting feedback, you should submit feedback about this." + ) + }) + }, setNotifications(value) { this.axios .put("/api/v1/communications/settings/" + this.context.user.raw.id, { @@ -1049,6 +1269,7 @@ export default { } }, mounted() { + this.feedback.route = this.$route.path Vue.axios.defaults.headers.common["Authorization"] = localStorage.getItem("token") this.searchUsers() @@ -1108,6 +1329,11 @@ export default { }) } }) + }, + watch: { + $route(to) { + this.feedback.route = to.path + } } } diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 4506f79..96ff613 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -139,6 +139,14 @@ const routes = [ import( /* webpackChunkName: "adminLogs" */ "../views/Admin/AdminLogs.vue" ) + }, + { + path: "feedback", + name: "Feedback", + component: () => + import( + /* webpackChunkName: "adminFeedback" */ "../views/Admin/AdminFeedback.vue" + ) } ], component: () => diff --git a/frontend/src/views/Admin/Admin.vue b/frontend/src/views/Admin/Admin.vue index 26eb68c..0da2922 100644 --- a/frontend/src/views/Admin/Admin.vue +++ b/frontend/src/views/Admin/Admin.vue @@ -17,6 +17,10 @@ mdi-account-multiple  Users + + mdi-bug  + Feedback + mdi-brush  Themes diff --git a/frontend/src/views/Admin/AdminFeedback.vue b/frontend/src/views/Admin/AdminFeedback.vue new file mode 100644 index 0000000..3a035ba --- /dev/null +++ b/frontend/src/views/Admin/AdminFeedback.vue @@ -0,0 +1,61 @@ + + + + +