AddSongToQueue.vue 5.8 KB

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