Skip to content

Commit 6195d57

Browse files
committed
fix: horizontal scroll for the afcl table
1 parent 360d7f4 commit 6195d57

File tree

1 file changed

+117
-120
lines changed

1 file changed

+117
-120
lines changed

adminforth/spa/src/afcl/Table.vue

Lines changed: 117 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,124 @@
11
<template>
2-
3-
<div class="afcl-table-container relative overflow-x-auto shadow-md sm:rounded-lg">
4-
<table class="afcl-table w-full text-sm text-left rtl:text-right text-lightTableText dark:text-darkTableText">
5-
<thead class="afcl-table-thread text-xs text-lightTableHeadingText uppercase bg-lightTableHeadingBackground dark:bg-darkTableHeadingBackground dark:text-darkTableHeadingText">
6-
<tr>
7-
<th scope="col" class="px-6 py-3" ref="headerRefs"
8-
v-for="column in columns"
9-
>
10-
<slot v-if="$slots[`header:${column.fieldName}`]" :name="`header:${column.fieldName}`" :column="column" />
11-
12-
<span v-else>
13-
{{ column.label }}
14-
</span>
15-
</th>
16-
</tr>
17-
</thead>
18-
<tbody>
19-
<SkeleteLoader
20-
v-if="isLoading"
21-
:rows="pageSize"
22-
:columns="columns.length"
23-
:row-heights="rowHeights"
24-
:column-widths="columnWidths"
25-
/>
26-
<tr v-else-if="!isLoading && dataPage.length === 0" class="afcl-table-empty-body">
27-
<td :colspan="columns.length" class="px-6 py-12 text-center">
28-
<div class="flex flex-col items-center justify-center text-lightTableText dark:text-darkTableText">
29-
<IconTableRowOutline class="w-10 h-10 mb-4 text-gray-400 dark:text-gray-500" />
30-
<p class="text-md">{{ $t('No data available') }}</p>
31-
</div>
32-
</td>
33-
</tr>
34-
<tr
35-
v-else="!isLoading"
36-
v-for="(item, index) in dataPage"
37-
ref="rowRefs"
38-
:class="{
39-
'afcl-table-body odd:bg-lightTableOddBackground odd:dark:bg-darkTableOddBackground even:bg-lightTableEvenBackground even:dark:bg-darkTableEvenBackground': evenHighlights,
40-
'border-b border-lightTableBorder dark:border-darkTableBorder': index !== dataPage.length - 1 || totalPages > 1,
41-
}"
42-
>
43-
<td class="px-6 py-4"
44-
v-for="column in props.columns"
45-
>
46-
<slot v-if="$slots[`cell:${column.fieldName}`]"
47-
:name="`cell:${column.fieldName}`"
48-
:item="item" :column="column"
2+
<div class="afcl-table-container relative overflow-x-auto shadow-md sm:rounded-lg">
3+
<div class="overflow-x-auto w-full">
4+
<table class="afcl-table w-full text-sm text-left rtl:text-right text-lightTableText dark:text-darkTableText overflow-x-auto">
5+
<thead class="afcl-table-thread text-xs text-lightTableHeadingText uppercase bg-lightTableHeadingBackground dark:bg-darkTableHeadingBackground dark:text-darkTableHeadingText">
6+
<tr>
7+
<th scope="col" class="px-6 py-3" ref="headerRefs"
8+
v-for="column in columns"
9+
>
10+
<slot v-if="$slots[`header:${column.fieldName}`]" :name="`header:${column.fieldName}`" :column="column" />
11+
12+
<span v-else>
13+
{{ column.label }}
14+
</span>
15+
</th>
16+
</tr>
17+
</thead>
18+
<tbody>
19+
<SkeleteLoader
20+
v-if="isLoading"
21+
:rows="pageSize"
22+
:columns="columns.length"
23+
:row-heights="rowHeights"
24+
:column-widths="columnWidths"
25+
/>
26+
<tr v-else-if="!isLoading && dataPage.length === 0" class="afcl-table-empty-body">
27+
<td :colspan="columns.length" class="px-6 py-12 text-center">
28+
<div class="flex flex-col items-center justify-center text-lightTableText dark:text-darkTableText">
29+
<IconTableRowOutline class="w-10 h-10 mb-4 text-gray-400 dark:text-gray-500" />
30+
<p class="text-md">{{ $t('No data available') }}</p>
31+
</div>
32+
</td>
33+
</tr>
34+
<tr
35+
v-else="!isLoading"
36+
v-for="(item, index) in dataPage"
37+
ref="rowRefs"
38+
:class="{
39+
'afcl-table-body odd:bg-lightTableOddBackground odd:dark:bg-darkTableOddBackground even:bg-lightTableEvenBackground even:dark:bg-darkTableEvenBackground': evenHighlights,
40+
'border-b border-lightTableBorder dark:border-darkTableBorder': index !== dataPage.length - 1 || totalPages > 1,
41+
}"
4942
>
50-
</slot>
51-
<span v-else-if="!isLoading" >
52-
{{ item[column.fieldName] }}
53-
</span>
54-
<div v-else>
55-
<div class=" w-full">
56-
<Skeleton class="h-4" />
57-
</div>
58-
</div>
59-
</td>
60-
</tr>
61-
</tbody>
62-
</table>
63-
<nav class="afcl-table-pagination-container bg-lightTableBackground dark:bg-darkTableBackground mt-2 flex flex-col gap-2 items-center sm:flex-row justify-center sm:justify-between px-4 pb-4"
64-
v-if="totalPages > 1"
65-
:aria-label="$t('Table navigation')">
66-
<i18n-t
67-
keypath="Showing {from} to {to} of {total}" tag="span" class="afcl-table-pagination-text text-sm font-normal text-center text-lightTablePaginationText dark:text-darkTablePaginationText sm:mb-4 md:mb-0 block w-full md:inline md:w-auto"
68-
>
69-
<template #from><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ Math.min((currentPage - 1) * props.pageSize + 1, dataResult.total) }}</span></template>
70-
<template #to><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ Math.min(currentPage * props.pageSize, dataResult.total) }}</span></template>
71-
<template #total><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ dataResult.total }}</span></template>
72-
</i18n-t>
73-
<div class="af-pagination-container flex flex-row items-center xs:flex-row xs:justify-between xs:items-center gap-3">
74-
<div class="inline-flex">
75-
<!-- Buttons -->
76-
<button
77-
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText bg-lightActivePaginationButtonBackground border-r-0 rounded-s hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
78-
@click="currentPage--; pageInput = currentPage.toString();" :disabled="currentPage <= 1">
79-
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
80-
viewBox="0 0 14 10">
81-
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
82-
d="M13 5H1m0 0 4 4M1 5l4-4"/>
83-
</svg>
84-
</button>
85-
<button
86-
class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-r-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
87-
@click="switchPage(1); pageInput = currentPage.toString();" :disabled="currentPage <= 1">
88-
<!-- <IconChevronDoubleLeftOutline class="w-4 h-4" /> -->
89-
1
90-
</button>
91-
<div
92-
contenteditable="true"
93-
class="min-w-10 outline-none inline-block w-auto py-1.5 px-3 text-sm text-center text-lightTablePaginationInputText border border-lightTablePaginationInputBorder bg-lightTablePaginationInputBackground dark:border-darkTablePaginationInputBorder dark:text-darkTablePaginationInputText dark:bg-darkTablePaginationInputBackground z-10"
94-
@keydown="onPageKeydown($event)"
95-
@input="onPageInput($event)"
96-
@blur="validatePageInput()"
97-
>
98-
{{ pageInput }}
43+
<td class="px-6 py-4"
44+
v-for="column in props.columns"
45+
>
46+
<slot v-if="$slots[`cell:${column.fieldName}`]"
47+
:name="`cell:${column.fieldName}`"
48+
:item="item" :column="column"
49+
>
50+
</slot>
51+
<span v-else-if="!isLoading" >
52+
{{ item[column.fieldName] }}
53+
</span>
54+
<div v-else>
55+
<div class=" w-full">
56+
<Skeleton class="h-4" />
57+
</div>
58+
</div>
59+
</td>
60+
</tr>
61+
</tbody>
62+
</table>
63+
</div>
64+
<nav class="afcl-table-pagination-container bg-lightTableBackground dark:bg-darkTableBackground mt-2 flex flex-col gap-2 items-center sm:flex-row justify-center sm:justify-between px-4 pb-4"
65+
v-if="totalPages > 1"
66+
:aria-label="$t('Table navigation')">
67+
<i18n-t
68+
keypath="Showing {from} to {to} of {total}" tag="span" class="afcl-table-pagination-text text-sm font-normal text-center text-lightTablePaginationText dark:text-darkTablePaginationText sm:mb-4 md:mb-0 block w-full md:inline md:w-auto"
69+
>
70+
<template #from><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ Math.min((currentPage - 1) * props.pageSize + 1, dataResult.total) }}</span></template>
71+
<template #to><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ Math.min(currentPage * props.pageSize, dataResult.total) }}</span></template>
72+
<template #total><span class="font-semibold text-lightTablePaginationNumeration dark:text-darkTablePaginationNumeration">{{ dataResult.total }}</span></template>
73+
</i18n-t>
74+
<div class="af-pagination-container flex flex-row items-center xs:flex-row xs:justify-between xs:items-center gap-3">
75+
<div class="inline-flex">
76+
<!-- Buttons -->
77+
<button
78+
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText bg-lightActivePaginationButtonBackground border-r-0 rounded-s hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
79+
@click="currentPage--; pageInput = currentPage.toString();" :disabled="currentPage <= 1">
80+
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
81+
viewBox="0 0 14 10">
82+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
83+
d="M13 5H1m0 0 4 4M1 5l4-4"/>
84+
</svg>
85+
</button>
86+
<button
87+
class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-r-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
88+
@click="switchPage(1); pageInput = currentPage.toString();" :disabled="currentPage <= 1">
89+
<!-- <IconChevronDoubleLeftOutline class="w-4 h-4" /> -->
90+
1
91+
</button>
92+
<div
93+
contenteditable="true"
94+
class="min-w-10 outline-none inline-block w-auto py-1.5 px-3 text-sm text-center text-lightTablePaginationInputText border border-lightTablePaginationInputBorder bg-lightTablePaginationInputBackground dark:border-darkTablePaginationInputBorder dark:text-darkTablePaginationInputText dark:bg-darkTablePaginationInputBackground z-10"
95+
@keydown="onPageKeydown($event)"
96+
@input="onPageInput($event)"
97+
@blur="validatePageInput()"
98+
>
99+
{{ pageInput }}
100+
</div>
101+
102+
<button
103+
class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-l-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
104+
@click="currentPage = totalPages; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
105+
{{ totalPages }}
106+
107+
<!-- <IconChevronDoubleRightOutline class="w-4 h-4" /> -->
108+
</button>
109+
<button
110+
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText focus:outline-none bg-lightActivePaginationButtonBackground border-l-0 rounded-e hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
111+
@click="currentPage++; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
112+
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
113+
viewBox="0 0 14 10">
114+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
115+
d="M1 5h12m0 0L9 1m4 4L9 9"/>
116+
</svg>
117+
</button>
99118
</div>
100-
101-
<button
102-
class="flex items-center py-1 px-3 text-sm font-medium text-lightUnactivePaginationButtonText focus:outline-none bg-lightUnactivePaginationButtonBackground border-l-0 border border-lightUnactivePaginationButtonBorder hover:bg-lightUnactivePaginationButtonHoverBackground hover:text-lightUnactivePaginationButtonHoverText dark:bg-darkUnactivePaginationButtonBackground dark:text-darkUnactivePaginationButtonText dark:border-darkUnactivePaginationButtonBorder dark:hover:text-darkUnactivePaginationButtonHoverText dark:hover:bg-darkUnactivePaginationButtonHoverBackground disabled:opacity-50"
103-
@click="currentPage = totalPages; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
104-
{{ totalPages }}
105-
106-
<!-- <IconChevronDoubleRightOutline class="w-4 h-4" /> -->
107-
</button>
108-
<button
109-
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightActivePaginationButtonText focus:outline-none bg-lightActivePaginationButtonBackground border-l-0 rounded-e hover:opacity-90 dark:bg-darkActivePaginationButtonBackground dark:text-darkActivePaginationButtonText disabled:opacity-50"
110-
@click="currentPage++; pageInput = currentPage.toString();" :disabled="currentPage >= totalPages">
111-
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
112-
viewBox="0 0 14 10">
113-
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
114-
d="M1 5h12m0 0L9 1m4 4L9 9"/>
115-
</svg>
116-
</button>
117119
</div>
118-
</div>
119-
</nav>
120-
</div>
121-
122-
123-
120+
</nav>
121+
</div>
124122
</template>
125123

126124
<script setup lang="ts">
@@ -166,7 +164,6 @@
166164
refresh();
167165
});
168166
169-
170167
watch(() => currentPage.value, () => {
171168
rowHeights.value = !rowRefs.value ? [] : rowRefs.value.map((el: HTMLElement) => el.offsetHeight);
172169
columnWidths.value = !headerRefs.value ? [] : headerRefs.value.map((el: HTMLElement) => el.offsetWidth);

0 commit comments

Comments
 (0)