EntityTable.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <!--
  2. A data table for the parameters page
  3. -->
  4. <template>
  5. <div class="container">
  6. <UiLoadingPanel v-if="status===FETCHING_STATUS.PENDING" />
  7. <div v-else>
  8. <LayoutParametersTable
  9. :items="items"
  10. :title="title"
  11. :columns-definitions="columns"
  12. :actions="actions"
  13. :actions-route="actionsRoute"
  14. @edit-clicked="onEditClicked"
  15. @delete-clicked="onDeleteClicked"
  16. @add-clicked="goToCreatePage"
  17. />
  18. <UiFormDeletionConfirmationDialog
  19. v-model="showDeletionConfirmationDialog"
  20. @delete-clicked="onDeleteConfirmed"
  21. @cancel-clicked="onCancelClicked"
  22. />
  23. </div>
  24. </div>
  25. </template>
  26. <script setup lang="ts">
  27. import type { PropType, ComputedRef, Ref } from 'vue'
  28. import { TABLE_ACTION } from '~/types/enum/enums'
  29. import UrlUtils from '~/services/utils/urlUtils'
  30. import type ApiResource from '~/models/ApiResource'
  31. import { useEntityFetch } from '~/composables/data/useEntityFetch'
  32. import type { AssociativeArray } from '~/types/data'
  33. import type { ColumnDefinition } from '~/types/interfaces'
  34. import { useDeleteItem } from '~/composables/form/useDeleteItem'
  35. import { useEntityManager } from '~/composables/data/useEntityManager'
  36. import {FETCHING_STATUS} from "~/types/enum/data";
  37. const props = defineProps({
  38. /**
  39. * The model whom entities shall be to fetch
  40. */
  41. model: {
  42. type: Object as PropType<typeof ApiResource>,
  43. required: true,
  44. },
  45. /** Titre du tableau */
  46. title: {
  47. type: String,
  48. required: false,
  49. default: null,
  50. },
  51. /**
  52. * If provided, define the columns to show.
  53. * Else, all the entity's props are shown.
  54. *
  55. * Ex: [
  56. * { property: 'id', label : 'Identifier'},
  57. * { property: 'name', label : 'Full name'},
  58. * ]
  59. */
  60. columnsDefinitions: {
  61. type: Array as PropType<Array<ColumnDefinition> | null>,
  62. required: false,
  63. default: null,
  64. },
  65. /**
  66. * List of the actions available for each record
  67. */
  68. actions: {
  69. type: Array as PropType<Array<TABLE_ACTION>>,
  70. required: false,
  71. default: () => [TABLE_ACTION.EDIT, TABLE_ACTION.DELETE, TABLE_ACTION.ADD],
  72. },
  73. /**
  74. * The base URL for the edit / create pages
  75. * The resulting url will be constructed this way :
  76. *
  77. * Edition : ({baseUrl}/){apiResource.entity}/{id}
  78. * Creation : ({baseUrl}/){apiResource.entity}/new
  79. */
  80. baseActionsRoute: {
  81. type: String,
  82. required: false,
  83. default: '/parameters',
  84. },
  85. /**
  86. * If provided, sort the record by the given property
  87. */
  88. sortBy: {
  89. type: String as PropType<string>,
  90. required: false,
  91. default: 'id',
  92. },
  93. })
  94. const i18n = useI18n()
  95. const { em } = useEntityManager()
  96. const { fetchCollection } = useEntityFetch()
  97. const { data: collection, status } = fetchCollection(props.model)
  98. const { deleteItem } = useDeleteItem()
  99. const pageStore = usePageStore()
  100. /**
  101. * Return the properties to display in the table, or all the
  102. * props of the model if not specified.
  103. */
  104. const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
  105. return (
  106. props.columnsDefinitions ??
  107. Object.getOwnPropertyNames(new props.model()).map((prop) => {
  108. return { property: prop }
  109. })
  110. )
  111. })
  112. /**
  113. * Fetch the collection of ApiResources of the given model, then
  114. * map it according to the configuration.
  115. */
  116. const items: ComputedRef<Array<ApiResource> | null> = computed(() => {
  117. if (status.value === FETCHING_STATUS.PENDING || collection.value === null) {
  118. return null
  119. }
  120. let items: Array<ApiResource> = collection.value!.items
  121. if (props.columnsDefinitions !== null) {
  122. // Filter the columns to show
  123. items = items.map((item) => {
  124. const newItem: any = { id: item.id }
  125. for (const col of props.columnsDefinitions!) {
  126. newItem[col.property] = item[col.property]
  127. }
  128. return newItem as ApiResource
  129. })
  130. }
  131. if (props.sortBy) {
  132. items = items.sort((a: ApiResource, b: ApiResource) => {
  133. return (a as any)[props.sortBy] > (b as any)[props.sortBy] ? 1 : -1
  134. })
  135. }
  136. return items
  137. })
  138. const actionsRoute = computed(() => {
  139. return UrlUtils.join(props.baseActionsRoute, props.model.entity)
  140. })
  141. const showDeletionConfirmationDialog: Ref<boolean> = ref(false)
  142. const itemToDelete: Ref<ApiResource | null> = ref(null)
  143. /**
  144. * Redirect to the edition page for the given item
  145. * @param item
  146. */
  147. const onEditClicked = (item: ApiResource) => {
  148. navigateTo(UrlUtils.join(actionsRoute.value, item.id))
  149. }
  150. /**
  151. * Show the deletion confirmation dialog
  152. * @param item
  153. */
  154. const onDeleteClicked = (item: ApiResource) => {
  155. itemToDelete.value = em.cast(props.model, item)
  156. showDeletionConfirmationDialog.value = true
  157. }
  158. const onCancelClicked = () => {
  159. itemToDelete.value = null
  160. }
  161. /**
  162. * Deletion has be confirmed, perform
  163. */
  164. const onDeleteConfirmed = async () => {
  165. pageStore.loading = true
  166. await deleteItem(itemToDelete.value)
  167. pageStore.loading = false
  168. }
  169. /**
  170. * Redirect to the creation page for this model
  171. */
  172. const goToCreatePage = () => {
  173. navigateTo(UrlUtils.join(actionsRoute.value, 'new'))
  174. }
  175. // Nettoyer les données lors du démontage du composant
  176. onBeforeUnmount(() => {
  177. // Nettoyer les références du store si nécessaire
  178. if (process.client) {
  179. clearNuxtData('/^' + props.model.entity + '_many_/')
  180. useRepo(props.model).flush()
  181. }
  182. })
  183. </script>
  184. <style scoped lang="scss"></style>