Table.vue 3.8 KB

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