AddSongToQueue.vue 5.2 KB

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