ViewReport.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <template>
  2. <modal class="view-report-modal" title="View Report">
  3. <template #body v-if="report && report._id">
  4. <div class="report-item">
  5. <report-info-item
  6. :created-at="report.createdAt"
  7. :created-by="report.createdBy"
  8. />
  9. <div class="report-sub-items">
  10. <div
  11. class="report-sub-item report-sub-item-unresolved"
  12. :class="[
  13. 'report',
  14. issue.resolved
  15. ? 'report-sub-item-resolved'
  16. : 'report-sub-item-unresolved'
  17. ]"
  18. v-for="(issue, issueIndex) in report.issues"
  19. :key="issueIndex"
  20. >
  21. <i
  22. class="material-icons duration-icon report-sub-item-left-icon"
  23. :content="issue.category"
  24. v-tippy
  25. >
  26. {{ icons[issue.category] }}
  27. </i>
  28. <p class="report-sub-item-info">
  29. <span class="report-sub-item-title">
  30. {{ issue.title }}
  31. </span>
  32. <span
  33. class="report-sub-item-description"
  34. v-if="issue.description"
  35. >
  36. {{ issue.description }}
  37. </span>
  38. </p>
  39. <div
  40. class="report-sub-item-actions universal-item-actions"
  41. >
  42. <i
  43. class="material-icons resolve-icon"
  44. content="Resolve"
  45. v-tippy
  46. v-if="!issue.resolved"
  47. @click="toggleIssue(report._id, issue._id)"
  48. >
  49. done
  50. </i>
  51. <i
  52. class="material-icons unresolve-icon"
  53. content="Unresolve"
  54. v-tippy
  55. v-else
  56. @click="toggleIssue(report._id, issue._id)"
  57. >
  58. remove
  59. </i>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. </template>
  65. <template #footer v-if="report && report._id">
  66. <a class="button is-primary" @click="openSong()">
  67. <i
  68. class="material-icons icon-with-button"
  69. content="Edit Song"
  70. v-tippy
  71. >
  72. edit
  73. </i>
  74. Edit Song
  75. </a>
  76. <a class="button is-success" href="#" @click="resolve(report._id)">
  77. <i
  78. class="material-icons icon-with-button"
  79. content="Resolve"
  80. v-tippy
  81. >
  82. done_all
  83. </i>
  84. Resolve
  85. </a>
  86. </template>
  87. </modal>
  88. </template>
  89. <script>
  90. import { mapActions, mapGetters } from "vuex";
  91. import Toast from "toasters";
  92. import Modal from "@/components/Modal.vue";
  93. import ReportInfoItem from "@/components/ReportInfoItem.vue";
  94. export default {
  95. components: { Modal, ReportInfoItem },
  96. props: {
  97. reportId: { type: String, default: "" },
  98. sector: { type: String, default: "admin" }
  99. },
  100. data() {
  101. return {
  102. icons: {
  103. duration: "timer",
  104. video: "tv",
  105. thumbnail: "image",
  106. artists: "record_voice_over",
  107. title: "title",
  108. custom: "lightbulb"
  109. },
  110. report: {}
  111. };
  112. },
  113. computed: {
  114. ...mapGetters({
  115. socket: "websockets/getSocket"
  116. })
  117. },
  118. mounted() {
  119. this.socket.dispatch("reports.findOne", this.reportId, res => {
  120. if (res.status === "success") {
  121. const { report } = res.data;
  122. this.socket.dispatch(
  123. "apis.joinRoom",
  124. `view-report.${report._id}`
  125. );
  126. this.report = report;
  127. } else {
  128. new Toast("Report with that ID not found");
  129. this.closeModal("viewReport");
  130. }
  131. });
  132. this.socket.on(
  133. "event:admin.report.resolved",
  134. () => this.closeModal("viewReport"),
  135. { modal: "viewReport" }
  136. );
  137. this.socket.on(
  138. "event:admin.report.issue.toggled",
  139. res => {
  140. if (this.report._id === res.data.reportId) {
  141. const issue = this.report.issues.find(
  142. issue => issue._id.toString() === res.data.issueId
  143. );
  144. issue.resolved = res.data.resolved;
  145. }
  146. },
  147. { modal: "viewReport" }
  148. );
  149. },
  150. beforeUnmount() {
  151. this.socket.dispatch("apis.leaveRoom", `view-report.${this.reportId}`);
  152. },
  153. methods: {
  154. resolve(reportId) {
  155. return this.resolveReport(reportId)
  156. .then(res => {
  157. if (res.status === "success") this.closeModal("viewReport");
  158. })
  159. .catch(err => new Toast(err.message));
  160. },
  161. toggleIssue(reportId, issueId) {
  162. this.socket.dispatch(
  163. "reports.toggleIssue",
  164. reportId,
  165. issueId,
  166. res => {
  167. if (res.status !== "success") new Toast(res.message);
  168. }
  169. );
  170. },
  171. openSong() {
  172. this.editSong({ _id: this.report.song._id });
  173. this.openModal("editSong");
  174. },
  175. ...mapActions("admin/reports", ["indexReports", "resolveReport"]),
  176. ...mapActions("modals/editSong", ["editSong"]),
  177. ...mapActions("modalVisibility", ["closeModal", "openModal"])
  178. }
  179. };
  180. </script>
  181. <style lang="scss">
  182. .view-report-modal .modal-card {
  183. width: auto;
  184. .modal-card-body {
  185. display: flex;
  186. justify-content: center;
  187. }
  188. }
  189. </style>
  190. <style lang="scss" scoped>
  191. .night-mode {
  192. .report-item {
  193. background-color: var(--dark-grey-2) !important;
  194. }
  195. .report-item-header {
  196. background-color: var(--dark-grey-3) !important;
  197. }
  198. }
  199. .report-item {
  200. background-color: var(--white);
  201. border: 0.5px solid var(--primary-color);
  202. border-radius: 5px;
  203. padding: 8px;
  204. &:not(:first-of-type) {
  205. margin-bottom: 16px;
  206. }
  207. .report-sub-items {
  208. .report-sub-item {
  209. border: 0.5px solid var(--black);
  210. margin-top: -1px;
  211. line-height: 24px;
  212. display: flex;
  213. // padding: 4px;
  214. padding: 8px;
  215. display: flex;
  216. &:first-child {
  217. border-radius: 3px 3px 0 0;
  218. }
  219. &:last-child {
  220. border-radius: 0 0 3px 3px;
  221. }
  222. &.report-sub-item-resolved {
  223. .report-sub-item-description,
  224. .report-sub-item-title {
  225. text-decoration: line-through;
  226. }
  227. }
  228. .report-sub-item-left-icon {
  229. margin-right: 8px;
  230. margin-top: auto;
  231. margin-bottom: auto;
  232. }
  233. .report-sub-item-info {
  234. flex: 1;
  235. display: flex;
  236. flex-direction: column;
  237. .report-sub-item-title {
  238. // font-size: 14px;
  239. font-size: 16px;
  240. }
  241. .report-sub-item-description {
  242. // font-size: 12px;
  243. font-size: 14px;
  244. line-height: 16px;
  245. }
  246. }
  247. .report-sub-item-actions {
  248. height: 24px;
  249. margin-left: 8px;
  250. margin-top: auto;
  251. margin-bottom: auto;
  252. }
  253. }
  254. }
  255. .resolve-icon {
  256. color: var(--green);
  257. cursor: pointer;
  258. }
  259. .unresolve-icon {
  260. color: var(--red);
  261. cursor: pointer;
  262. }
  263. }
  264. </style>