mirror of
https://github.com/Troplo/Colubrina.git
synced 2024-11-23 03:36:42 +11:00
1.0.26
This commit is contained in:
parent
686f602b56
commit
7125909046
10 changed files with 404 additions and 20 deletions
|
@ -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/mediaproxy", require("./routes/mediaproxy.js"))
|
||||||
app.use("/api/v1/associations", require("./routes/associations.js"))
|
app.use("/api/v1/associations", require("./routes/associations.js"))
|
||||||
app.use("/api/v1/polls", require("./routes/polls.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) => {
|
app.get("/api/v1/state", async (req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
release: req.app.locals.config.release,
|
release: req.app.locals.config.release,
|
||||||
|
|
42
backend/migrations/20220831101545-feedback.js
Normal file
42
backend/migrations/20220831101545-feedback.js
Normal file
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ module.exports = (sequelize, DataTypes) => {
|
||||||
feedbackText: DataTypes.TEXT,
|
feedbackText: DataTypes.TEXT,
|
||||||
starRating: DataTypes.BIGINT,
|
starRating: DataTypes.BIGINT,
|
||||||
route: DataTypes.STRING,
|
route: DataTypes.STRING,
|
||||||
userId: DataTypes.STRING,
|
userId: DataTypes.BIGINT,
|
||||||
tenant: DataTypes.STRING,
|
tenant: DataTypes.STRING,
|
||||||
debug: DataTypes.JSON
|
debug: DataTypes.JSON
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@ const express = require("express")
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
const Errors = require("../lib/errors.js")
|
const Errors = require("../lib/errors.js")
|
||||||
const auth = require("../lib/authorize.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 { Op } = require("sequelize")
|
||||||
const dayjs = require("dayjs")
|
const dayjs = require("dayjs")
|
||||||
const fs = require("fs")
|
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) => {
|
router.get("/", auth, async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
res.json({
|
res.json({
|
||||||
|
|
25
backend/routes/feedback.js
Normal file
25
backend/routes/feedback.js
Normal file
|
@ -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
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "colubrina",
|
"name": "colubrina",
|
||||||
"version": "1.0.25",
|
"version": "1.0.26",
|
||||||
"description": "Simple instant communication.",
|
"description": "Simple instant communication.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "Troplo <troplo@troplo.com>",
|
"author": "Troplo <troplo@troplo.com>",
|
||||||
|
|
|
@ -357,6 +357,139 @@
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
<v-dialog v-model="shortcuts" width="700">
|
||||||
|
<v-card color="card" elevation="7">
|
||||||
|
<v-toolbar color="toolbar">
|
||||||
|
<v-toolbar-title> Shortcuts </v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-layout row wrap>
|
||||||
|
<v-card class="mx-2 mt-2">
|
||||||
|
<v-card-title> QuickSwitcher </v-card-title>
|
||||||
|
<v-card-text class="text-center">
|
||||||
|
<v-btn text outlined> CTRL </v-btn>
|
||||||
|
<v-btn text outlined class="ml-2"> K </v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-card class="mx-2 mt-2">
|
||||||
|
<v-card-title> RouteSwitcher </v-card-title>
|
||||||
|
<v-card-text class="text-center">
|
||||||
|
<v-btn text outlined> CTRL </v-btn>
|
||||||
|
<v-btn text outlined class="ml-2"> B </v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-card class="mx-2 mt-2">
|
||||||
|
<v-card-title> Shortcuts </v-card-title>
|
||||||
|
<v-card-text class="text-center">
|
||||||
|
<v-btn text outlined class="ml-2"> CTRL </v-btn>
|
||||||
|
<v-btn text outlined class="ml-2"> / </v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-card class="mx-2 mt-2">
|
||||||
|
<v-card-title> Toggle CSS </v-card-title>
|
||||||
|
<v-card-text class="text-center">
|
||||||
|
<v-btn text outlined> F9 </v-btn>
|
||||||
|
<span class="ml-2">or</span>
|
||||||
|
<v-btn text outlined class="ml-2"> CTRL </v-btn>
|
||||||
|
<v-btn text outlined class="ml-2"> ALT </v-btn>
|
||||||
|
<v-btn text outlined class="ml-2"> D </v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
<v-dialog v-model="feedback.modal" width="700">
|
||||||
|
<v-card color="card" elevation="7">
|
||||||
|
<v-toolbar color="toolbar">
|
||||||
|
<v-toolbar-title> Provide Feedback </v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" md="4" sm="6">
|
||||||
|
Rating:
|
||||||
|
<v-rating
|
||||||
|
v-model="feedback.rating"
|
||||||
|
background-color="grey darken-1"
|
||||||
|
color="yellow darken-3"
|
||||||
|
empty-icon="$ratingFull"
|
||||||
|
hover
|
||||||
|
></v-rating>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-textarea
|
||||||
|
class="rounded-xl"
|
||||||
|
v-model="feedback.text"
|
||||||
|
label="Enter your Feedback"
|
||||||
|
required
|
||||||
|
autofocus
|
||||||
|
placeholder="Enter your Feedback"
|
||||||
|
></v-textarea>
|
||||||
|
</v-col>
|
||||||
|
<small
|
||||||
|
>Your feedback will be used to make
|
||||||
|
{{ $store.state.site.name }} even better.</small
|
||||||
|
>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn
|
||||||
|
class="rounded-xl"
|
||||||
|
color="blue darken-1"
|
||||||
|
text
|
||||||
|
@click="feedback.modal = false"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
class="rounded-xl"
|
||||||
|
color="blue darken-1"
|
||||||
|
text
|
||||||
|
@click="submitFeedback()"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
<v-dialog v-model="route.modal" width="700">
|
||||||
|
<v-card color="card" elevation="7">
|
||||||
|
<v-toolbar color="toolbar">
|
||||||
|
<v-toolbar-title> Go to Route </v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-card-text>
|
||||||
|
<v-container>
|
||||||
|
<v-text-field
|
||||||
|
class="rounded-xl"
|
||||||
|
v-model="route.value"
|
||||||
|
autofocus
|
||||||
|
@keyup.enter="goToRoute()"
|
||||||
|
label="Route"
|
||||||
|
required
|
||||||
|
></v-text-field>
|
||||||
|
</v-container>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn class="rounded-xl" text @click="route.modal = false">
|
||||||
|
Close
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
class="rounded-xl"
|
||||||
|
color="blue darken-1"
|
||||||
|
text
|
||||||
|
@click="goToRoute()"
|
||||||
|
>
|
||||||
|
Go
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
<v-app-bar app color="dark" elevation="5" style="z-index: 15">
|
<v-app-bar app color="dark" elevation="5" style="z-index: 15">
|
||||||
<v-app-bar-nav-icon
|
<v-app-bar-nav-icon
|
||||||
@click.stop="$store.state.drawer = !$store.state.drawer"
|
@click.stop="$store.state.drawer = !$store.state.drawer"
|
||||||
|
@ -397,6 +530,20 @@
|
||||||
>
|
>
|
||||||
Debug
|
Debug
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
style="display: none"
|
||||||
|
v-shortkey="['ctrl', 'b']"
|
||||||
|
@shortkey="route.modal = true"
|
||||||
|
>
|
||||||
|
Debug
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
style="display: none"
|
||||||
|
v-shortkey="['ctrl', '/']"
|
||||||
|
@shortkey="shortcuts = true"
|
||||||
|
>
|
||||||
|
Debug
|
||||||
|
</button>
|
||||||
<template v-if="$route.name === 'Communications'">
|
<template v-if="$route.name === 'Communications'">
|
||||||
<v-toolbar-title v-if="$store.state.selectedChat?.chat?.type">
|
<v-toolbar-title v-if="$store.state.selectedChat?.chat?.type">
|
||||||
{{
|
{{
|
||||||
|
@ -406,28 +553,66 @@
|
||||||
}}
|
}}
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
|
<v-tooltip bottom>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
|
<v-btn v-on="on" icon @click="feedback.modal = true">
|
||||||
|
<v-icon>mdi-bug</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<span>Provide Feedback</span>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-tooltip bottom>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
v-model="$store.state.context.pins.value"
|
v-model="$store.state.context.pins.value"
|
||||||
@click="show($event, 'pins', null, null, true)"
|
@click="show($event, 'pins', null, null, true)"
|
||||||
id="pin-button"
|
id="pin-button"
|
||||||
|
v-on="on"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-pin-outline</v-icon>
|
<v-icon>mdi-pin-outline</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<span>Chat Pins</span>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-tooltip bottom>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
@click="$store.state.searchPanel = !$store.state.searchPanel"
|
@click="$store.state.searchPanel = !$store.state.searchPanel"
|
||||||
|
v-on="on"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-magnify</v-icon>
|
<v-icon>mdi-magnify</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn icon @click="$store.state.userPanel = !$store.state.userPanel">
|
</template>
|
||||||
|
<span>Search Messages</span>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-tooltip bottom>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
|
<v-btn
|
||||||
|
v-on="on"
|
||||||
|
icon
|
||||||
|
@click="$store.state.userPanel = !$store.state.userPanel"
|
||||||
|
>
|
||||||
<v-icon>mdi-account-group-outline</v-icon>
|
<v-icon>mdi-account-group-outline</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
|
<span>Toggle member list</span>
|
||||||
|
</v-tooltip>
|
||||||
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<v-toolbar-title>
|
<v-toolbar-title>
|
||||||
{{ $route.name }}
|
{{ $route.name }}
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-tooltip bottom>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
|
<v-btn v-on="on" icon @click="feedback.modal = true">
|
||||||
|
<v-icon>mdi-bug</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<span>Provide Feedback</span>
|
||||||
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<v-navigation-drawer
|
<v-navigation-drawer
|
||||||
|
@ -682,6 +867,17 @@ export default {
|
||||||
components: { NicknameDialog },
|
components: { NicknameDialog },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
shortcuts: false,
|
||||||
|
route: {
|
||||||
|
modal: false,
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
feedback: {
|
||||||
|
modal: false,
|
||||||
|
route: "",
|
||||||
|
rating: 0,
|
||||||
|
text: ""
|
||||||
|
},
|
||||||
search: "",
|
search: "",
|
||||||
nickname: {
|
nickname: {
|
||||||
dialog: false,
|
dialog: false,
|
||||||
|
@ -757,6 +953,30 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
goToRoute() {
|
||||||
|
this.$router.push(this.route.value)
|
||||||
|
this.route.modal = false
|
||||||
|
this.route.value = ""
|
||||||
|
},
|
||||||
|
submitFeedback() {
|
||||||
|
this.axios
|
||||||
|
.post("/api/v1/feedback", {
|
||||||
|
text: this.feedback.text,
|
||||||
|
starRating: this.feedback.rating,
|
||||||
|
route: this.feedback.route
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
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) {
|
setNotifications(value) {
|
||||||
this.axios
|
this.axios
|
||||||
.put("/api/v1/communications/settings/" + this.context.user.raw.id, {
|
.put("/api/v1/communications/settings/" + this.context.user.raw.id, {
|
||||||
|
@ -1049,6 +1269,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.feedback.route = this.$route.path
|
||||||
Vue.axios.defaults.headers.common["Authorization"] =
|
Vue.axios.defaults.headers.common["Authorization"] =
|
||||||
localStorage.getItem("token")
|
localStorage.getItem("token")
|
||||||
this.searchUsers()
|
this.searchUsers()
|
||||||
|
@ -1108,6 +1329,11 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route(to) {
|
||||||
|
this.feedback.route = to.path
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -139,6 +139,14 @@ const routes = [
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "adminLogs" */ "../views/Admin/AdminLogs.vue"
|
/* webpackChunkName: "adminLogs" */ "../views/Admin/AdminLogs.vue"
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "feedback",
|
||||||
|
name: "Feedback",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "adminFeedback" */ "../views/Admin/AdminFeedback.vue"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
component: () =>
|
component: () =>
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
<v-icon>mdi-account-multiple</v-icon>
|
<v-icon>mdi-account-multiple</v-icon>
|
||||||
<span>Users</span>
|
<span>Users</span>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
|
<v-tab to="/admin/feedback">
|
||||||
|
<v-icon>mdi-bug</v-icon>
|
||||||
|
<span>Feedback</span>
|
||||||
|
</v-tab>
|
||||||
<v-tab to="/admin/themes">
|
<v-tab to="/admin/themes">
|
||||||
<v-icon>mdi-brush</v-icon>
|
<v-icon>mdi-brush</v-icon>
|
||||||
<span>Themes</span>
|
<span>Themes</span>
|
||||||
|
|
61
frontend/src/views/Admin/AdminFeedback.vue
Normal file
61
frontend/src/views/Admin/AdminFeedback.vue
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<div id="admin-feedback">
|
||||||
|
<v-toolbar color="toolbar">
|
||||||
|
<v-toolbar-title>Feedback ({{ feedback.count }})</v-toolbar-title>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn @click="getFeedback" icon>
|
||||||
|
<v-icon>mdi-refresh</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-container :fluid="$vuetify.breakpoint.lgAndDown">
|
||||||
|
<v-card
|
||||||
|
v-for="item in feedback.rows"
|
||||||
|
:key="item.id"
|
||||||
|
class="rounded-xl mb-2"
|
||||||
|
color="card"
|
||||||
|
>
|
||||||
|
<v-toolbar color="toolbar">
|
||||||
|
<v-toolbar-title>
|
||||||
|
Feedback -
|
||||||
|
{{ item.user.username }} ({{ item.user.id }})
|
||||||
|
</v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-container :fluid="$vuetify.breakpoint.lgAndDown">
|
||||||
|
{{ item.feedbackText.substring(0, 1000) }}
|
||||||
|
<br />
|
||||||
|
<small v-if="item.user">
|
||||||
|
Route: {{ item.route }}<br />
|
||||||
|
Rating: {{ item.starRating }}<br />
|
||||||
|
Created At:
|
||||||
|
{{ $date(item.createdAt).format("YYYY-MM-DD hh:mm A") }}</small
|
||||||
|
>
|
||||||
|
</v-container>
|
||||||
|
</v-card>
|
||||||
|
</v-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "AdminFeedback",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
feedback: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getFeedback() {
|
||||||
|
this.axios
|
||||||
|
.get(process.env.VUE_APP_BASE_URL + "/api/v1/admin/feedback")
|
||||||
|
.then((res) => {
|
||||||
|
this.feedback = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getFeedback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
Reference in a new issue