Report.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <modal title="Report">
  3. <template #body>
  4. <div class="edit-report-wrapper">
  5. <song-item
  6. :song="song"
  7. :disabled-actions="['report']"
  8. header="Selected Song.."
  9. />
  10. <div class="columns is-multiline">
  11. <div
  12. v-for="issue in issues"
  13. class="column is-half"
  14. :key="issue.name"
  15. >
  16. <label class="label">{{ issue.name }}</label>
  17. <p
  18. v-for="reason in issue.reasons"
  19. class="control checkbox-control"
  20. :key="reason.reason"
  21. >
  22. <span class="align-horizontally">
  23. <span>
  24. <label class="switch">
  25. <input
  26. type="checkbox"
  27. :id="reason.reason"
  28. v-model="reason.enabled"
  29. />
  30. <span class="slider round"></span>
  31. </label>
  32. <label :for="reason.reason">
  33. <span></span>
  34. <p>{{ reason.reason }}</p>
  35. </label>
  36. </span>
  37. <i
  38. class="material-icons"
  39. content="Provide More Info"
  40. v-tippy
  41. @click="reason.showInfo = !reason.showInfo"
  42. >
  43. info
  44. </i>
  45. </span>
  46. <input
  47. type="text"
  48. class="input"
  49. v-model="reason.info"
  50. v-if="reason.showInfo"
  51. placeholder="Provide more information..."
  52. @keyup="reason.enabled = true"
  53. />
  54. </p>
  55. </div>
  56. <!-- allow for multiple custom issues with plus/add button and then a input textbox -->
  57. <!-- do away with textbox -->
  58. <!--
  59. <div class="column">
  60. <p class="content-box-optional-helper">
  61. <a href="#" @click="changeToLoginModal()">
  62. Issue isn't listed?
  63. </a>
  64. </p>
  65. <br />
  66. <textarea
  67. v-model="report.description"
  68. class="textarea"
  69. maxlength="400"
  70. placeholder="Any other details..."
  71. />
  72. <div class="textarea-counter">
  73. {{ charactersRemaining }}
  74. </div>
  75. </div>
  76. -->
  77. </div>
  78. </div>
  79. </template>
  80. <template #footer>
  81. <a class="button is-success" @click="create()" href="#">
  82. <i class="material-icons save-changes">done</i>
  83. <span>&nbsp;Create</span>
  84. </a>
  85. <a class="button is-danger" href="#" @click="closeModal('report')">
  86. <span>&nbsp;Cancel</span>
  87. </a>
  88. </template>
  89. </modal>
  90. </template>
  91. <script>
  92. import { mapState, mapGetters, mapActions } from "vuex";
  93. import Toast from "toasters";
  94. import SongItem from "@/components/SongItem.vue";
  95. import Modal from "../Modal.vue";
  96. export default {
  97. components: { Modal, SongItem },
  98. data() {
  99. return {
  100. report: {
  101. resolved: false,
  102. youtubeId: "",
  103. description: "",
  104. issues: [
  105. { name: "Video", reasons: [] },
  106. { name: "Title", reasons: [] },
  107. { name: "Duration", reasons: [] },
  108. { name: "Artists", reasons: [] },
  109. { name: "Thumbnail", reasons: [] }
  110. ]
  111. },
  112. issues: [
  113. {
  114. name: "Video",
  115. reasons: [
  116. {
  117. enabled: false,
  118. reason: "Doesn't exist",
  119. info: "",
  120. showInfo: false
  121. },
  122. {
  123. enabled: false,
  124. reason: "It's private",
  125. info: "",
  126. showInfo: false
  127. },
  128. {
  129. enabled: false,
  130. reason: "It's not available in my country",
  131. info: "United States",
  132. showInfo: false
  133. },
  134. {
  135. enabled: false,
  136. reason: "Unofficial",
  137. info: "",
  138. showInfo: false
  139. }
  140. ]
  141. },
  142. {
  143. name: "Title",
  144. reasons: [
  145. {
  146. enabled: false,
  147. reason: "Incorrect",
  148. info: "",
  149. showInfo: false
  150. },
  151. {
  152. enabled: false,
  153. reason: "Inappropriate",
  154. info: "",
  155. showInfo: false
  156. }
  157. ]
  158. },
  159. {
  160. name: "Duration",
  161. reasons: [
  162. {
  163. enabled: false,
  164. reason: "Skips too soon",
  165. info: "",
  166. showInfo: false
  167. },
  168. {
  169. enabled: false,
  170. reason: "Skips too late",
  171. info: "",
  172. showInfo: false
  173. },
  174. {
  175. enabled: false,
  176. reason: "Starts too soon",
  177. info: "",
  178. showInfo: false
  179. },
  180. {
  181. enabled: false,
  182. reason: "Starts too late",
  183. info: "",
  184. showInfo: false
  185. }
  186. ]
  187. },
  188. {
  189. name: "Artists",
  190. reasons: [
  191. {
  192. enabled: false,
  193. reason: "Incorrect",
  194. info: "",
  195. showInfo: false
  196. },
  197. {
  198. enabled: false,
  199. reason: "Inappropriate",
  200. info: "",
  201. showInfo: false
  202. }
  203. ]
  204. },
  205. {
  206. name: "Thumbnail",
  207. reasons: [
  208. {
  209. enabled: false,
  210. reason: "Incorrect",
  211. info: "",
  212. showInfo: false
  213. },
  214. {
  215. enabled: false,
  216. reason: "Inappropriate",
  217. info: "",
  218. showInfo: false
  219. },
  220. {
  221. enabled: false,
  222. reason: "Doesn't exist",
  223. info: "",
  224. showInfo: false
  225. }
  226. ]
  227. }
  228. ]
  229. };
  230. },
  231. computed: {
  232. charactersRemaining() {
  233. return 400 - this.report.description.length;
  234. },
  235. ...mapState({
  236. song: state => state.modals.report.song
  237. }),
  238. ...mapGetters({
  239. socket: "websockets/getSocket"
  240. })
  241. },
  242. mounted() {
  243. if (this.song !== null) this.report.youtubeId = this.song.youtubeId;
  244. },
  245. methods: {
  246. create() {
  247. // generate report from here (filter by enabled reasons)
  248. this.socket.dispatch("reports.create", this.report, res => {
  249. new Toast(res.message);
  250. if (res.status === "success") this.closeModal("report");
  251. });
  252. },
  253. ...mapActions("modals/report", ["reportSong"]),
  254. ...mapActions("modalVisibility", ["closeModal"])
  255. }
  256. };
  257. </script>
  258. <style lang="scss">
  259. .edit-report-wrapper .song-item {
  260. .song-info {
  261. width: calc(100% - 150px);
  262. }
  263. .thumbnail {
  264. min-width: 130px;
  265. width: 130px;
  266. height: 130px;
  267. }
  268. }
  269. </style>
  270. <style lang="scss" scoped>
  271. .radio-controls .control {
  272. display: flex;
  273. align-items: center;
  274. }
  275. .textarea-counter {
  276. text-align: right;
  277. }
  278. @media screen and (min-width: 769px) {
  279. .radio-controls .control-label {
  280. padding-top: 0 !important;
  281. }
  282. }
  283. .columns {
  284. margin-left: unset;
  285. margin-right: unset;
  286. margin-top: 20px;
  287. .control {
  288. display: flex;
  289. flex-direction: column;
  290. span.align-horizontally {
  291. width: 100%;
  292. display: flex;
  293. align-items: center;
  294. justify-content: space-between;
  295. span {
  296. display: flex;
  297. }
  298. }
  299. i {
  300. cursor: pointer;
  301. }
  302. input[type="text"] {
  303. height: initial;
  304. margin: 10px 0;
  305. }
  306. }
  307. }
  308. </style>