|
|
@@ -1,25 +1,28 @@
|
|
|
+<!--
|
|
|
+A data table for the parameters page
|
|
|
+-->
|
|
|
<template>
|
|
|
<div>
|
|
|
<UiLoadingPanel v-if="pending" />
|
|
|
<v-table v-else>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
- <td v-for="(_, i) in actualColumnProps">
|
|
|
- {{ actualColumnLabels[i] ?? '' }}
|
|
|
+ <td v-for="col in columns">
|
|
|
+ {{ col.label }}
|
|
|
</td>
|
|
|
<td>{{ $t('actions') }}</td>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
- <tbody v-if="items.value">
|
|
|
+ <tbody v-if="items">
|
|
|
<tr
|
|
|
- v-for="item in items.value"
|
|
|
- :key="item.id"
|
|
|
+ v-for="(item, i) in items"
|
|
|
+ :key="i"
|
|
|
>
|
|
|
<td
|
|
|
- v-for="prop in actualColumnProps"
|
|
|
+ v-for="col in columns"
|
|
|
class="cycle-editable-cell"
|
|
|
>
|
|
|
- {{ item[prop] }}
|
|
|
+ {{ item[col.property] }}
|
|
|
</td>
|
|
|
|
|
|
<td class="d-flex flex-row">
|
|
|
@@ -60,11 +63,25 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-
|
|
|
import {TABLE_ACTION} from '~/types/enum/enums';
|
|
|
import UrlUtils from '~/services/utils/urlUtils';
|
|
|
import type ApiResource from '~/models/ApiResource';
|
|
|
import {useEntityFetch} from '~/composables/data/useEntityFetch';
|
|
|
+import type {AssociativeArray} from '~/types/data';
|
|
|
+
|
|
|
+interface ColumnDefinition {
|
|
|
+ /**
|
|
|
+ * The entity's property to display in this column
|
|
|
+ */
|
|
|
+ property: string,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Label of the column.
|
|
|
+ * If not provided, a translation of the property's name will be looked for.
|
|
|
+ * If none is found, the property's name will be displayed as it is.
|
|
|
+ */
|
|
|
+ label: string | null
|
|
|
+}
|
|
|
|
|
|
const props = defineProps({
|
|
|
/**
|
|
|
@@ -78,35 +95,27 @@ const props = defineProps({
|
|
|
* The base URL for the edit / create pages
|
|
|
* The resulting url will be constructed this way :
|
|
|
*
|
|
|
- * Edition : {baseUrl}/{apiResource.entity}/{id}
|
|
|
- * Creation : {baseUrl}/{apiResource.entity}/new
|
|
|
+ * Edition : ({baseUrl}/){apiResource.entity}/{id}
|
|
|
+ * Creation : ({baseUrl}/){apiResource.entity}/new
|
|
|
*/
|
|
|
baseRoute: {
|
|
|
type: String,
|
|
|
required: false,
|
|
|
- default: 'parameters'
|
|
|
- },
|
|
|
- /**
|
|
|
- * If provided, limit the properties shown in the table to this list.
|
|
|
- * Else, all the props are shown.
|
|
|
- *
|
|
|
- * Ex: ['id', 'name']
|
|
|
- */
|
|
|
- columnsProps: {
|
|
|
- type: Array as PropType<Array<string>>,
|
|
|
- required: false
|
|
|
+ default: ''
|
|
|
},
|
|
|
/**
|
|
|
- * If provided, add labels to the columns
|
|
|
- *
|
|
|
- * Ex: ['Identifier', 'Full Name']
|
|
|
+ * If provided, define the columns to show.
|
|
|
+ * Else, all the entity's props are shown.
|
|
|
*
|
|
|
- * If not provided, a translation of the entity's props names will be looked for.
|
|
|
- * If none is found, no title will be displayed.
|
|
|
+ * Ex: [
|
|
|
+ * { property: 'id', label : 'Identifier'},
|
|
|
+ * { property: 'name', label : 'Full name'},
|
|
|
+ * ]
|
|
|
*/
|
|
|
- columnsLabels: {
|
|
|
- type: Array as PropType<Array<string>>,
|
|
|
- required: false
|
|
|
+ columnsDefinitions: {
|
|
|
+ type: Array as PropType<Array<ColumnDefinition> | null>,
|
|
|
+ required: false,
|
|
|
+ default: null
|
|
|
},
|
|
|
/**
|
|
|
* List of the actions available for each record
|
|
|
@@ -120,7 +129,7 @@ const props = defineProps({
|
|
|
* If provided, sort the record by the given property
|
|
|
*/
|
|
|
sortBy: {
|
|
|
- type: String,
|
|
|
+ type: String as PropType<string>,
|
|
|
required: false,
|
|
|
default: 'id'
|
|
|
}
|
|
|
@@ -139,50 +148,57 @@ const {
|
|
|
* Return the properties to display in the table, or all the
|
|
|
* props of the model if not specified.
|
|
|
*/
|
|
|
-const actualColumnProps = computed(() => {
|
|
|
- if (props.columnsProps) {
|
|
|
- return props.columnsProps
|
|
|
- }
|
|
|
- return Object.getOwnPropertyNames(new props.model())
|
|
|
-})
|
|
|
+const columns: ComputedRef<Array<ColumnDefinition>> = computed(() => {
|
|
|
+ let columns: Array<ColumnDefinition>
|
|
|
|
|
|
-/**
|
|
|
- * Return the labels for the columns if provided, or try to
|
|
|
- * find a translation for the property name if not specified.
|
|
|
- */
|
|
|
-const actualColumnLabels: ComputedRef<string> = computed(() => {
|
|
|
- if (props.columnsLabels) {
|
|
|
- return props.columnsLabels
|
|
|
+ if (!props.columnsDefinitions) {
|
|
|
+ const entityProps = Object.getOwnPropertyNames(new props.model())
|
|
|
+
|
|
|
+ columns = entityProps.map(prop => {
|
|
|
+ return {
|
|
|
+ property: prop,
|
|
|
+ label: i18n.t(prop)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ columns = props.columnsDefinitions
|
|
|
+
|
|
|
+ columns = columns.map(col => {
|
|
|
+ return {
|
|
|
+ property: col.property,
|
|
|
+ label: col.label ?? i18n.t(col.property)
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
- return actualColumnProps.value.map(prop => {
|
|
|
- return i18n.t(prop) ?? ''
|
|
|
- })
|
|
|
+
|
|
|
+ return columns
|
|
|
})
|
|
|
|
|
|
/**
|
|
|
* Fetch the collection of ApiResources of the given model, then
|
|
|
* map it according to the configuration.
|
|
|
*/
|
|
|
-const items: ComputedRef<Array<object>> = computed(() => {
|
|
|
- if (pending.value) {
|
|
|
+const items: ComputedRef<Array<ApiResource> | null> = computed(() => {
|
|
|
+ if (pending.value || collection.value === null) {
|
|
|
return null
|
|
|
}
|
|
|
|
|
|
- const items: Ref<object[]> = ref(collection.value.items)
|
|
|
+ let items: Array<ApiResource> = collection.value!.items
|
|
|
|
|
|
- if (props.columnsProps) {
|
|
|
- items.value = items.value.map(item => {
|
|
|
- const res = {}
|
|
|
- for (const prop of props.columnsProps) {
|
|
|
- res[prop] = item[prop]
|
|
|
+ if (props.columnsDefinitions !== null) {
|
|
|
+ // Filter the columns to show
|
|
|
+ items = items.map(item => {
|
|
|
+ const newItem: ApiResource = {}
|
|
|
+ for (const col of props.columnsDefinitions) {
|
|
|
+ newItem[col.property] = item[col.property]
|
|
|
}
|
|
|
- return res
|
|
|
+ return newItem
|
|
|
})
|
|
|
}
|
|
|
|
|
|
if (props.sortBy) {
|
|
|
- items.value = items.value.sort((a, b) => {
|
|
|
- return a[props.sortBy] > b[props.sortBy] ? 1 : -1
|
|
|
+ items = items.sort((a: AssociativeArray, b: AssociativeArray) => {
|
|
|
+ return (a[props.sortBy as keyof typeof a] > b[props.sortBy as keyof typeof b]) ? 1 : -1
|
|
|
})
|
|
|
}
|
|
|
|