EditAlbum.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <script setup lang="ts">
  2. import Toast from "toasters";
  3. import { defineAsyncComponent, ref, onMounted } from "vue";
  4. import { GenericResponse } from "@musare_types/actions/GenericActions";
  5. import VueJsonPretty from "vue-json-pretty";
  6. import { useForm } from "@/composables/useForm";
  7. import { useWebsocketsStore } from "@/stores/websockets";
  8. import { useModalsStore } from "@/stores/modals";
  9. const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
  10. const SaveButton = defineAsyncComponent(
  11. () => import("@/components/SaveButton.vue")
  12. );
  13. const props = defineProps({
  14. modalUuid: { type: String, required: true },
  15. createAlbum: { type: Boolean, default: false },
  16. albumId: { type: String, default: null },
  17. sector: { type: String, default: "admin" }
  18. });
  19. const { socket } = useWebsocketsStore();
  20. const { closeCurrentModal } = useModalsStore();
  21. const createdBy = ref();
  22. const createdAt = ref(0);
  23. const hideMusicbrainzData = ref(true);
  24. const { inputs, save, setOriginalValue } = useForm(
  25. {
  26. name: {
  27. value: ""
  28. },
  29. musicbrainzIdentifier: {
  30. value: ""
  31. },
  32. musicbrainzData: {
  33. value: {}
  34. }
  35. },
  36. ({ status, messages, values }, resolve, reject) => {
  37. if (status === "success") {
  38. const data = {
  39. name: values.name,
  40. musicbrainzIdentifier: values.musicbrainzIdentifier,
  41. musicbrainzData: values.musicbrainzData
  42. };
  43. const cb = (res: GenericResponse) => {
  44. new Toast(res.message);
  45. if (res.status === "success") resolve();
  46. else reject(new Error(res.message));
  47. };
  48. if (props.createAlbum) socket.dispatch("albums.create", data, cb);
  49. else socket.dispatch("albums.update", props.albumId, data, cb);
  50. } else {
  51. if (status === "unchanged") new Toast(messages.unchanged);
  52. else if (status === "error")
  53. Object.values(messages).forEach(message => {
  54. new Toast({ content: message, timeout: 8000 });
  55. });
  56. resolve();
  57. }
  58. },
  59. {
  60. modalUuid: props.modalUuid
  61. }
  62. );
  63. onMounted(() => {
  64. console.log(111);
  65. socket.onConnect(() => {
  66. console.log(222);
  67. if (props.albumId && !props.createAlbum) {
  68. socket.dispatch(`albums.getAlbumFromId`, props.albumId, res => {
  69. // res: GetAlbumResponse
  70. if (res.status === "success") {
  71. setOriginalValue({
  72. name: res.data.album.name,
  73. musicbrainzIdentifier:
  74. res.data.album.musicbrainzIdentifier,
  75. musicbrainzData: res.data.album.musicbrainzData ?? {}
  76. });
  77. createdBy.value = res.data.album.createdBy;
  78. createdAt.value = res.data.album.createdAt;
  79. } else {
  80. new Toast("Album with that ID not found.");
  81. closeCurrentModal();
  82. }
  83. });
  84. }
  85. });
  86. });
  87. const saveAlbum = (close?: boolean) => {
  88. save(() => {
  89. if (close) {
  90. closeCurrentModal();
  91. }
  92. });
  93. };
  94. const getMusicbrainzAlbumData = musicbrainzIdentifier => {
  95. socket.dispatch(
  96. "albums.getMusicbrainzAlbum",
  97. musicbrainzIdentifier,
  98. res => {
  99. new Toast("Successfully got data");
  100. inputs.value.musicbrainzData.value = res.data;
  101. }
  102. );
  103. };
  104. </script>
  105. <template>
  106. <modal
  107. class="edit-album-modal"
  108. :title="createAlbum ? 'Create Album' : 'Edit Album'"
  109. :size="'wide'"
  110. :split="true"
  111. >
  112. <template #body>
  113. <div class="flex flex-row w-full">
  114. <div class="flex flex-column gap-4 w-2/3">
  115. <div>
  116. <div class="control is-grouped">
  117. <div class="name-container">
  118. <label class="label">Name</label>
  119. <p class="control has-addons">
  120. <input
  121. class="input"
  122. type="text"
  123. :ref="el => (inputs['name'].ref = el)"
  124. v-model="inputs['name'].value"
  125. placeholder="Enter album name..."
  126. />
  127. </p>
  128. </div>
  129. </div>
  130. </div>
  131. <div>
  132. <div class="control is-grouped gap-4">
  133. <div class="musicbrainz-identifier-container">
  134. <label class="label"
  135. >MusicBrainz identifier</label
  136. >
  137. <input
  138. class="input"
  139. type="text"
  140. :ref="
  141. el =>
  142. (inputs[
  143. 'musicbrainzIdentifier'
  144. ].ref = el)
  145. "
  146. v-model="
  147. inputs['musicbrainzIdentifier'].value
  148. "
  149. placeholder="Enter MusicBrainz identifier..."
  150. />
  151. </div>
  152. <button
  153. class="button is-primary button-bottom"
  154. @click="
  155. getMusicbrainzAlbumData(
  156. inputs['musicbrainzIdentifier'].value
  157. )
  158. "
  159. >
  160. Get MusicBrainz album data
  161. </button>
  162. </div>
  163. <div>
  164. <div class="flex flex-row gap-4">
  165. <p class="text-vcenter">MusicBrainz data</p>
  166. <button
  167. class="button is-primary"
  168. @click="
  169. hideMusicbrainzData =
  170. !hideMusicbrainzData
  171. "
  172. >
  173. <span v-show="hideMusicbrainzData"
  174. >Show MusicBrainz data</span
  175. >
  176. <span v-show="!hideMusicbrainzData"
  177. >Hide MusicBrainz data</span
  178. >
  179. </button>
  180. </div>
  181. <vue-json-pretty
  182. :data="inputs['musicbrainzData'].value"
  183. :show-length="true"
  184. v-if="!hideMusicbrainzData"
  185. ></vue-json-pretty>
  186. </div>
  187. </div>
  188. </div>
  189. <div class="flex flex-column w-1/3"></div>
  190. </div>
  191. </template>
  192. <template #footer>
  193. <div>
  194. <save-button
  195. :default-message="`${createAlbum ? 'Create' : 'Update'} Album`"
  196. @clicked="saveAlbum()"
  197. />
  198. <save-button
  199. :default-message="`${createAlbum ? 'Create' : 'Update'} and close`"
  200. @clicked="saveAlbum(true)"
  201. />
  202. </div>
  203. </template>
  204. </modal>
  205. </template>
  206. <style lang="less"></style>
  207. <style lang="less" scoped></style>