Reports.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <template>
  2. <div>
  3. <metadata title="Admin | Reports" />
  4. <div class="container">
  5. <table class="table is-striped">
  6. <thead>
  7. <tr>
  8. <td>Summary</td>
  9. <td>YouTube / Song ID</td>
  10. <td>Categories Included</td>
  11. <td>Options</td>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <tr v-for="report in reports" :key="report._id">
  16. <td>
  17. <report-info-item
  18. :created-at="report.createdAt"
  19. :created-by="report.createdBy"
  20. />
  21. </td>
  22. <td>
  23. <span>
  24. <a
  25. :href="
  26. 'https://www.youtube.com/watch?v=' +
  27. `${report.song.youtubeId}`
  28. "
  29. target="_blank"
  30. >
  31. {{ report.song.youtubeId }}</a
  32. >
  33. <br />
  34. {{ report.song._id }}
  35. </span>
  36. </td>
  37. <td id="categories-column">
  38. <ul>
  39. <li
  40. v-for="category in getCategories(
  41. report.issues
  42. )"
  43. :key="category"
  44. >
  45. {{ category }}
  46. </li>
  47. </ul>
  48. </td>
  49. <td id="options-column">
  50. <a
  51. class="button is-primary"
  52. href="#"
  53. @click="view(report)"
  54. content="Expand"
  55. v-tippy
  56. >
  57. <i class="material-icons icon-with-button">
  58. open_in_full
  59. </i>
  60. Expand
  61. </a>
  62. <a
  63. class="button is-success "
  64. href="#"
  65. @click="resolve(report._id)"
  66. content="Resolve"
  67. v-tippy
  68. >
  69. <i class="material-icons icon-with-button">
  70. done_all
  71. </i>
  72. Resolve
  73. </a>
  74. </td>
  75. </tr>
  76. </tbody>
  77. </table>
  78. </div>
  79. <view-report
  80. v-if="modals.viewReport"
  81. :report-id="viewingReportId"
  82. sector="admin"
  83. />
  84. <edit-song v-if="modals.editSong" song-type="songs" />
  85. </div>
  86. </template>
  87. <script>
  88. import ReportInfoItem from "@/components/ReportInfoItem.vue";
  89. import { mapState, mapActions, mapGetters } from "vuex";
  90. import { defineAsyncComponent } from "vue";
  91. import Toast from "toasters";
  92. import ws from "@/ws";
  93. export default {
  94. components: {
  95. ViewReport: defineAsyncComponent(() =>
  96. import("@/components/modals/ViewReport.vue")
  97. ),
  98. EditSong: defineAsyncComponent(() =>
  99. import("@/components/modals/EditSong/index.vue")
  100. ),
  101. ReportInfoItem
  102. },
  103. data() {
  104. return {
  105. viewingReportId: "",
  106. reports: []
  107. };
  108. },
  109. computed: {
  110. ...mapState("modalVisibility", {
  111. modals: state => state.modals
  112. }),
  113. ...mapGetters({
  114. socket: "websockets/getSocket"
  115. })
  116. },
  117. mounted() {
  118. if (this.socket.readyState === 1) this.init();
  119. ws.onConnect(() => this.init());
  120. this.socket.dispatch("reports.index", res => {
  121. if (res.status === "success") this.reports = res.data.reports;
  122. });
  123. this.socket.on("event:admin.report.resolved", res => {
  124. this.reports = this.reports.filter(report => {
  125. return report._id !== res.data.reportId;
  126. });
  127. });
  128. this.socket.on("event:admin.report.created", res =>
  129. this.reports.unshift(res.data.report)
  130. );
  131. // if (this.$route.query.id) {
  132. // this.socket.dispatch(
  133. // "reports.findOne",
  134. // this.$route.query.id,
  135. // res => {
  136. // if (res.status === "success") this.view(res.data.report);
  137. // else new Toast("Report with that ID not found");
  138. // }
  139. // );
  140. // }
  141. },
  142. methods: {
  143. init() {
  144. this.socket.dispatch("apis.joinAdminRoom", "reports", () => {});
  145. },
  146. getCategories(issues) {
  147. const categories = [];
  148. issues.forEach(issue => {
  149. if (categories.indexOf(issue.category) === -1)
  150. categories.push(issue.category);
  151. });
  152. return categories;
  153. },
  154. view(report) {
  155. this.viewingReportId = report._id;
  156. this.openModal("viewReport");
  157. },
  158. resolve(reportId) {
  159. return this.resolveReport(reportId)
  160. .then(res => {
  161. if (res.status === "success" && this.modals.viewReport)
  162. this.closeModal("viewReport");
  163. })
  164. .catch(err => new Toast(err.message));
  165. },
  166. ...mapActions("modalVisibility", ["openModal", "closeModal"]),
  167. ...mapActions("admin/reports", ["resolveReport"])
  168. }
  169. };
  170. </script>
  171. <style lang="scss" scoped>
  172. .night-mode {
  173. .table {
  174. color: var(--light-grey-2);
  175. background-color: var(--dark-grey-3);
  176. thead tr {
  177. background: var(--dark-grey-3);
  178. td {
  179. color: var(--white);
  180. }
  181. }
  182. tbody tr:hover {
  183. background-color: var(--dark-grey-4) !important;
  184. }
  185. tbody tr:nth-child(even) {
  186. background-color: var(--dark-grey-2);
  187. }
  188. strong {
  189. color: var(--light-grey-2);
  190. }
  191. }
  192. .report-item-header {
  193. background-color: var(--dark-grey-4) !important;
  194. }
  195. }
  196. #options-column {
  197. a:not(:last-of-type) {
  198. margin-right: 5px;
  199. }
  200. }
  201. #categories-column {
  202. text-transform: capitalize;
  203. }
  204. td {
  205. word-wrap: break-word;
  206. max-width: 10vw;
  207. vertical-align: middle;
  208. }
  209. li {
  210. list-style: inside;
  211. }
  212. </style>