QueueItem.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <template>
  2. <div class="universal-item queue-item">
  3. <add-to-playlist-dropdown v-if="showPlaylistDropdown" :song="song" />
  4. <div id="thumbnail-and-info">
  5. <img
  6. class="item-thumbnail"
  7. :src="song.ytThumbnail ? song.ytThumbnail : song.thumbnail"
  8. onerror="this.src='/assets/notes-transparent.png'"
  9. />
  10. <div id="song-info">
  11. <h4
  12. class="item-title"
  13. :style="
  14. song.artists.length < 1 ? { fontSize: '16px' } : null
  15. "
  16. :title="song.title"
  17. >
  18. {{ song.title }}
  19. </h4>
  20. <h5
  21. class="item-description"
  22. v-if="song.artists"
  23. :title="song.artists.join(', ')"
  24. >
  25. {{ song.artists.join(", ") }}
  26. </h5>
  27. <p
  28. id="song-request-time"
  29. v-if="
  30. station.type === 'community' &&
  31. station.partyMode === true
  32. "
  33. >
  34. Requested by
  35. <strong>
  36. <user-id-to-username
  37. :user-id="song.requestedBy"
  38. :link="true"
  39. />
  40. {{
  41. formatDistance(
  42. parseISO(song.requestedAt),
  43. new Date(),
  44. {
  45. addSuffix: true
  46. }
  47. )
  48. }}
  49. </strong>
  50. </p>
  51. </div>
  52. </div>
  53. <div id="duration-and-actions">
  54. <p id="song-duration">
  55. {{ utils.formatTime(song.duration) }}
  56. </p>
  57. <div class="universal-item-actions">
  58. <i
  59. v-if="
  60. $parent.loggedIn &&
  61. song.likes !== -1 &&
  62. song.dislikes !== -1
  63. "
  64. class="material-icons report-icon"
  65. @click="report(song)"
  66. >
  67. flag
  68. </i>
  69. <i
  70. class="material-icons"
  71. @click="showPlaylistDropdown = !showPlaylistDropdown"
  72. >queue</i
  73. >
  74. <i
  75. v-if="
  76. $parent.isAdminOnly() &&
  77. song.likes !== -1 &&
  78. song.dislikes !== -1
  79. "
  80. class="material-icons edit-icon"
  81. @click="$parent.$parent.$parent.editSong(song)"
  82. >
  83. edit
  84. </i>
  85. <i
  86. v-if="$parent.isOwnerOnly() || $parent.isAdminOnly()"
  87. class="material-icons delete-icon"
  88. @click="$parent.removeFromQueue(song.songId)"
  89. >delete_forever</i
  90. >
  91. </div>
  92. </div>
  93. </div>
  94. </template>
  95. <script>
  96. import { mapActions } from "vuex";
  97. import { formatDistance, parseISO } from "date-fns";
  98. import AddToPlaylistDropdown from "../../../../../components/ui/AddToPlaylistDropdown.vue";
  99. import UserIdToUsername from "../../../../../components/common/UserIdToUsername.vue";
  100. import utils from "../../../../../../js/utils";
  101. export default {
  102. components: { UserIdToUsername, AddToPlaylistDropdown },
  103. props: {
  104. song: {
  105. type: Object,
  106. default: () => {}
  107. },
  108. station: {
  109. type: Object,
  110. default: () => {
  111. return { type: "community", partyMode: false };
  112. }
  113. }
  114. },
  115. data() {
  116. return {
  117. utils,
  118. showPlaylistDropdown: false
  119. };
  120. },
  121. methods: {
  122. report(song) {
  123. this.reportSong(song);
  124. this.openModal({ sector: "station", modal: "report" });
  125. },
  126. ...mapActions("modals/report", ["reportSong"]),
  127. ...mapActions("modalVisibility", ["openModal"]),
  128. formatDistance,
  129. parseISO
  130. }
  131. };
  132. </script>
  133. <style lang="scss" scoped>
  134. .night-mode {
  135. .queue-item {
  136. background-color: var(--dark-grey-2) !important;
  137. border: 0 !important;
  138. }
  139. }
  140. /deep/ #nav-dropdown {
  141. margin-top: 36px;
  142. /deep/ .nav-dropdown-items {
  143. position: absolute;
  144. right: 0;
  145. }
  146. }
  147. .queue-item {
  148. #thumbnail-and-info,
  149. #duration-and-actions {
  150. display: flex;
  151. align-items: center;
  152. }
  153. #duration-and-actions {
  154. margin-left: 5px;
  155. .universal-item-actions div i {
  156. margin-left: 5px;
  157. }
  158. }
  159. #thumbnail-and-info {
  160. width: calc(100% - 120px);
  161. }
  162. #song-info {
  163. display: flex;
  164. flex-direction: column;
  165. justify-content: center;
  166. margin-left: 20px;
  167. width: calc(100% - 65px);
  168. *:not(i) {
  169. margin: 0;
  170. font-family: Karla, Arial, sans-serif;
  171. }
  172. #song-request-time {
  173. font-size: 12px;
  174. margin-top: 7px;
  175. }
  176. }
  177. #song-duration {
  178. font-size: 20px;
  179. }
  180. .edit-icon {
  181. color: var(--primary-color);
  182. }
  183. }
  184. </style>