AddSongToQueue.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <template>
  2. <modal title="Add Song To Queue">
  3. <div slot="body">
  4. <aside class="menu" v-if="loggedIn && $parent.type === 'community'">
  5. <ul class="menu-list">
  6. <li v-for="(playlist, index) in playlists" :key="index">
  7. <a
  8. href="#"
  9. target="_blank"
  10. v-on:click="$parent.editPlaylist(playlist._id)"
  11. >{{ playlist.displayName }}</a
  12. >
  13. <div class="controls">
  14. <a
  15. href="#"
  16. v-on:click="selectPlaylist(playlist._id)"
  17. v-if="!isPlaylistSelected(playlist._id)"
  18. >
  19. <i class="material-icons">panorama_fish_eye</i>
  20. </a>
  21. <a
  22. href="#"
  23. v-on:click="unSelectPlaylist()"
  24. v-if="isPlaylistSelected(playlist._id)"
  25. >
  26. <i class="material-icons">lens</i>
  27. </a>
  28. </div>
  29. </li>
  30. </ul>
  31. <br />
  32. </aside>
  33. <div class="control is-grouped">
  34. <p class="control is-expanded">
  35. <input
  36. class="input"
  37. type="text"
  38. placeholder="YouTube Query"
  39. v-model="querySearch"
  40. autofocus
  41. @keyup.enter="submitQuery()"
  42. />
  43. </p>
  44. <p class="control">
  45. <a
  46. class="button is-info"
  47. v-on:click="submitQuery()"
  48. href="#"
  49. >Search</a
  50. >
  51. </p>
  52. </div>
  53. <div class="control is-grouped" v-if="$parent.type === 'official'">
  54. <p class="control is-expanded">
  55. <input
  56. class="input"
  57. type="text"
  58. placeholder="YouTube Playlist URL"
  59. v-model="importQuery"
  60. @keyup.enter="importPlaylist()"
  61. />
  62. </p>
  63. <p class="control">
  64. <a
  65. class="button is-info"
  66. v-on:click="importPlaylist()"
  67. href="#"
  68. >Import</a
  69. >
  70. </p>
  71. </div>
  72. <table class="table" v-if="queryResults.length > 0">
  73. <tbody>
  74. <tr v-for="(result, index) in queryResults" :key="index">
  75. <td>
  76. <img :src="result.thumbnail" />
  77. </td>
  78. <td>{{ result.title }}</td>
  79. <td>
  80. <a
  81. class="button is-success"
  82. v-on:click="addSongToQueue(result.id)"
  83. href="#"
  84. >Add</a
  85. >
  86. </td>
  87. </tr>
  88. </tbody>
  89. </table>
  90. </div>
  91. </modal>
  92. </template>
  93. <script>
  94. import { mapState } from "vuex";
  95. import { Toast } from "vue-roaster";
  96. import Modal from "./Modal.vue";
  97. import io from "../../io";
  98. export default {
  99. data() {
  100. return {
  101. querySearch: "",
  102. queryResults: [],
  103. playlists: [],
  104. privatePlaylistQueueSelected: null,
  105. importQuery: ""
  106. };
  107. },
  108. computed: mapState({
  109. loggedIn: state => state.user.auth.loggedIn
  110. }),
  111. methods: {
  112. isPlaylistSelected(playlistId) {
  113. return this.privatePlaylistQueueSelected === playlistId;
  114. },
  115. selectPlaylist(playlistId) {
  116. if (this.$parent.type === "community") {
  117. this.privatePlaylistQueueSelected = playlistId;
  118. this.$parent.privatePlaylistQueueSelected = playlistId;
  119. this.$parent.addFirstPrivatePlaylistSongToQueue();
  120. }
  121. },
  122. unSelectPlaylist() {
  123. if (this.$parent.type === "community") {
  124. this.privatePlaylistQueueSelected = null;
  125. this.$parent.privatePlaylistQueueSelected = null;
  126. }
  127. },
  128. addSongToQueue(songId) {
  129. if (this.$parent.type === "community") {
  130. this.socket.emit(
  131. "stations.addToQueue",
  132. this.$parent.station._id,
  133. songId,
  134. data => {
  135. if (data.status !== "success")
  136. Toast.methods.addToast(
  137. `Error: ${data.message}`,
  138. 8000
  139. );
  140. else Toast.methods.addToast(`${data.message}`, 4000);
  141. }
  142. );
  143. } else {
  144. this.socket.emit("queueSongs.add", songId, data => {
  145. if (data.status !== "success")
  146. Toast.methods.addToast(`Error: ${data.message}`, 8000);
  147. else Toast.methods.addToast(`${data.message}`, 4000);
  148. });
  149. }
  150. },
  151. importPlaylist() {
  152. Toast.methods.addToast(
  153. "Starting to import your playlist. This can take some time to do.",
  154. 4000
  155. );
  156. this.socket.emit(
  157. "queueSongs.addSetToQueue",
  158. this.importQuery,
  159. res => {
  160. Toast.methods.addToast(res.message, 4000);
  161. }
  162. );
  163. },
  164. submitQuery() {
  165. let query = this.querySearch;
  166. if (query.indexOf("&index=") !== -1) {
  167. query = query.split("&index=");
  168. query.pop();
  169. query = query.join("");
  170. }
  171. if (query.indexOf("&list=") !== -1) {
  172. query = query.split("&list=");
  173. query.pop();
  174. query = query.join("");
  175. }
  176. this.socket.emit("apis.searchYoutube", query, res => {
  177. // check for error
  178. const { data } = res;
  179. this.queryResults = [];
  180. for (let i = 0; i < data.items.length; i += 1) {
  181. this.queryResults.push({
  182. id: data.items[i].id.videoId,
  183. url: `https://www.youtube.com/watch?v=${this.id}`,
  184. title: data.items[i].snippet.title,
  185. thumbnail: data.items[i].snippet.thumbnails.default.url
  186. });
  187. }
  188. });
  189. }
  190. },
  191. mounted() {
  192. io.getSocket(socket => {
  193. this.socket = socket;
  194. this.socket.emit("playlists.indexForUser", res => {
  195. if (res.status === "success") this.playlists = res.data;
  196. });
  197. this.privatePlaylistQueueSelected = this.$parent.privatePlaylistQueueSelected;
  198. });
  199. },
  200. components: { Modal }
  201. };
  202. </script>
  203. <style lang="scss" scoped>
  204. @import "styles/global.scss";
  205. tr td {
  206. vertical-align: middle;
  207. img {
  208. width: 55px;
  209. }
  210. }
  211. .table {
  212. margin-bottom: 0;
  213. }
  214. </style>