Artists.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <script setup lang="ts">
  2. import { defineAsyncComponent, ref } from "vue";
  3. import Toast from "toasters";
  4. import { GenericResponse } from "@musare_types/actions/GenericActions";
  5. import { useWebsocketsStore } from "@/stores/websockets";
  6. import { useModalsStore } from "@/stores/modals";
  7. import { useUserAuthStore } from "@/stores/userAuth";
  8. import { TableColumn, TableFilter, TableEvents } from "@/types/advancedTable";
  9. import utils from "@/utils";
  10. const AdvancedTable = defineAsyncComponent(
  11. () => import("@/components/AdvancedTable.vue")
  12. );
  13. const QuickConfirm = defineAsyncComponent(
  14. () => import("@/components/QuickConfirm.vue")
  15. );
  16. const UserLink = defineAsyncComponent(
  17. () => import("@/components/UserLink.vue")
  18. );
  19. const { socket } = useWebsocketsStore();
  20. const columnDefault = ref<TableColumn>({
  21. sortable: true,
  22. hidable: true,
  23. defaultVisibility: "shown",
  24. draggable: true,
  25. resizable: true,
  26. minWidth: 150,
  27. maxWidth: 600
  28. });
  29. const columns = ref<TableColumn[]>([
  30. {
  31. name: "options",
  32. displayName: "Options",
  33. properties: ["_id"],
  34. sortable: false,
  35. hidable: false,
  36. resizable: false,
  37. minWidth: 85,
  38. defaultWidth: 85
  39. },
  40. {
  41. name: "name",
  42. displayName: "Name",
  43. properties: ["name"],
  44. sortProperty: "name"
  45. },
  46. {
  47. name: "musicbrainzIdentifier",
  48. displayName: "MusicBrainz identifier",
  49. properties: ["musicbrainzIdentifier"],
  50. sortProperty: "musicbrainzIdentifier"
  51. },
  52. {
  53. name: "createdBy",
  54. displayName: "Created By",
  55. properties: ["createdBy"],
  56. sortProperty: "createdBy",
  57. defaultWidth: 150
  58. },
  59. {
  60. name: "createdAt",
  61. displayName: "Created At",
  62. properties: ["createdAt"],
  63. sortProperty: "createdAt",
  64. defaultWidth: 150
  65. }
  66. ]);
  67. const filters = ref<TableFilter[]>([
  68. {
  69. name: "name",
  70. displayName: "Name",
  71. property: "name",
  72. filterTypes: ["contains", "exact", "regex"],
  73. defaultFilterType: "contains"
  74. },
  75. {
  76. name: "musicbrainzIdentifier",
  77. displayName: "MusicBrainz identifier",
  78. property: "musicbrainzIdentifier",
  79. filterTypes: ["contains", "exact", "regex"],
  80. defaultFilterType: "contains"
  81. },
  82. {
  83. name: "createdBy",
  84. displayName: "Created By",
  85. property: "createdBy",
  86. filterTypes: ["contains", "exact", "regex"],
  87. defaultFilterType: "contains"
  88. },
  89. {
  90. name: "createdAt",
  91. displayName: "Created At",
  92. property: "createdAt",
  93. filterTypes: ["datetimeBefore", "datetimeAfter"],
  94. defaultFilterType: "datetimeBefore"
  95. }
  96. ]);
  97. const events = ref<TableEvents>({
  98. adminRoom: "artists",
  99. updated: {
  100. event: "admin.artists.updated",
  101. id: "artist._id",
  102. item: "artist"
  103. },
  104. removed: {
  105. event: "admin.artists.deleted",
  106. id: "artistId"
  107. }
  108. });
  109. const { openModal } = useModalsStore();
  110. const { hasPermission } = useUserAuthStore();
  111. const remove = (id: string) => {
  112. socket.dispatch(
  113. "artist.remove",
  114. id,
  115. (res: GenericResponse) => new Toast(res.message)
  116. );
  117. };
  118. </script>
  119. <template>
  120. <div class="admin-tab container">
  121. <page-metadata title="Admin | Artists" />
  122. <div class="card tab-info">
  123. <div class="info-row">
  124. <h1>Artists</h1>
  125. <p>Create and update artists</p>
  126. </div>
  127. <div class="button-row">
  128. <button
  129. v-if="hasPermission('artists.create')"
  130. class="is-primary button"
  131. @click="
  132. openModal({
  133. modal: 'editArtist',
  134. props: { createArtist: true }
  135. })
  136. "
  137. >
  138. Create Artist
  139. </button>
  140. </div>
  141. </div>
  142. <advanced-table
  143. :column-default="columnDefault"
  144. :columns="columns"
  145. :filters="filters"
  146. data-action="artists.getData"
  147. name="admin-artists"
  148. :max-width="1200"
  149. :events="events"
  150. >
  151. <template #column-options="slotProps">
  152. <div class="row-options">
  153. <button
  154. v-if="hasPermission('artists.update')"
  155. class="button is-primary icon-with-button material-icons"
  156. @click="
  157. openModal({
  158. modal: 'editArtist',
  159. props: { artistId: slotProps.item._id }
  160. })
  161. "
  162. content="Edit Artist"
  163. v-tippy
  164. >
  165. edit
  166. </button>
  167. <quick-confirm
  168. v-if="hasPermission('artist.remove')"
  169. @confirm="remove(slotProps.item._id)"
  170. :disabled="slotProps.item.removed"
  171. >
  172. <button
  173. class="button is-danger icon-with-button material-icons"
  174. content="Remove Artist"
  175. v-tippy
  176. >
  177. delete_forever
  178. </button>
  179. </quick-confirm>
  180. </div>
  181. </template>
  182. <template #column-name="slotProps">
  183. <span :title="slotProps.item.name">{{
  184. slotProps.item.name
  185. }}</span>
  186. </template>
  187. <template #column-musicbrainzIdentifier="slotProps">
  188. <span :title="slotProps.item.musicbrainzIdentifier">{{
  189. slotProps.item.musicbrainzIdentifier
  190. }}</span>
  191. </template>
  192. <template #column-createdBy="slotProps">
  193. <user-link
  194. :user-id="slotProps.item.createdBy"
  195. :alt="slotProps.item.createdBy"
  196. />
  197. </template>
  198. <template #column-createdAt="slotProps">
  199. <span :title="new Date(slotProps.item.createdAt).toString()">{{
  200. utils.getDateFormatted(slotProps.item.createdAt)
  201. }}</span>
  202. </template>
  203. </advanced-table>
  204. </div>
  205. </template>