Settings.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <script setup lang="ts">
  2. import Toast from "toasters";
  3. import { storeToRefs } from "pinia";
  4. import validation from "@/validation";
  5. import { useWebsocketsStore } from "@/stores/websockets";
  6. import { useUserAuthStore } from "@/stores/userAuth";
  7. import { useEditPlaylistStore } from "@/stores/editPlaylist";
  8. const props = defineProps({
  9. modalUuid: { type: String, default: "" }
  10. });
  11. const userAuthStore = useUserAuthStore();
  12. const { loggedIn, userId } = storeToRefs(userAuthStore);
  13. const { hasPermission } = userAuthStore;
  14. const { socket } = useWebsocketsStore();
  15. const editPlaylistStore = useEditPlaylistStore(props);
  16. const { playlist } = storeToRefs(editPlaylistStore);
  17. const isOwner = () =>
  18. loggedIn.value && userId.value === playlist.value.createdBy;
  19. const isEditable = permission =>
  20. ((playlist.value.type === "user" ||
  21. playlist.value.type === "user-liked" ||
  22. playlist.value.type === "user-disliked") &&
  23. (isOwner() || hasPermission(permission))) ||
  24. (playlist.value.type === "genre" &&
  25. permission === "playlists.updatePrivacy" &&
  26. hasPermission(permission));
  27. const renamePlaylist = () => {
  28. const { displayName } = playlist.value;
  29. if (!validation.isLength(displayName, 2, 32))
  30. return new Toast("Display name must have between 2 and 32 characters.");
  31. if (!validation.regex.ascii.test(displayName))
  32. return new Toast(
  33. "Invalid display name format. Only ASCII characters are allowed."
  34. );
  35. return socket.dispatch(
  36. "playlists.updateDisplayName",
  37. playlist.value._id,
  38. playlist.value.displayName,
  39. res => {
  40. new Toast(res.message);
  41. }
  42. );
  43. };
  44. const updatePrivacy = () => {
  45. const { privacy } = playlist.value;
  46. if (privacy === "public" || privacy === "private") {
  47. socket.dispatch(
  48. playlist.value.type === "genre"
  49. ? "playlists.updatePrivacyAdmin"
  50. : "playlists.updatePrivacy",
  51. playlist.value._id,
  52. privacy,
  53. res => {
  54. new Toast(res.message);
  55. }
  56. );
  57. }
  58. };
  59. </script>
  60. <template>
  61. <div class="settings-tab section">
  62. <div
  63. v-if="
  64. isEditable('playlists.updateDisplayName') &&
  65. !(
  66. playlist.type === 'user-liked' ||
  67. playlist.type === 'user-disliked'
  68. )
  69. "
  70. >
  71. <label class="label"> Change display name </label>
  72. <div class="control is-grouped input-with-button">
  73. <p class="control is-expanded">
  74. <input
  75. v-model="playlist.displayName"
  76. class="input"
  77. type="text"
  78. placeholder="Playlist Display Name"
  79. @keyup.enter="renamePlaylist()"
  80. />
  81. </p>
  82. <p class="control">
  83. <button
  84. class="button is-info"
  85. @click.prevent="renamePlaylist()"
  86. >
  87. Rename
  88. </button>
  89. </p>
  90. </div>
  91. </div>
  92. <div v-if="isEditable('playlists.updatePrivacy')">
  93. <label class="label"> Change privacy </label>
  94. <div class="control is-grouped input-with-button">
  95. <div class="control is-expanded select">
  96. <select v-model="playlist.privacy">
  97. <option value="private">Private</option>
  98. <option value="public">Public</option>
  99. </select>
  100. </div>
  101. <p class="control">
  102. <button
  103. class="button is-info"
  104. @click.prevent="updatePrivacy()"
  105. >
  106. Update Privacy
  107. </button>
  108. </p>
  109. </div>
  110. </div>
  111. </div>
  112. </template>
  113. <style lang="less" scoped>
  114. @media screen and (max-width: 1300px) {
  115. .section {
  116. max-width: 100% !important;
  117. }
  118. }
  119. </style>