Playlists.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <template>
  2. <div>
  3. <metadata title="Admin | Playlists" />
  4. <div class="container">
  5. <button
  6. class="button is-primary"
  7. @click="deleteOrphanedStationPlaylists()"
  8. >
  9. Delete orphaned station playlists
  10. </button>
  11. <br />
  12. <br />
  13. <table class="table is-striped">
  14. <thead>
  15. <tr>
  16. <td>Display name</td>
  17. <td>Type</td>
  18. <td>Is user modifiable</td>
  19. <td>Songs #</td>
  20. <td>Playlist length</td>
  21. <td>Created by</td>
  22. <td>Created at</td>
  23. <td>Created for</td>
  24. <td>Playlist id</td>
  25. <td>Options</td>
  26. </tr>
  27. </thead>
  28. <tbody>
  29. <tr v-for="playlist in playlists" :key="playlist._id">
  30. <td>{{ playlist.displayName }}</td>
  31. <td>{{ playlist.type }}</td>
  32. <td>{{ playlist.isUserModifiable }}</td>
  33. <td>{{ playlist.songs.length }}</td>
  34. <td>{{ totalLengthForPlaylist(playlist.songs) }}</td>
  35. <td v-if="playlist.createdBy === 'Musare'">Musare</td>
  36. <td v-else>
  37. <user-id-to-username
  38. :user-id="playlist.createdBy"
  39. :link="true"
  40. />
  41. </td>
  42. <td :title="new Date(playlist.createdAt)">
  43. {{ getDateFormatted(playlist.createdAt) }}
  44. </td>
  45. <td>{{ playlist.createdFor }}</td>
  46. <td>{{ playlist._id }}</td>
  47. <td>
  48. <button
  49. class="button is-primary"
  50. @click="edit(playlist._id)"
  51. >
  52. View
  53. </button>
  54. </td>
  55. </tr>
  56. </tbody>
  57. </table>
  58. </div>
  59. <edit-playlist v-if="modals.admin.editPlaylist" sector="admin" />
  60. <report v-if="modals.station.report" />
  61. <edit-song
  62. v-if="modals.admin.editSong"
  63. :song-id="editingSongId"
  64. song-type="songs"
  65. />
  66. </div>
  67. </template>
  68. <script>
  69. import { mapState, mapActions, mapGetters } from "vuex";
  70. import Toast from "toasters";
  71. import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
  72. import ws from "../../../ws";
  73. import utils from "../../../../js/utils";
  74. export default {
  75. components: {
  76. EditPlaylist: () =>
  77. import("../../../components/modals/EditPlaylist/index.vue"),
  78. UserIdToUsername,
  79. Report: () => import("../../../components/modals/Report.vue"),
  80. EditSong: () => import("../../../components/modals/EditSong.vue")
  81. },
  82. data() {
  83. return {
  84. utils,
  85. playlists: [],
  86. editingSongId: ""
  87. };
  88. },
  89. computed: {
  90. ...mapState("modalVisibility", {
  91. modals: state => state.modals
  92. }),
  93. ...mapGetters({
  94. socket: "websockets/getSocket"
  95. })
  96. },
  97. mounted() {
  98. if (this.socket.readyState === 1) this.init();
  99. ws.onConnect(() => this.init());
  100. },
  101. methods: {
  102. edit(playlistId) {
  103. this.editPlaylist(playlistId);
  104. this.openModal({ sector: "admin", modal: "editPlaylist" });
  105. },
  106. init() {
  107. this.socket.dispatch("playlists.index", res => {
  108. if (res.status === "success") {
  109. this.playlists = res.data;
  110. // if (this.$route.query.userId) {
  111. // const user = this.users.find(
  112. // user => user._id === this.$route.query.userId
  113. // );
  114. // if (user) this.edit(user);
  115. // }
  116. }
  117. });
  118. this.socket.dispatch("apis.joinAdminRoom", "playlists", () => {});
  119. },
  120. getDateFormatted(createdAt) {
  121. const date = new Date(createdAt);
  122. const year = date.getFullYear();
  123. const month = `${date.getMonth() + 1}`.padStart(2, 0);
  124. const day = `${date.getDate()}`.padStart(2, 0);
  125. const hour = `${date.getHours()}`.padStart(2, 0);
  126. const minute = `${date.getMinutes()}`.padStart(2, 0);
  127. return `${year}-${month}-${day} ${hour}:${minute}`;
  128. },
  129. totalLengthForPlaylist(songs) {
  130. let length = 0;
  131. songs.forEach(song => {
  132. length += song.duration;
  133. });
  134. return this.utils.formatTimeLong(length);
  135. },
  136. deleteOrphanedStationPlaylists() {
  137. this.socket.dispatch(
  138. "playlists.deleteOrphanedStationPlaylists",
  139. res => {
  140. if (res.status === "success") {
  141. new Toast({
  142. content: `${res.message}`,
  143. timeout: 4000
  144. });
  145. } else {
  146. new Toast({
  147. content: `Error: ${res.message}`,
  148. timeout: 8000
  149. });
  150. }
  151. }
  152. );
  153. },
  154. ...mapActions("modalVisibility", ["openModal"]),
  155. ...mapActions("user/playlists", ["editPlaylist"])
  156. }
  157. };
  158. </script>
  159. <style lang="scss" scoped>
  160. .night-mode {
  161. .table {
  162. color: var(--light-grey-2);
  163. background-color: var(--dark-grey-3);
  164. thead tr {
  165. background: var(--dark-grey-3);
  166. td {
  167. color: var(--white);
  168. }
  169. }
  170. tbody tr:hover {
  171. background-color: var(--dark-grey-4) !important;
  172. }
  173. tbody tr:nth-child(even) {
  174. background-color: var(--dark-grey-2);
  175. }
  176. strong {
  177. color: var(--light-grey-2);
  178. }
  179. }
  180. }
  181. body {
  182. font-family: "Hind", sans-serif;
  183. }
  184. td {
  185. vertical-align: middle;
  186. }
  187. .is-primary:focus {
  188. background-color: var(--primary-color) !important;
  189. }
  190. </style>