Songs.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <div class="search">
  3. <div class="musare-search">
  4. <label class="label"> Search for a song on Musare </label>
  5. <div class="control is-grouped input-with-button">
  6. <p class="control is-expanded">
  7. <input
  8. class="input"
  9. type="text"
  10. placeholder="Enter your song query here..."
  11. v-model="musareSearch.query"
  12. @keyup.enter="searchForMusareSongs(1)"
  13. />
  14. </p>
  15. <p class="control">
  16. <a class="button is-info" @click="searchForMusareSongs(1)"
  17. ><i class="material-icons icon-with-button">search</i
  18. >Search</a
  19. >
  20. </p>
  21. </div>
  22. <div v-if="musareSearch.results.length > 0">
  23. <song-item
  24. v-for="song in musareSearch.results"
  25. :key="song._id"
  26. :song="song"
  27. >
  28. <template #actions>
  29. <i
  30. class="material-icons add-to-queue-icon"
  31. v-if="station.partyMode && !station.locked"
  32. @click="addSongToQueue(song.youtubeId)"
  33. content="Add Song to Queue"
  34. v-tippy
  35. >queue</i
  36. >
  37. </template>
  38. </song-item>
  39. <button
  40. v-if="resultsLeftCount > 0"
  41. class="button is-primary load-more-button"
  42. @click="searchForMusareSongs(musareSearch.page + 1)"
  43. >
  44. Load {{ nextPageResultsCount }} more results
  45. </button>
  46. </div>
  47. </div>
  48. <div class="youtube-search">
  49. <label class="label"> Search for a song on YouTube </label>
  50. <div class="control is-grouped input-with-button">
  51. <p class="control is-expanded">
  52. <input
  53. class="input"
  54. type="text"
  55. placeholder="Enter your YouTube query here..."
  56. v-model="youtubeSearch.songs.query"
  57. autofocus
  58. @keyup.enter="searchForSongs()"
  59. />
  60. </p>
  61. <p class="control">
  62. <a class="button is-info" @click.prevent="searchForSongs()"
  63. ><i class="material-icons icon-with-button">search</i
  64. >Search</a
  65. >
  66. </p>
  67. </div>
  68. <div
  69. v-if="youtubeSearch.songs.results.length > 0"
  70. id="song-query-results"
  71. >
  72. <search-query-item
  73. v-for="(result, index) in youtubeSearch.songs.results"
  74. :key="result.id"
  75. :result="result"
  76. >
  77. <template #actions>
  78. <transition name="search-query-actions" mode="out-in">
  79. <i
  80. v-if="result.isAddedToQueue"
  81. class="material-icons added-to-queue-icon"
  82. content="Song Added to Queue"
  83. v-tippy
  84. key="added-to-queue"
  85. >library_add_check</i
  86. >
  87. <i
  88. v-else
  89. class="material-icons add-to-queue-icon"
  90. @click.prevent="
  91. addSongToQueue(result.id, index)
  92. "
  93. content="Add Song to Queue"
  94. v-tippy
  95. key="add-to-queue"
  96. >queue</i
  97. >
  98. </transition>
  99. </template>
  100. </search-query-item>
  101. <a
  102. class="button is-primary load-more-button"
  103. @click.prevent="loadMoreSongs()"
  104. >
  105. Load more...
  106. </a>
  107. </div>
  108. </div>
  109. </div>
  110. </template>
  111. <script>
  112. import { mapState, mapGetters } from "vuex";
  113. import Toast from "toasters";
  114. import SearchYoutube from "@/mixins/SearchYoutube.vue";
  115. import SearchMusare from "@/mixins/SearchMusare.vue";
  116. import SongItem from "@/components/SongItem.vue";
  117. import SearchQueryItem from "../../../SearchQueryItem.vue";
  118. export default {
  119. components: {
  120. SongItem,
  121. SearchQueryItem
  122. },
  123. mixins: [SearchYoutube, SearchMusare],
  124. computed: {
  125. ...mapState("modals/manageStation", {
  126. station: state => state.station,
  127. originalStation: state => state.originalStation
  128. }),
  129. ...mapGetters({
  130. socket: "websockets/getSocket"
  131. })
  132. },
  133. methods: {
  134. addSongToQueue(youtubeId, index) {
  135. if (this.station.type === "community") {
  136. this.socket.dispatch(
  137. "stations.addToQueue",
  138. this.station._id,
  139. youtubeId,
  140. res => {
  141. if (res.status !== "success")
  142. new Toast(`Error: ${res.message}`);
  143. else {
  144. if (index)
  145. this.youtubeSearch.songs.results[
  146. index
  147. ].isAddedToQueue = true;
  148. new Toast(res.message);
  149. }
  150. }
  151. );
  152. } else {
  153. this.socket.dispatch("songs.request", youtubeId, res => {
  154. if (res.status !== "success")
  155. new Toast(`Error: ${res.message}`);
  156. else {
  157. this.youtubeSearch.songs.results[
  158. index
  159. ].isAddedToQueue = true;
  160. new Toast(res.message);
  161. }
  162. });
  163. }
  164. }
  165. }
  166. };
  167. </script>
  168. <style lang="less">
  169. .search {
  170. .musare-search,
  171. .universal-item:not(:last-of-type) {
  172. margin-bottom: 10px;
  173. }
  174. .load-more-button {
  175. width: 100%;
  176. margin-top: 10px;
  177. }
  178. }
  179. </style>