QueueSongs.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <template>
  2. <div>
  3. <div class="container">
  4. <input type="text" class="input" v-model="searchQuery" placeholder="Search for Songs" />
  5. <br />
  6. <br />
  7. <table class="table is-striped">
  8. <thead>
  9. <tr>
  10. <td>Thumbnail</td>
  11. <td>Title</td>
  12. <td>YouTube ID</td>
  13. <td>Artists</td>
  14. <td>Genres</td>
  15. <td>Requested By</td>
  16. <td>Options</td>
  17. </tr>
  18. </thead>
  19. <tbody>
  20. <tr v-for="(song, index) in filteredSongs" :key="index">
  21. <td>
  22. <img
  23. class="song-thumbnail"
  24. :src="song.thumbnail"
  25. onerror="this.src='/assets/notes-transparent.png'"
  26. />
  27. </td>
  28. <td>
  29. <strong>{{ song.title }}</strong>
  30. </td>
  31. <td>{{ song.songId }}</td>
  32. <td>{{ song.artists.join(', ') }}</td>
  33. <td>{{ song.genres.join(', ') }}</td>
  34. <td>{{ song.requestedBy }}</td>
  35. <td>
  36. <button class="button is-primary" v-on:click="edit(song, index)">Edit</button>
  37. <button class="button is-success" v-on:click="add(song)">Add</button>
  38. <button class="button is-danger" v-on:click="remove(song._id, index)">Remove</button>
  39. </td>
  40. </tr>
  41. </tbody>
  42. </table>
  43. </div>
  44. <nav class="pagination">
  45. <a class="button" href="#" v-on:click="getSet(position - 1)" v-if="position > 1">
  46. <i class="material-icons">navigate_before</i>
  47. </a>
  48. <a class="button" href="#" v-on:click="getSet(position + 1)" v-if="maxPosition > position">
  49. <i class="material-icons">navigate_next</i>
  50. </a>
  51. </nav>
  52. <edit-song v-if="modals.editSong"></edit-song>
  53. </div>
  54. </template>
  55. <script>
  56. import { mapState, mapActions } from "vuex";
  57. import { Toast } from "vue-roaster";
  58. import EditSong from "../Modals/EditSong.vue";
  59. import io from "../../io";
  60. export default {
  61. components: { EditSong },
  62. data() {
  63. return {
  64. position: 1,
  65. maxPosition: 1,
  66. searchQuery: "",
  67. songs: []
  68. };
  69. },
  70. computed: {
  71. filteredSongs: function() {
  72. return this.songs;
  73. // return this.songs.filter(song => song.indexOf(song.searchQuery) !== -1);
  74. },
  75. ...mapState("modals", {
  76. modals: state => state.modals.admin
  77. })
  78. },
  79. // watch: {
  80. // "modals.editSong": function(value) {
  81. // console.log(value);
  82. // if (value === false) this.stopVideo();
  83. // }
  84. // },
  85. methods: {
  86. getSet: function(position) {
  87. let _this = this;
  88. this.socket.emit("queueSongs.getSet", position, data => {
  89. _this.songs = data;
  90. this.position = position;
  91. });
  92. },
  93. edit: function(song, index) {
  94. console.log(song, index);
  95. let _this = this;
  96. let newSong = {};
  97. for (let n in song) newSong[n] = song[n];
  98. this.editSong({ index, song: newSong, type: "queueSongs" });
  99. this.toggleModal({ sector: "admin", modal: "editSong" });
  100. },
  101. add: function(song) {
  102. this.socket.emit("songs.add", song, res => {
  103. if (res.status == "success") Toast.methods.addToast(res.message, 2000);
  104. else Toast.methods.addToast(res.message, 4000);
  105. });
  106. },
  107. remove: function(id, index) {
  108. console.log("Removing ", id);
  109. this.socket.emit("queueSongs.remove", id, res => {
  110. if (res.status == "success") Toast.methods.addToast(res.message, 2000);
  111. else Toast.methods.addToast(res.message, 4000);
  112. });
  113. },
  114. init: function() {
  115. let _this = this;
  116. _this.socket.emit("queueSongs.index", data => {
  117. _this.songs = data.songs;
  118. _this.maxPosition = Math.round(data.maxLength / 50);
  119. });
  120. _this.socket.emit("apis.joinAdminRoom", "queue", data => {});
  121. },
  122. ...mapActions("admin/songs", ["stopVideo", "editSong"]),
  123. ...mapActions("modals", ["toggleModal"])
  124. },
  125. mounted: function() {
  126. let _this = this;
  127. io.getSocket(socket => {
  128. _this.socket = socket;
  129. if (_this.socket.connected) {
  130. _this.init();
  131. _this.socket.on("event:admin.queueSong.added", queueSong => {
  132. _this.songs.push(queueSong);
  133. });
  134. _this.socket.on("event:admin.queueSong.removed", songId => {
  135. _this.songs = _this.songs.filter(function(song) {
  136. return song._id !== songId;
  137. });
  138. });
  139. _this.socket.on("event:admin.queueSong.updated", updatedSong => {
  140. for (let i = 0; i < _this.songs.length; i++) {
  141. let song = _this.songs[i];
  142. if (song._id === updatedSong._id) {
  143. _this.songs.$set(i, updatedSong);
  144. }
  145. }
  146. });
  147. }
  148. io.onConnect(() => {
  149. _this.init();
  150. });
  151. });
  152. }
  153. };
  154. </script>
  155. <style lang='scss' scoped>
  156. .song-thumbnail {
  157. display: block;
  158. max-width: 50px;
  159. margin: 0 auto;
  160. }
  161. td {
  162. vertical-align: middle;
  163. }
  164. .is-primary:focus {
  165. background-color: #029ce3 !important;
  166. }
  167. </style>