Table.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <!--
  2. A data table for the parameters page
  3. -->
  4. <template>
  5. <div class="container">
  6. <div class="d-flex flex-row mb-2">
  7. <h4 v-if="title" class="align-self-center">
  8. {{ title }}
  9. </h4>
  10. <div class="flex-grow-1" />
  11. <v-btn
  12. prepend-icon="fa fa-plus"
  13. class="theme-neutral"
  14. @click="emit('addClicked')"
  15. >
  16. {{ i18n.t('add') }}
  17. </v-btn>
  18. </div>
  19. <div class="d-flex justify-end" v-if="actions.includes(TABLE_ACTION.ADD)">
  20. </div>
  21. <v-table>
  22. <thead>
  23. <tr>
  24. <td v-for="col in columns">
  25. {{ col.label }}
  26. </td>
  27. <td>{{ i18n.t('actions') }}</td>
  28. </tr>
  29. </thead>
  30. <tbody v-if="items">
  31. <tr
  32. v-for="(item, i) in items"
  33. :key="i"
  34. >
  35. <td
  36. v-for="col in columnsDefinitions"
  37. class="cycle-editable-cell"
  38. >
  39. {{ item[col.property] }}
  40. </td>
  41. <td class="d-flex flex-row actions-cell">
  42. <slot name="actions" :item="item">
  43. <v-btn
  44. v-if="actions.includes(TABLE_ACTION.EDIT)"
  45. :flat="true"
  46. icon="fa fa-pen"
  47. class="mr-3"
  48. @click="emit('editClicked', item)"
  49. />
  50. <v-btn
  51. v-if="actions.includes(TABLE_ACTION.DELETE)"
  52. :flat="true"
  53. icon="fas fa-trash"
  54. @click="emit('deleteClicked', item)"
  55. />
  56. </slot>
  57. </td>
  58. </tr>
  59. </tbody>
  60. <tbody v-else>
  61. <tr class="theme-neutral">
  62. <td>
  63. <i>{{ i18n.t('nothing_to_show') }}</i>
  64. </td>
  65. <td></td>
  66. </tr>
  67. </tbody>
  68. </v-table>
  69. </div>
  70. </template>
  71. <script setup lang="ts">
  72. import {TABLE_ACTION} from '~/types/enum/enums';
  73. import UrlUtils from '~/services/utils/urlUtils';
  74. import type {ColumnDefinition} from '~/types/interfaces';
  75. const props = defineProps({
  76. /**
  77. * Array of objects to display in the table
  78. */
  79. items: {
  80. type: Array as PropType<Array<object>>,
  81. required: true,
  82. },
  83. /** Titre du tableau */
  84. title: {
  85. type: String,
  86. required: false,
  87. default: null
  88. },
  89. /**
  90. * If provided, define the columns to show.
  91. * Else, all the entity's props are shown.
  92. *
  93. * Ex: [
  94. * { property: 'id', label : 'Identifier'},
  95. * { property: 'name', label : 'Full name'},
  96. * ]
  97. */
  98. columnsDefinitions: {
  99. type: Array as PropType<Array<ColumnDefinition> | null>,
  100. required: false,
  101. default: null
  102. },
  103. /**
  104. * The property used as identifier (required by 'edition' link)
  105. */
  106. identifier: {
  107. type: String,
  108. required: false,
  109. default: 'id'
  110. },
  111. /**
  112. * List of the actions available for each record
  113. */
  114. actions: {
  115. type: Array as PropType<Array<TABLE_ACTION>>,
  116. required: false,
  117. default: [TABLE_ACTION.EDIT, TABLE_ACTION.DELETE, TABLE_ACTION.ADD]
  118. },
  119. /**
  120. * The URL for the edit / create pages
  121. * The resulting url will be constructed this way :
  122. *
  123. * Edition : {baseUrl}/{id}
  124. * Creation : {baseUrl}/new
  125. */
  126. actionsRoute: {
  127. type: String,
  128. required: false,
  129. default: '/parameters'
  130. }
  131. })
  132. const i18n = useI18n()
  133. const emit = defineEmits(['editClicked', 'deleteClicked', 'addClicked'])
  134. const getId = (item: object) => {
  135. return item[props.identifier]
  136. }
  137. const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
  138. return props.columnsDefinitions.map(col => {
  139. return {
  140. property: col.property,
  141. label: col.label ?? i18n.t(col.property)
  142. }
  143. })
  144. })
  145. </script>
  146. <style scoped lang="scss">
  147. .v-table {
  148. width: 100%;
  149. thead {
  150. color: rgb(var(--v-theme-neutral-strong));
  151. font-weight: 600;
  152. td {
  153. border-bottom: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
  154. }
  155. td:last-of-type {
  156. padding-left: 30px;
  157. }
  158. }
  159. th, td {
  160. padding: 10px;
  161. text-align: left;
  162. }
  163. td:last-of-type {
  164. width: 125px;
  165. }
  166. }
  167. :deep(.actions-cell .v-icon) {
  168. color: rgb(var(--v-theme-neutral-strong));
  169. font-size: 18px;
  170. }
  171. </style>