mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-23 02:53:32 +00:00
add loading state support to DataTable component across various views
- UI/UX improvements for datatable
This commit is contained in:
@@ -1,41 +1,80 @@
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="rounded border shadow">
|
||||
<div class="overflow-hidden rounded-lg border border-border bg-card shadow-sm">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
||||
<TableRow
|
||||
v-for="headerGroup in table.getHeaderGroups()"
|
||||
:key="headerGroup.id"
|
||||
class="border-b border-border bg-muted/40 hover:bg-muted/40"
|
||||
>
|
||||
<TableHead
|
||||
v-for="header in headerGroup.headers"
|
||||
:key="header.id"
|
||||
class="font-semibold"
|
||||
:class="{ 'cursor-pointer select-none': header.column.getCanSort() }"
|
||||
class="h-11 px-4 text-center text-sm font-medium text-muted-foreground"
|
||||
:class="{
|
||||
'cursor-pointer select-none transition-colors hover:text-foreground':
|
||||
header.column.getCanSort()
|
||||
}"
|
||||
@click="header.column.getToggleSortingHandler()?.($event)"
|
||||
>
|
||||
<FlexRender
|
||||
v-if="!header.isPlaceholder"
|
||||
:render="header.column.columnDef.header"
|
||||
:props="header.getContext()"
|
||||
/>
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<FlexRender
|
||||
v-if="!header.isPlaceholder"
|
||||
:render="header.column.columnDef.header"
|
||||
:props="header.getContext()"
|
||||
/>
|
||||
<template v-if="header.column.getCanSort()">
|
||||
<ChevronUp v-if="header.column.getIsSorted() === 'asc'" class="h-3.5 w-3.5" />
|
||||
<ChevronDown
|
||||
v-else-if="header.column.getIsSorted() === 'desc'"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
<ArrowUpDown
|
||||
v-else
|
||||
class="h-3.5 w-3.5 opacity-0 transition-opacity group-hover:opacity-50"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<TableRow
|
||||
v-for="row in table.getRowModel().rows"
|
||||
:key="row.id"
|
||||
:data-state="row.getIsSelected() ? 'selected' : undefined"
|
||||
class="hover:bg-muted/50"
|
||||
class="border-b border-border/50 transition-colors last:border-0 hover:bg-muted/30 data-[state=selected]:bg-muted"
|
||||
>
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<TableCell
|
||||
v-for="cell in row.getVisibleCells()"
|
||||
:key="cell.id"
|
||||
class="px-4 py-3 text-center text-sm"
|
||||
>
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
|
||||
<template v-else-if="loading">
|
||||
<TableRow class="hover:bg-transparent">
|
||||
<TableCell :colspan="columns.length" class="h-32">
|
||||
<div class="flex items-center justify-center">
|
||||
<p class="text-sm text-muted-foreground">{{ t('globals.terms.loading') }}</p>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<TableRow>
|
||||
<TableCell :colspan="columns.length" class="h-24 text-center">
|
||||
<div class="text-muted-foreground">{{ emptyText }}</div>
|
||||
<TableRow class="hover:bg-transparent">
|
||||
<TableCell :colspan="columns.length" class="h-32">
|
||||
<div class="flex flex-col items-center justify-center gap-2 text-center">
|
||||
<Ghost class="h-8 w-8 text-muted-foreground/50" />
|
||||
<p class="text-sm font-medium text-muted-foreground">{{ emptyText }}</p>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
@@ -49,7 +88,7 @@
|
||||
import { FlexRender, getCoreRowModel, getSortedRowModel, useVueTable } from '@tanstack/vue-table'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { ArrowUpDown, ChevronDown, ChevronUp, Ghost } from 'lucide-vue-next'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -60,16 +99,20 @@ import {
|
||||
} from '@/components/ui/table'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
columns: Array,
|
||||
data: Array,
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
// Set the default value for emptyText if it's empty
|
||||
const emptyText = computed(
|
||||
() =>
|
||||
props.emptyText ||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex justify-between h-full">
|
||||
<div class="w-8/12">
|
||||
<div class="w-8/12 relative">
|
||||
<slot name="content" />
|
||||
</div>
|
||||
<div class="rounded w-3/12 p-2 space-y-2 self-start">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="data" />
|
||||
<DataTable :columns="createColumns(t)" :data="data" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<Spinner v-if="isLoading" />
|
||||
<DataTable :columns="createColumns(t)" :data="businessHours" />
|
||||
<DataTable :columns="createColumns(t)" :data="businessHours" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -58,10 +58,10 @@
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="contact">
|
||||
<DataTable :columns="createColumns(t)" :data="customAttributes" />
|
||||
<DataTable :columns="createColumns(t)" :data="customAttributes" :loading="isLoading" />
|
||||
</TabsContent>
|
||||
<TabsContent value="conversation">
|
||||
<DataTable :columns="createColumns(t)" :data="customAttributes" />
|
||||
<DataTable :columns="createColumns(t)" :data="customAttributes" :loading="isLoading" />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="columns" :data="data" />
|
||||
<DataTable :columns="columns" :data="data" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="macros" />
|
||||
<DataTable :columns="createColumns(t)" :data="macros" :loading="formLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="oidc" />
|
||||
<DataTable :columns="createColumns(t)" :data="oidc" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="roles" />
|
||||
<DataTable :columns="createColumns(t)" :data="roles" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="sharedViews" />
|
||||
<DataTable :columns="createColumns(t)" :data="sharedViews" :loading="formLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<Spinner v-if="isLoading"></Spinner>
|
||||
<DataTable :columns="createColumns(t)" :data="slas" />
|
||||
<DataTable :columns="createColumns(t)" :data="slas" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="statuses" />
|
||||
<DataTable :columns="createColumns(t)" :data="statuses" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="tags" />
|
||||
<DataTable :columns="createColumns(t)" :data="tags" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="columns" :data="data" />
|
||||
<DataTable :columns="columns" :data="data" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="email_outgoing">
|
||||
<DataTable :columns="createOutgoingEmailTableColumns(t)" :data="templates" />
|
||||
<DataTable :columns="createOutgoingEmailTableColumns(t)" :data="templates" :loading="isLoading" />
|
||||
</TabsContent>
|
||||
<TabsContent value="email_notification">
|
||||
<DataTable :columns="createEmailNotificationTableColumns(t)" :data="templates" />
|
||||
<DataTable :columns="createEmailNotificationTableColumns(t)" :data="templates" :loading="isLoading" />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<DataTable :columns="createColumns(t)" :data="webhooks" />
|
||||
<DataTable :columns="createColumns(t)" :data="webhooks" :loading="isLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user