Reports.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div>
  3. <page-metadata title="Admin | Songs | Reports" />
  4. <div class="container">
  5. <advanced-table
  6. :column-default="columnDefault"
  7. :columns="columns"
  8. :filters="filters"
  9. data-action="reports.getData"
  10. name="admin-reports"
  11. max-width="1200"
  12. :events="events"
  13. >
  14. <template #column-options="slotProps">
  15. <div class="row-options">
  16. <button
  17. class="button is-primary icon-with-button material-icons"
  18. @click="view(slotProps.item._id)"
  19. :disabled="slotProps.item.removed"
  20. content="View Report"
  21. v-tippy
  22. >
  23. open_in_full
  24. </button>
  25. <button
  26. v-if="slotProps.item.resolved"
  27. class="button is-danger material-icons icon-with-button"
  28. @click="resolve(slotProps.item._id, false)"
  29. :disabled="slotProps.item.removed"
  30. content="Unresolve Report"
  31. v-tippy
  32. >
  33. remove_done
  34. </button>
  35. <button
  36. v-else
  37. class="button is-success material-icons icon-with-button"
  38. @click="resolve(slotProps.item._id, true)"
  39. :disabled="slotProps.item.removed"
  40. content="Resolve Report"
  41. v-tippy
  42. >
  43. done_all
  44. </button>
  45. </div>
  46. </template>
  47. <template #column-_id="slotProps">
  48. <span :title="slotProps.item._id">{{
  49. slotProps.item._id
  50. }}</span>
  51. </template>
  52. <template #column-songId="slotProps">
  53. <span :title="slotProps.item.song._id">{{
  54. slotProps.item.song._id
  55. }}</span>
  56. </template>
  57. <template #column-songYoutubeId="slotProps">
  58. <a
  59. :href="
  60. 'https://www.youtube.com/watch?v=' +
  61. `${slotProps.item.song.youtubeId}`
  62. "
  63. target="_blank"
  64. >
  65. {{ slotProps.item.song.youtubeId }}
  66. </a>
  67. </template>
  68. <template #column-resolved="slotProps">
  69. <span :title="slotProps.item.resolved">{{
  70. slotProps.item.resolved
  71. }}</span>
  72. </template>
  73. <template #column-categories="slotProps">
  74. <span
  75. :title="
  76. slotProps.item.issues
  77. .map(issue => issue.category)
  78. .join(', ')
  79. "
  80. >{{
  81. slotProps.item.issues
  82. .map(issue => issue.category)
  83. .join(", ")
  84. }}</span
  85. >
  86. </template>
  87. <template #column-createdBy="slotProps">
  88. <span v-if="slotProps.item.createdBy === 'Musare'"
  89. >Musare</span
  90. >
  91. <user-id-to-username
  92. v-else
  93. :user-id="slotProps.item.createdBy"
  94. :link="true"
  95. />
  96. </template>
  97. <template #column-createdAt="slotProps">
  98. <span :title="new Date(slotProps.item.createdAt)">{{
  99. getDateFormatted(slotProps.item.createdAt)
  100. }}</span>
  101. </template>
  102. </advanced-table>
  103. </div>
  104. <view-report v-if="modals.viewReport" sector="admin" />
  105. <edit-song v-if="modals.editSong" song-type="songs" />
  106. <report v-if="modals.report" />
  107. </div>
  108. </template>
  109. <script>
  110. import { mapState, mapActions } from "vuex";
  111. import { defineAsyncComponent } from "vue";
  112. import Toast from "toasters";
  113. import AdvancedTable from "@/components/AdvancedTable.vue";
  114. import UserIdToUsername from "@/components/UserIdToUsername.vue";
  115. export default {
  116. components: {
  117. ViewReport: defineAsyncComponent(() =>
  118. import("@/components/modals/ViewReport.vue")
  119. ),
  120. Report: defineAsyncComponent(() =>
  121. import("@/components/modals/Report.vue")
  122. ),
  123. EditSong: defineAsyncComponent(() =>
  124. import("@/components/modals/EditSong/index.vue")
  125. ),
  126. AdvancedTable,
  127. UserIdToUsername
  128. },
  129. data() {
  130. return {
  131. columnDefault: {
  132. sortable: true,
  133. hidable: true,
  134. defaultVisibility: "shown",
  135. draggable: true,
  136. resizable: true,
  137. minWidth: 150,
  138. maxWidth: 600
  139. },
  140. columns: [
  141. {
  142. name: "options",
  143. displayName: "Options",
  144. properties: ["_id", "resolved"],
  145. sortable: false,
  146. hidable: false,
  147. resizable: false,
  148. minWidth: 85,
  149. defaultWidth: 85
  150. },
  151. {
  152. name: "_id",
  153. displayName: "Report ID",
  154. properties: ["_id"],
  155. sortProperty: "_id",
  156. minWidth: 215,
  157. defaultWidth: 215
  158. },
  159. {
  160. name: "songId",
  161. displayName: "Song ID",
  162. properties: ["song"],
  163. sortProperty: "song._id",
  164. minWidth: 215,
  165. defaultWidth: 215
  166. },
  167. {
  168. name: "songYoutubeId",
  169. displayName: "Song YouTube ID",
  170. properties: ["song"],
  171. sortProperty: "song.youtubeId",
  172. minWidth: 165,
  173. defaultWidth: 165
  174. },
  175. {
  176. name: "resolved",
  177. displayName: "Resolved",
  178. properties: ["resolved"],
  179. sortProperty: "resolved"
  180. },
  181. {
  182. name: "categories",
  183. displayName: "Categories",
  184. properties: ["issues"],
  185. sortable: false
  186. },
  187. {
  188. name: "createdBy",
  189. displayName: "Created By",
  190. properties: ["createdBy"],
  191. sortProperty: "createdBy",
  192. defaultWidth: 150
  193. },
  194. {
  195. name: "createdAt",
  196. displayName: "Created At",
  197. properties: ["createdAt"],
  198. sortProperty: "createdAt",
  199. defaultWidth: 150
  200. }
  201. ],
  202. filters: [
  203. {
  204. name: "_id",
  205. displayName: "Report ID",
  206. property: "_id",
  207. filterTypes: ["exact"],
  208. defaultFilterType: "exact"
  209. },
  210. {
  211. name: "songId",
  212. displayName: "Song ID",
  213. property: "song._id",
  214. filterTypes: ["exact"],
  215. defaultFilterType: "exact"
  216. },
  217. {
  218. name: "songYoutubeId",
  219. displayName: "Song YouTube ID",
  220. property: "song.youtubeId",
  221. filterTypes: ["contains", "exact", "regex"],
  222. defaultFilterType: "contains"
  223. },
  224. {
  225. name: "resolved",
  226. displayName: "Resolved",
  227. property: "resolved",
  228. filterTypes: ["boolean"],
  229. defaultFilterType: "boolean"
  230. },
  231. {
  232. name: "categories",
  233. displayName: "Categories",
  234. property: "issues.category",
  235. filterTypes: ["contains", "exact", "regex"],
  236. defaultFilterType: "contains"
  237. },
  238. {
  239. name: "createdBy",
  240. displayName: "Created By",
  241. property: "createdBy",
  242. filterTypes: ["contains", "exact", "regex"],
  243. defaultFilterType: "contains"
  244. },
  245. {
  246. name: "createdAt",
  247. displayName: "Created At",
  248. property: "createdAt",
  249. filterTypes: ["datetimeBefore", "datetimeAfter"],
  250. defaultFilterType: "datetimeBefore"
  251. }
  252. ],
  253. events: {
  254. adminRoom: "reports",
  255. updated: {
  256. event: "admin.report.updated",
  257. id: "report._id",
  258. item: "report"
  259. },
  260. removed: {
  261. event: "admin.report.removed",
  262. id: "reportId"
  263. }
  264. }
  265. };
  266. },
  267. computed: {
  268. ...mapState("modalVisibility", {
  269. modals: state => state.modals
  270. })
  271. },
  272. methods: {
  273. view(reportId) {
  274. this.viewReport(reportId);
  275. this.openModal("viewReport");
  276. },
  277. resolve(reportId, value) {
  278. return this.resolveReport({ reportId, value })
  279. .then(res => {
  280. if (res.status !== "success") new Toast(res.message);
  281. })
  282. .catch(err => new Toast(err.message));
  283. },
  284. getDateFormatted(createdAt) {
  285. const date = new Date(createdAt);
  286. const year = date.getFullYear();
  287. const month = `${date.getMonth() + 1}`.padStart(2, 0);
  288. const day = `${date.getDate()}`.padStart(2, 0);
  289. const hour = `${date.getHours()}`.padStart(2, 0);
  290. const minute = `${date.getMinutes()}`.padStart(2, 0);
  291. return `${year}-${month}-${day} ${hour}:${minute}`;
  292. },
  293. ...mapActions("modalVisibility", ["openModal", "closeModal"]),
  294. ...mapActions("admin/reports", ["resolveReport"]),
  295. ...mapActions("modals/viewReport", ["viewReport"])
  296. }
  297. };
  298. </script>