Files
homebox/frontend/components/Item/View/table/data-table-controls.vue
Tonya 6cd9e2779f Use Tanstack table for Selectable Table, quick actions (#998)
* feat: implement example of data table

* feat: load item data into table

* chore: begin switching dialogs

* feat: implement old dialog for controlling headers and page size

* feat: get table into relatively usable state

* feat: enhance dropdown actions for multi-selection and CSV download

* feat: enhance table cell and dropdown button styles for better usability

* feat: json download for table

* feat: add expanded row component for item details in data table

* chore: add translation support

* feat: restore table on home page

* fix: oops need ids

* feat: move card view to use tanstack to allow for pagination

* feat: switch the items search to use ItemViewSelectable

* fix: update pagination handling and improve button click logic

* feat: improve selectable table

* feat: add indeterminate to checkbox

* feat: overhaul maintenance dialog to use new system and add maintenance options to table

* feat: add label ids and location id to item patch api

* feat: change location and labels in table view

* feat: add quick actions preference and enable toggle in table settings

* fix: lint

* fix: remove sized 1 pages

* fix: attempt to fix type error

* fix: various issues

* fix: remove

* fix: refactor item fetching logic to use useAsyncData for improved reactivity and improve use confirm

* fix: sort backend issues

* fix: enhance CSV export functionality by escaping fields to prevent formula injection

* fix: put aria sort on th not button

* chore: update api types
2025-09-24 02:37:38 +01:00

94 lines
3.2 KiB
Vue

<script setup lang="ts">
import type { Table as TableType } from "@tanstack/vue-table";
import type { ItemSummary } from "~/lib/api/types/data-contracts";
import MdiTableCog from "~icons/mdi/table-cog";
import Button from "~/components/ui/button/Button.vue";
import {
Pagination,
PaginationEllipsis,
PaginationFirst,
PaginationLast,
PaginationList,
PaginationListItem,
} from "@/components/ui/pagination";
import { DialogID, useDialog } from "~/components/ui/dialog-provider/utils";
import type { Pagination as PaginationType } from "../pagination";
const { openDialog } = useDialog();
const props = defineProps<{
table: TableType<ItemSummary>;
dataLength: number;
externalPagination?: PaginationType;
}>();
const setPage = (page: number) => {
if (props.externalPagination) {
if (page !== props.externalPagination.page) {
// clear selection and expanded
props.table.resetRowSelection();
props.table.resetExpanded();
}
props.externalPagination.setPage(page);
} else {
props.table.setPageIndex(page - 1);
}
};
</script>
<template>
<div class="flex flex-col gap-2 md:flex-row md:items-center md:justify-between md:gap-0">
<div class="order-2 flex items-center gap-2 md:order-1">
<Button class="size-10 p-0" variant="outline" @click="openDialog(DialogID.ItemTableSettings)">
<MdiTableCog />
</Button>
<div class="text-sm text-muted-foreground">
{{
$t("components.item.view.table.selected_rows", {
selected: table.getFilteredSelectedRowModel().rows.length,
total: table.getFilteredRowModel().rows.length,
})
}}
</div>
</div>
<div class="order-1 flex w-full justify-center md:order-2 md:w-auto">
<Pagination
v-slot="{ page }"
:items-per-page="externalPagination ? externalPagination.pageSize : table.getState().pagination.pageSize"
:total="externalPagination ? externalPagination.totalSize : dataLength"
:sibling-count="2"
:page="externalPagination ? externalPagination.page : table.getState().pagination.pageIndex + 1"
@update:page="val => setPage(val)"
>
<PaginationList v-slot="{ items: pageItems }" class="flex items-center gap-1">
<PaginationFirst @click="() => setPage(1)" />
<template v-for="(item, index) in pageItems">
<PaginationListItem v-if="item.type === 'page'" :key="index" :value="item.value" as-child>
<Button
class="size-10 p-0"
:variant="item.value === page ? 'default' : 'outline'"
@click="() => setPage(item.value)"
>
{{ item.value }}
</Button>
</PaginationListItem>
<PaginationEllipsis v-else :key="item.type" :index="index" />
</template>
<PaginationLast
@click="
() =>
setPage(
externalPagination
? Math.ceil(externalPagination.totalSize / externalPagination.pageSize)
: table.getPageCount()
)
"
/>
</PaginationList>
</Pagination>
</div>
</div>
</template>