Report.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 predefinedIssues"
  13. class="column is-half"
  14. :key="issue.category"
  15. >
  16. <label class="label">{{ issue.category }}</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. <div class="column is-half">
  59. <div id="custom-issues">
  60. <div id="custom-issues-title">
  61. <label class="label">Issues not listed</label>
  62. <button
  63. class="button tab-actionable-button "
  64. content="Add an issue that isn't listed"
  65. v-tippy="{ theme: 'info' }"
  66. @click="customIssues.push('')"
  67. >
  68. <i class="material-icons icon-with-button"
  69. >add</i
  70. >
  71. <span>
  72. Add Custom Issue
  73. </span>
  74. </button>
  75. </div>
  76. <div
  77. class="custom-issue control is-grouped input-with-button"
  78. v-for="(issue, index) in customIssues"
  79. :key="index"
  80. >
  81. <p class="control is-expanded">
  82. <input
  83. type="text"
  84. class="input"
  85. v-model="customIssues[index]"
  86. placeholder="Provide information..."
  87. />
  88. </p>
  89. <p class="control">
  90. <button
  91. class="button is-danger"
  92. content="Remove custom issue"
  93. v-tippy="{ theme: 'info' }"
  94. @click="customIssues.splice(index, 1)"
  95. >
  96. <i class="material-icons">
  97. delete
  98. </i>
  99. </button>
  100. </p>
  101. </div>
  102. <p
  103. id="no-issues-listed"
  104. v-if="customIssues.length <= 0"
  105. >
  106. <em>
  107. Add any issues that aren't listed above.
  108. </em>
  109. </p>
  110. </div>
  111. </div>
  112. <!--
  113. <div class="column">
  114. <p class="content-box-optional-helper">
  115. <a href="#" @click="changeToLoginModal()">
  116. Issue isn't listed?
  117. </a>
  118. </p>
  119. <br />
  120. <textarea
  121. v-model="report.description"
  122. class="textarea"
  123. maxlength="400"
  124. placeholder="Any other details..."
  125. />
  126. <div class="textarea-counter">
  127. {{ charactersRemaining }}
  128. </div>
  129. </div>
  130. -->
  131. </div>
  132. </div>
  133. </template>
  134. <template #footer>
  135. <a class="button is-success" @click="create()" href="#">
  136. <i class="material-icons save-changes">done</i>
  137. <span>&nbsp;Create</span>
  138. </a>
  139. <a class="button is-danger" href="#" @click="closeModal('report')">
  140. <span>&nbsp;Cancel</span>
  141. </a>
  142. </template>
  143. </modal>
  144. </template>
  145. <script>
  146. import { mapState, mapGetters, mapActions } from "vuex";
  147. import Toast from "toasters";
  148. import SongItem from "@/components/SongItem.vue";
  149. import Modal from "../Modal.vue";
  150. export default {
  151. components: { Modal, SongItem },
  152. data() {
  153. return {
  154. customIssues: [],
  155. predefinedIssues: [
  156. {
  157. category: "video",
  158. reasons: [
  159. {
  160. enabled: false,
  161. reason: "Doesn't exist",
  162. info: "",
  163. showInfo: false
  164. },
  165. {
  166. enabled: false,
  167. reason: "It's private",
  168. info: "",
  169. showInfo: false
  170. },
  171. {
  172. enabled: false,
  173. reason: "It's not available in my country",
  174. info: "United States",
  175. showInfo: false
  176. },
  177. {
  178. enabled: false,
  179. reason: "Unofficial",
  180. info: "",
  181. showInfo: false
  182. }
  183. ]
  184. },
  185. {
  186. category: "title",
  187. reasons: [
  188. {
  189. enabled: false,
  190. reason: "Incorrect",
  191. info: "",
  192. showInfo: false
  193. },
  194. {
  195. enabled: false,
  196. reason: "Inappropriate",
  197. info: "",
  198. showInfo: false
  199. }
  200. ]
  201. },
  202. {
  203. category: "duration",
  204. reasons: [
  205. {
  206. enabled: false,
  207. reason: "Skips too soon",
  208. info: "",
  209. showInfo: false
  210. },
  211. {
  212. enabled: false,
  213. reason: "Skips too late",
  214. info: "",
  215. showInfo: false
  216. },
  217. {
  218. enabled: false,
  219. reason: "Starts too soon",
  220. info: "",
  221. showInfo: false
  222. },
  223. {
  224. enabled: false,
  225. reason: "Starts too late",
  226. info: "",
  227. showInfo: false
  228. }
  229. ]
  230. },
  231. {
  232. category: "artists",
  233. reasons: [
  234. {
  235. enabled: false,
  236. reason: "Incorrect",
  237. info: "",
  238. showInfo: false
  239. },
  240. {
  241. enabled: false,
  242. reason: "Inappropriate",
  243. info: "",
  244. showInfo: false
  245. }
  246. ]
  247. },
  248. {
  249. category: "thumbnail",
  250. reasons: [
  251. {
  252. enabled: false,
  253. reason: "Incorrect",
  254. info: "",
  255. showInfo: false
  256. },
  257. {
  258. enabled: false,
  259. reason: "Inappropriate",
  260. info: "",
  261. showInfo: false
  262. },
  263. {
  264. enabled: false,
  265. reason: "Doesn't exist",
  266. info: "",
  267. showInfo: false
  268. }
  269. ]
  270. }
  271. ]
  272. };
  273. },
  274. computed: {
  275. charactersRemaining() {
  276. return 400 - this.report.description.length;
  277. },
  278. ...mapState({
  279. song: state => state.modals.report.song
  280. }),
  281. ...mapGetters({
  282. socket: "websockets/getSocket"
  283. })
  284. },
  285. methods: {
  286. create() {
  287. const issues = [];
  288. // any predefined issues that are enabled
  289. this.predefinedIssues.forEach(category =>
  290. category.reasons.forEach(reason => {
  291. if (reason.enabled) {
  292. const info =
  293. reason.info === ""
  294. ? reason.reason
  295. : `${reason.reason} - ${reason.info}`;
  296. issues.push({ category: category.category, info });
  297. }
  298. })
  299. );
  300. // any custom issues
  301. this.customIssues.forEach(issue =>
  302. issues.push({ category: "custom", info: issue })
  303. );
  304. this.socket.dispatch(
  305. "reports.create",
  306. {
  307. issues,
  308. youtubeId: this.song.youtubeId
  309. },
  310. res => {
  311. new Toast(res.message);
  312. if (res.status === "success") this.closeModal("report");
  313. }
  314. );
  315. },
  316. ...mapActions("modals/report", ["reportSong"]),
  317. ...mapActions("modalVisibility", ["closeModal"])
  318. }
  319. };
  320. </script>
  321. <style lang="scss">
  322. .edit-report-wrapper .song-item {
  323. .song-info {
  324. width: calc(100% - 150px);
  325. }
  326. .thumbnail {
  327. min-width: 130px;
  328. width: 130px;
  329. height: 130px;
  330. }
  331. }
  332. </style>
  333. <style lang="scss" scoped>
  334. .radio-controls .control {
  335. display: flex;
  336. align-items: center;
  337. }
  338. .textarea-counter {
  339. text-align: right;
  340. }
  341. @media screen and (min-width: 769px) {
  342. .radio-controls .control-label {
  343. padding-top: 0 !important;
  344. }
  345. }
  346. .label {
  347. text-transform: capitalize;
  348. }
  349. .columns {
  350. margin-left: unset;
  351. margin-right: unset;
  352. margin-top: 20px;
  353. .control {
  354. display: flex;
  355. flex-direction: column;
  356. span.align-horizontally {
  357. width: 100%;
  358. display: flex;
  359. align-items: center;
  360. justify-content: space-between;
  361. span {
  362. display: flex;
  363. }
  364. }
  365. i {
  366. cursor: pointer;
  367. }
  368. input[type="text"] {
  369. height: initial;
  370. margin: 10px 0;
  371. }
  372. }
  373. }
  374. #custom-issues {
  375. height: 100%;
  376. #custom-issues-title {
  377. display: flex;
  378. align-items: center;
  379. justify-content: space-between;
  380. margin-bottom: 15px;
  381. button {
  382. padding: 3px 5px;
  383. height: initial;
  384. }
  385. label {
  386. margin: 0;
  387. }
  388. }
  389. #no-issues-listed {
  390. display: flex;
  391. height: calc(100% - 32px - 15px);
  392. align-items: center;
  393. justify-content: center;
  394. }
  395. .custom-issue {
  396. flex-direction: row;
  397. input {
  398. height: 36px;
  399. margin: 0;
  400. }
  401. }
  402. }
  403. </style>