AddSongToQueue.vue 5.2 KB

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