mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-26 07:13:37 +01:00
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
This commit is contained in:
@@ -6,17 +6,32 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button, ButtonGroup } from "@/components/ui/button";
|
||||
import BaseSectionHeader from "@/components/Base/SectionHeader.vue";
|
||||
import ItemCard from "@/components/Item/Card.vue";
|
||||
import ItemViewTable from "@/components/Item/View/Table.vue";
|
||||
import DataTable from "./table/data-table.vue";
|
||||
import { makeColumns } from "./table/columns";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import type { Pagination } from "./pagination";
|
||||
import MaintenanceEditModal from "@/components/Maintenance/EditModal.vue";
|
||||
import ItemChangeDetails from "./ItemChangeDetails.vue";
|
||||
|
||||
type Props = {
|
||||
const props = defineProps<{
|
||||
view?: ViewType;
|
||||
items: ItemSummary[];
|
||||
};
|
||||
locationFlatTree?: FlatTreeItem[];
|
||||
pagination?: Pagination;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "refresh"): void;
|
||||
}>();
|
||||
|
||||
const preferences = useViewPreferences();
|
||||
const { t } = useI18n();
|
||||
const columns = computed(() =>
|
||||
makeColumns(t, () => {
|
||||
emit("refresh");
|
||||
})
|
||||
);
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const viewSet = computed(() => {
|
||||
return !!props.view;
|
||||
});
|
||||
@@ -28,17 +43,29 @@
|
||||
function setViewPreference(view: ViewType) {
|
||||
preferences.value.itemDisplayView = view;
|
||||
}
|
||||
|
||||
const externalPagination = computed(() => !!props.pagination);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<BaseSectionHeader class="mb-2 mt-4 flex items-center justify-between">
|
||||
<MaintenanceEditModal />
|
||||
<ItemChangeDetails />
|
||||
|
||||
<BaseSectionHeader class="flex items-center justify-between" :class="{ 'mb-2 mt-4': !externalPagination }">
|
||||
<div class="flex gap-2 text-nowrap">
|
||||
{{ $t("components.item.view.selectable.items") }}
|
||||
<Badge>
|
||||
<Badge v-if="!externalPagination">
|
||||
{{ items.length }}
|
||||
</Badge>
|
||||
</div>
|
||||
<template #subtitle>
|
||||
<div
|
||||
id="selectable-subtitle"
|
||||
class="flex grow items-center px-2"
|
||||
:class="{ hidden: !preferences.quickActions.enabled }"
|
||||
/>
|
||||
</template>
|
||||
<template #description>
|
||||
<div v-if="!viewSet">
|
||||
<ButtonGroup>
|
||||
@@ -59,15 +86,26 @@
|
||||
</template>
|
||||
</BaseSectionHeader>
|
||||
|
||||
<template v-if="itemView === 'table'">
|
||||
<ItemViewTable :items="items" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3">
|
||||
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
||||
<div class="hidden first:block">{{ $t("components.item.view.selectable.no_items") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<p v-if="externalPagination && pagination!.totalSize > 0" class="mb-4 flex items-center text-base font-medium">
|
||||
{{ $t("items.results", { total: pagination!.totalSize }) }}
|
||||
<span class="ml-auto text-base">
|
||||
{{
|
||||
$t("items.pages", {
|
||||
page: pagination!.page,
|
||||
totalPages: Math.ceil(pagination!.totalSize / pagination!.pageSize),
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<DataTable
|
||||
:view="itemView"
|
||||
:columns="preferences.quickActions.enabled ? columns : columns.filter(c => c.enableHiding !== false)"
|
||||
:data="items"
|
||||
:location-flat-tree="locationFlatTree"
|
||||
:external-pagination="pagination"
|
||||
@refresh="$emit('refresh')"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user