CreatePlaylist.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <script setup lang="ts">
  2. import { defineAsyncComponent, ref, onBeforeUnmount } from "vue";
  3. import Toast from "toasters";
  4. import validation from "@/validation";
  5. import { useWebsocketsStore } from "@/stores/websockets";
  6. import { useModalsStore } from "@/stores/modals";
  7. const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
  8. const props = defineProps({
  9. modalUuid: { type: String, required: true },
  10. admin: { type: Boolean, default: false }
  11. });
  12. const playlist = ref({
  13. displayName: "",
  14. privacy: "public",
  15. songs: []
  16. });
  17. const { openModal, closeCurrentModal } = useModalsStore();
  18. const { socket } = useWebsocketsStore();
  19. const createPlaylist = () => {
  20. const { displayName } = playlist.value;
  21. if (!validation.isLength(displayName, 1, 64))
  22. return new Toast("Display name must have between 1 and 64 characters.");
  23. if (!validation.regex.ascii.test(displayName))
  24. return new Toast(
  25. "Invalid display name format. Only ASCII characters are allowed."
  26. );
  27. return socket.dispatch(
  28. "playlists.create",
  29. { ...playlist.value, admin: props.admin },
  30. res => {
  31. new Toast(res.message);
  32. if (res.status === "success") {
  33. closeCurrentModal();
  34. if (!window.addToPlaylistDropdown) {
  35. openModal({
  36. modal: "editPlaylist",
  37. props: { playlistId: res.data.playlistId }
  38. });
  39. }
  40. }
  41. }
  42. );
  43. };
  44. onBeforeUnmount(() => {
  45. if (window.addToPlaylistDropdown)
  46. window.addToPlaylistDropdown.tippy.setProps({
  47. zIndex: 9999,
  48. hideOnClick: true
  49. });
  50. window.addToPlaylistDropdown = null;
  51. });
  52. </script>
  53. <template>
  54. <modal
  55. :title="admin ? 'Create Admin Playlist' : 'Create Playlist'"
  56. :size="'slim'"
  57. >
  58. <template #body>
  59. <p class="control is-expanded">
  60. <label class="label">Display Name</label>
  61. <input
  62. v-model="playlist.displayName"
  63. class="input"
  64. type="text"
  65. placeholder="Enter display name..."
  66. autofocus
  67. @keyup.enter="createPlaylist()"
  68. />
  69. </p>
  70. <div class="control" id="privacy-selection">
  71. <label class="label">Privacy</label>
  72. <p class="control is-expanded select">
  73. <select v-model="playlist.privacy">
  74. <option value="private">Private</option>
  75. <option value="public" selected>Public</option>
  76. </select>
  77. </p>
  78. </div>
  79. </template>
  80. <template #footer>
  81. <a class="button is-info" @click="createPlaylist()"
  82. ><i class="material-icons icon-with-button">create</i>Create
  83. Playlist</a
  84. >
  85. </template>
  86. </modal>
  87. </template>