improvement: separate Table and Renderer
This commit is contained in:
parent
f6fcf218d3
commit
d62bbceef9
2 changed files with 145 additions and 111 deletions
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, reactive, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import PaginatedFilteredTable from "@/utils/tables/PaginatedFilteredTable";
|
import type { TableField, TableItem } from "@/utils/tables/types";
|
||||||
import type { TableField } from "@/utils/tables/types";
|
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import TableRenderer from "./TableRenderer.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
fields: {
|
fields: {
|
||||||
|
@ -20,21 +20,8 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const DEFAULT_MAX_ITEM_BY_PAGE = 10;
|
const toLoad = ref(1);
|
||||||
|
const items = ref([] as TableItem[]);
|
||||||
const table = reactive(new PaginatedFilteredTable(DEFAULT_MAX_ITEM_BY_PAGE));
|
|
||||||
|
|
||||||
const filtersFieldMap = computed(() => {
|
|
||||||
return table?.filteredTable?.filtersFieldMap;
|
|
||||||
});
|
|
||||||
|
|
||||||
const displayedFieldKeys = computed(() => {
|
|
||||||
return table?.filteredTable?.table.displayedFieldKeys;
|
|
||||||
});
|
|
||||||
|
|
||||||
const paginatedList = computed(() => {
|
|
||||||
return table?.items;
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -43,106 +30,21 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
table.fields = props.fields;
|
toLoad.value = props.files.length;
|
||||||
for (const file of props.files) {
|
for (const file of props.files) {
|
||||||
const listItems = `/jdr/${props.category}/${file}.json`;
|
const listItems = `/jdr/${props.category}/${file}.json`;
|
||||||
axios.get(listItems).then((response) => {
|
axios.get(listItems).then((response) => {
|
||||||
table.addItems(response.data);
|
toLoad.value = toLoad.value - 1;
|
||||||
table.currentPage = 0;
|
items.value = items.value.concat(response.data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchFilter(filterSet: string | number, filterName: string | number) {
|
|
||||||
table.switchFilter(filterSet as string, filterName as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeFilter(filterSet: string | number) {
|
|
||||||
table.removeAllFilters(filterSet as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentPage = computed(() => {
|
|
||||||
return table?.currentPage;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getTotalPage = computed(() => {
|
|
||||||
return table?.pageNumber;
|
|
||||||
});
|
|
||||||
|
|
||||||
function canGo(rel: number) {
|
|
||||||
return table?.canGo(rel);
|
|
||||||
}
|
|
||||||
|
|
||||||
function go(rel: number) {
|
|
||||||
table?.go(rel);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="small-text" v-for="(filter, key) in filtersFieldMap" :key="key">
|
<TableRenderer
|
||||||
<strong>{{ filter.title }} : </strong>
|
:fields="fields"
|
||||||
<button
|
:items="items"
|
||||||
v-for="(isTrue, filterName) in filter.filters"
|
v-if="toLoad === 0"
|
||||||
:key="filterName"
|
></TableRenderer>
|
||||||
class="btn-small mb-0"
|
|
||||||
:class="{ 'btn-grey': !isTrue, 'btn-primary': isTrue }"
|
|
||||||
@click="switchFilter(key, filterName)"
|
|
||||||
>
|
|
||||||
{{ filterName }}
|
|
||||||
</button>
|
|
||||||
<button class="btn-small btn-secondary mb-0" @click="removeFilter(key)">
|
|
||||||
Vider filtres
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<table class="pb-0 table-auto">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th v-for="field in fields" :key="field.key">
|
|
||||||
{{ field.label }}
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(item, index) of paginatedList" :key="index">
|
|
||||||
<td v-for="(key, index2) in displayedFieldKeys" :key="index2">
|
|
||||||
{{ item[key] }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-flex f-between f-middle nextprevious small-text">
|
|
||||||
<div>
|
|
||||||
<strong class="btn m-0 pages pl-0">
|
|
||||||
Page {{ currentPage + 1 }} / {{ getTotalPage + 1 }}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="btn btn-grey m-0 mr-1"
|
|
||||||
:class="{ 'bg-grey': !canGo(-1), 'btn-secondary': canGo(-1) }"
|
|
||||||
@click="go(-1)"
|
|
||||||
>
|
|
||||||
Page précédante
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-grey m-0"
|
|
||||||
:class="{ 'bg-grey': !canGo(1), 'btn-secondary': canGo(1) }"
|
|
||||||
@click="go(1)"
|
|
||||||
>
|
|
||||||
Page suivante
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.small-text {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pages {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
132
src/components/tableaux/TableRenderer.vue
Normal file
132
src/components/tableaux/TableRenderer.vue
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, reactive, onMounted } from "vue";
|
||||||
|
import PaginatedFilteredTable from "@/utils/tables/PaginatedFilteredTable";
|
||||||
|
import type { TableField, TableItem } from "@/utils/tables/types";
|
||||||
|
import type { PropType } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
fields: {
|
||||||
|
type: Array as PropType<TableField[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Array as PropType<TableItem[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const DEFAULT_MAX_ITEM_BY_PAGE = 10;
|
||||||
|
|
||||||
|
const table = reactive(new PaginatedFilteredTable(DEFAULT_MAX_ITEM_BY_PAGE));
|
||||||
|
|
||||||
|
const filtersFieldMap = computed(() => {
|
||||||
|
return table?.filteredTable?.filtersFieldMap;
|
||||||
|
});
|
||||||
|
|
||||||
|
const displayedFieldKeys = computed(() => {
|
||||||
|
return table?.filteredTable?.table.displayedFieldKeys;
|
||||||
|
});
|
||||||
|
|
||||||
|
const paginatedList = computed(() => {
|
||||||
|
return table?.items;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
table.fields = props.fields;
|
||||||
|
table.addItems(props.items);
|
||||||
|
table.currentPage = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
function switchFilter(filterSet: string | number, filterName: string | number) {
|
||||||
|
table.switchFilter(filterSet as string, filterName as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFilter(filterSet: string | number) {
|
||||||
|
table.removeAllFilters(filterSet as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentPage = computed(() => {
|
||||||
|
return table?.currentPage;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getTotalPage = computed(() => {
|
||||||
|
return table?.pageNumber;
|
||||||
|
});
|
||||||
|
|
||||||
|
function canGo(rel: number) {
|
||||||
|
return table?.canGo(rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function go(rel: number) {
|
||||||
|
table?.go(rel);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="small-text" v-for="(filter, key) in filtersFieldMap" :key="key">
|
||||||
|
<strong>{{ filter.title }} : </strong>
|
||||||
|
<button
|
||||||
|
v-for="(isTrue, filterName) in filter.filters"
|
||||||
|
:key="filterName"
|
||||||
|
class="btn-small mb-0"
|
||||||
|
:class="{ 'btn-grey': !isTrue, 'btn-primary': isTrue }"
|
||||||
|
@click="switchFilter(key, filterName)"
|
||||||
|
>
|
||||||
|
{{ filterName }}
|
||||||
|
</button>
|
||||||
|
<button class="btn-small btn-secondary mb-0" @click="removeFilter(key)">
|
||||||
|
Vider filtres
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<table class="pb-0 table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="field in fields" :key="field.key">
|
||||||
|
{{ field.label }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) of paginatedList" :key="index">
|
||||||
|
<td v-for="(key, index2) in displayedFieldKeys" :key="index2">
|
||||||
|
{{ item[key] }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-flex f-between f-middle nextprevious small-text">
|
||||||
|
<div>
|
||||||
|
<strong class="btn m-0 pages pl-0">
|
||||||
|
Page {{ currentPage + 1 }} / {{ getTotalPage + 1 }}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="btn btn-grey m-0 mr-1"
|
||||||
|
:class="{ 'bg-grey': !canGo(-1), 'btn-secondary': canGo(-1) }"
|
||||||
|
@click="go(-1)"
|
||||||
|
>
|
||||||
|
Page précédante
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-grey m-0"
|
||||||
|
:class="{ 'bg-grey': !canGo(1), 'btn-secondary': canGo(1) }"
|
||||||
|
@click="go(1)"
|
||||||
|
>
|
||||||
|
Page suivante
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.small-text {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pages {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in a new issue