CreatePlaylist.vue 2.7 KB

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