mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 21:33:18 +01:00
feat: adds option to home page to show more than default containers per page (#2703)
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
!
|
!
|
||||||
<template>
|
<template>
|
||||||
|
<div class="text-right">
|
||||||
|
Show per page
|
||||||
|
<dropdown-menu
|
||||||
|
class="dropdown-left"
|
||||||
|
v-model="perPage"
|
||||||
|
:options="pageSizes.map((i) => ({ label: i.toLocaleString(), value: i }))"
|
||||||
|
v-if="containers.length > 0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<table class="table table-lg bg-base">
|
<table class="table table-lg bg-base">
|
||||||
<thead>
|
<thead>
|
||||||
<tr :data-direction="direction > 0 ? 'asc' : 'desc'">
|
<tr :data-direction="direction > 0 ? 'asc' : 'desc'">
|
||||||
@@ -95,12 +104,14 @@ const fields = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { containers, perPage = 15 } = defineProps<{
|
const { containers } = defineProps<{
|
||||||
containers: Container[];
|
containers: Container[];
|
||||||
perPage?: number;
|
|
||||||
}>();
|
}>();
|
||||||
type keys = keyof typeof fields;
|
type keys = keyof typeof fields;
|
||||||
|
|
||||||
|
const perPage = useStorage("DOZZLE_TABLE_PAGE_SIZE", 15);
|
||||||
|
const pageSizes = [15, 30, 50, 100];
|
||||||
|
|
||||||
const storage = useStorage<{ column: keys; direction: 1 | -1 }>("DOZZLE_TABLE_CONTAINERS_SORT", {
|
const storage = useStorage<{ column: keys; direction: 1 | -1 }>("DOZZLE_TABLE_CONTAINERS_SORT", {
|
||||||
column: "created",
|
column: "created",
|
||||||
direction: -1,
|
direction: -1,
|
||||||
@@ -115,12 +126,12 @@ const sortedContainers = computedWithControl(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(sortedContainers.value.length / perPage));
|
const totalPages = computed(() => Math.ceil(sortedContainers.value.length / perPage.value));
|
||||||
const isPaginated = computed(() => totalPages.value > 1);
|
const isPaginated = computed(() => totalPages.value > 1);
|
||||||
const currentPage = ref(1);
|
const currentPage = ref(1);
|
||||||
const paginated = computed(() => {
|
const paginated = computed(() => {
|
||||||
const start = (currentPage.value - 1) * perPage;
|
const start = (currentPage.value - 1) * perPage.value;
|
||||||
const end = start + perPage;
|
const end = start + perPage.value;
|
||||||
|
|
||||||
return sortedContainers.value.slice(start, end);
|
return sortedContainers.value.slice(start, end);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<details class="dropdown" ref="details" v-on-click-outside="close">
|
<details class="dropdown" ref="details" v-on-click-outside="close">
|
||||||
<summary class="btn btn-primary flex-nowrap" v-bind="$attrs">
|
<summary class="btn btn-primary flex-nowrap" v-bind="$attrs">
|
||||||
<slot name="trigger"> {{ values[modelValue] ?? defaultLabel }} <carbon:caret-down /></slot>
|
<slot name="trigger"> {{ label }} <carbon:caret-down /></slot>
|
||||||
</summary>
|
</summary>
|
||||||
<ul class="menu dropdown-content rounded-box z-50 mt-1 w-52 border border-base-content/20 bg-base p-2 shadow">
|
<ul class="menu dropdown-content z-50 mt-1 w-52 rounded-box border border-base-content/20 bg-base p-2 shadow">
|
||||||
<slot>
|
<slot>
|
||||||
<li v-for="item in options">
|
<li v-for="item in options">
|
||||||
<a @click="modelValue = item.value">
|
<a @click="modelValue = item.value">
|
||||||
@@ -17,27 +17,18 @@
|
|||||||
</details>
|
</details>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup generic="T">
|
||||||
import { vOnClickOutside } from "@vueuse/components";
|
import { vOnClickOutside } from "@vueuse/components";
|
||||||
type DropdownItem = {
|
type DropdownItem = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: T;
|
||||||
};
|
};
|
||||||
const { options = [], defaultLabel = "" } = defineProps<{ options?: DropdownItem[]; defaultLabel?: string }>();
|
const { options = [], defaultLabel = "" } = defineProps<{ options?: DropdownItem[]; defaultLabel?: string }>();
|
||||||
const { modelValue } = defineModels<{
|
const { modelValue } = defineModels<{
|
||||||
modelValue: string;
|
modelValue: T;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const values = computed(() =>
|
const label = computed(() => options.find((item) => item.value === modelValue.value)?.label ?? defaultLabel);
|
||||||
options.reduce(
|
|
||||||
(acc, curr) => {
|
|
||||||
acc[curr.value] = curr.label;
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, string>,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
const details = ref<HTMLElement | null>(null);
|
const details = ref<HTMLElement | null>(null);
|
||||||
const close = () => details.value?.removeAttribute("open");
|
const close = () => details.value?.removeAttribute("open");
|
||||||
watch(modelValue, () => close());
|
watch(modelValue, () => close());
|
||||||
|
|||||||
Reference in New Issue
Block a user