AddSongToQueue.vue 5.2 KB

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