AddSongToQueue.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. const _this = this;
  117. if (_this.$parent.type === "community") {
  118. _this.privatePlaylistQueueSelected = playlistId;
  119. _this.$parent.privatePlaylistQueueSelected = playlistId;
  120. _this.$parent.addFirstPrivatePlaylistSongToQueue();
  121. }
  122. },
  123. unSelectPlaylist() {
  124. const _this = this;
  125. if (_this.$parent.type === "community") {
  126. _this.privatePlaylistQueueSelected = null;
  127. _this.$parent.privatePlaylistQueueSelected = null;
  128. }
  129. },
  130. addSongToQueue(songId) {
  131. const _this = this;
  132. if (_this.$parent.type === "community") {
  133. _this.socket.emit(
  134. "stations.addToQueue",
  135. _this.$parent.station._id,
  136. songId,
  137. data => {
  138. if (data.status !== "success")
  139. Toast.methods.addToast(
  140. `Error: ${data.message}`,
  141. 8000
  142. );
  143. else Toast.methods.addToast(`${data.message}`, 4000);
  144. }
  145. );
  146. } else {
  147. _this.socket.emit("queueSongs.add", songId, data => {
  148. if (data.status !== "success")
  149. Toast.methods.addToast(`Error: ${data.message}`, 8000);
  150. else Toast.methods.addToast(`${data.message}`, 4000);
  151. });
  152. }
  153. },
  154. importPlaylist() {
  155. const _this = this;
  156. Toast.methods.addToast(
  157. "Starting to import your playlist. This can take some time to do.",
  158. 4000
  159. );
  160. this.socket.emit(
  161. "queueSongs.addSetToQueue",
  162. _this.importQuery,
  163. res => {
  164. Toast.methods.addToast(res.message, 4000);
  165. }
  166. );
  167. },
  168. submitQuery() {
  169. const _this = this;
  170. let query = _this.querySearch;
  171. if (query.indexOf("&index=") !== -1) {
  172. query = query.split("&index=");
  173. query.pop();
  174. query = query.join("");
  175. }
  176. if (query.indexOf("&list=") !== -1) {
  177. query = query.split("&list=");
  178. query.pop();
  179. query = query.join("");
  180. }
  181. _this.socket.emit("apis.searchYoutube", query, res => {
  182. // check for error
  183. const { data } = res;
  184. _this.queryResults = [];
  185. for (let i = 0; i < data.items.length; i += 1) {
  186. _this.queryResults.push({
  187. id: data.items[i].id.videoId,
  188. url: `https://www.youtube.com/watch?v=${this.id}`,
  189. title: data.items[i].snippet.title,
  190. thumbnail: data.items[i].snippet.thumbnails.default.url
  191. });
  192. }
  193. });
  194. }
  195. },
  196. mounted() {
  197. const _this = this;
  198. io.getSocket(socket => {
  199. _this.socket = socket;
  200. _this.socket.emit("playlists.indexForUser", res => {
  201. if (res.status === "success") _this.playlists = res.data;
  202. });
  203. _this.privatePlaylistQueueSelected =
  204. _this.$parent.privatePlaylistQueueSelected;
  205. });
  206. },
  207. components: { Modal }
  208. };
  209. </script>
  210. <style lang="scss" scoped>
  211. tr td {
  212. vertical-align: middle;
  213. img {
  214. width: 55px;
  215. }
  216. }
  217. .table {
  218. margin-bottom: 0;
  219. }
  220. </style>