QueueItem.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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.simpleSong &&
  62. song.likes !== -1 &&
  63. song.dislikes !== -1
  64. "
  65. class="material-icons report-icon"
  66. @click="reportQueueSong(song)"
  67. >
  68. flag
  69. </i>
  70. <i
  71. class="material-icons"
  72. @click="showPlaylistDropdown = !showPlaylistDropdown"
  73. >queue</i
  74. >
  75. <i
  76. v-if="
  77. $parent.isAdminOnly() &&
  78. !song.simpleSong &&
  79. song.likes !== -1 &&
  80. song.dislikes !== -1
  81. "
  82. class="material-icons edit-icon"
  83. @click="$parent.$parent.$parent.editSong(song)"
  84. >
  85. edit
  86. </i>
  87. <i
  88. v-if="
  89. station.type === 'community' &&
  90. ($parent.isOwnerOnly() || $parent.isAdminOnly())
  91. "
  92. class="material-icons delete-icon"
  93. @click="$parent.removeFromQueue(song.songId)"
  94. >delete_forever</i
  95. >
  96. </div>
  97. </div>
  98. </div>
  99. </template>
  100. <script>
  101. import { mapActions } from "vuex";
  102. import { formatDistance, parseISO } from "date-fns";
  103. import AddToPlaylistDropdown from "../../../../../components/ui/AddToPlaylistDropdown.vue";
  104. import UserIdToUsername from "../../../../../components/common/UserIdToUsername.vue";
  105. import utils from "../../../../../../js/utils";
  106. export default {
  107. components: { UserIdToUsername, AddToPlaylistDropdown },
  108. props: {
  109. song: {
  110. type: Object,
  111. default: () => {}
  112. },
  113. station: {
  114. type: Object,
  115. default: () => {
  116. return { type: "community", partyMode: false };
  117. }
  118. }
  119. },
  120. data() {
  121. return {
  122. utils,
  123. showPlaylistDropdown: false
  124. };
  125. },
  126. methods: {
  127. reportQueueSong(song) {
  128. this.updateReportQueueSong(song);
  129. this.openModal({ sector: "station", modal: "report" });
  130. },
  131. ...mapActions("station", ["updateReportQueueSong"]),
  132. ...mapActions("modalVisibility", ["openModal"]),
  133. formatDistance,
  134. parseISO
  135. }
  136. };
  137. </script>
  138. <style lang="scss" scoped>
  139. .night-mode {
  140. .queue-item {
  141. background-color: var(--dark-grey-2) !important;
  142. border: 0 !important;
  143. }
  144. }
  145. /deep/ #nav-dropdown {
  146. margin-top: 36px;
  147. /deep/ .nav-dropdown-items {
  148. position: absolute;
  149. right: 0;
  150. }
  151. }
  152. .queue-item {
  153. #thumbnail-and-info,
  154. #duration-and-actions {
  155. display: flex;
  156. align-items: center;
  157. }
  158. #duration-and-actions {
  159. margin-left: 5px;
  160. .universal-item-actions div i {
  161. margin-left: 5px;
  162. }
  163. }
  164. #thumbnail-and-info {
  165. width: calc(100% - 120px);
  166. }
  167. #song-info {
  168. display: flex;
  169. flex-direction: column;
  170. justify-content: center;
  171. margin-left: 20px;
  172. width: calc(100% - 65px);
  173. *:not(i) {
  174. margin: 0;
  175. font-family: Karla, Arial, sans-serif;
  176. }
  177. #song-request-time {
  178. font-size: 12px;
  179. margin-top: 7px;
  180. }
  181. }
  182. #song-duration {
  183. font-size: 20px;
  184. }
  185. .edit-icon {
  186. color: var(--primary-color);
  187. }
  188. }
  189. </style>