-
Notifications
You must be signed in to change notification settings - Fork 23
feat: add dropdown for selecting page size options in list view #603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5f5d671
707947c
76a7d3d
b49e575
99eb1d1
a610e96
c03a3a7
8cd6d72
13c22f4
b3fe21c
93aba31
e3b985f
1d6a2f4
22d1c07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -340,6 +340,24 @@ | |
| </span> | ||
| </template> | ||
| </span> | ||
| <div v-if="totalRows > 0 && pageSizeOptionsComputed?.length" | ||
| class="flex items-center gap-2 ml-auto" > | ||
| <span class="text-sm text-lightListTablePaginationHelpText dark:text-darkListTablePaginationHelpText whitespace-nowrap"> | ||
| {{ $t('Rows per page') }} | ||
| </span> | ||
| <Select | ||
| v-model="pageSizeInternal" | ||
| :options="pageSizeOptionsComputed" | ||
| :searchDisabled="true" | ||
| :disableTogleOfSelectedItem="true" | ||
| :style="{ width: selectDynamicWidth }" | ||
| :placeholder="pageSizeInternal?.toString()" | ||
| class="text-sm " | ||
| classesForInput="h-[34px] min-h-0 py-1 pl-2 pr-6 text-sm rounded-md cursor-pointer af-button-shadow | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. w-fit |
||
| bg-lightDropdownButtonsBackground text-lightDropdownButtonsText border-lightDropdownButtonsBorder | ||
| dark:bg-darkDropdownButtonsBackground dark:text-darkDropdownButtonsText dark:border-darkDropdownButtonsBorder" | ||
| /> | ||
| </div> | ||
|
kulikp1 marked this conversation as resolved.
|
||
| </div> | ||
| </template> | ||
|
|
||
|
|
@@ -368,6 +386,7 @@ import { useAdminforth } from '@/adminforth'; | |
| import Checkbox from '@/afcl/Checkbox.vue'; | ||
| import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue'; | ||
| import CallActionWrapper from '@/components/CallActionWrapper.vue' | ||
| import Select from '@/afcl/Select.vue'; | ||
|
|
||
| const coreStore = useCoreStore(); | ||
| const { t } = useI18n(); | ||
|
|
@@ -378,6 +397,7 @@ const props = withDefaults(defineProps<{ | |
| rows: any[] | null, | ||
| totalRows: number, | ||
| pageSize: number, | ||
| pageSizeOptions?: { label: string; value: any }[] | number[] | null; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. { label: string; value: any }[] I thought user can enter only array with numbers |
||
| checkboxes: any[], | ||
| sort: any[], | ||
| noRoundings?: boolean, | ||
|
|
@@ -402,9 +422,16 @@ const rowsToRender = computed(() => { | |
| } | ||
| }); | ||
|
|
||
| const selectDynamicWidth = computed(() => { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can just remove fixed width and everything will be fine |
||
| const length = pageSizeInternal.value?.toString().length || 2; | ||
| const calculatedWidth = length * 9 + 50; | ||
| return `${Math.max(68, calculatedWidth)}px`; | ||
| }); | ||
|
|
||
| // emits, update page | ||
| const emits = defineEmits([ | ||
| 'update:page', | ||
| 'update:pageSize', | ||
| 'update:sort', | ||
| 'update:checkboxes', | ||
| 'update:records' | ||
|
|
@@ -414,6 +441,25 @@ const emits = defineEmits([ | |
| const checkboxesInternal: Ref<any[]> = ref([]); | ||
| const pageInput = ref('1'); | ||
| const page = ref(1); | ||
|
|
||
| const pageSizeInternal = ref(props.pageSize); | ||
|
|
||
| const pageSizeOptionsComputed = computed(() => { | ||
| if (!props.pageSizeOptions || props.pageSizeOptions.length === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| const firstItem = props.pageSizeOptions[0]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove it |
||
| if (typeof firstItem === 'object' && firstItem !== null) { | ||
| return props.pageSizeOptions as { label: string; value: any }[]; | ||
| } | ||
|
|
||
| return (props.pageSizeOptions as number[]).map(size => ({ | ||
| label: size.toString(), | ||
| value: size | ||
| })); | ||
| }); | ||
|
|
||
| const sort: Ref<Array<{field: string, direction: string}>> = ref([]); | ||
|
|
||
| const showListActionsThreeDots = computed(() => { | ||
|
|
@@ -465,6 +511,14 @@ watch(() => props.page, (newPage) => { | |
| page.value = newPage; | ||
| }); | ||
|
|
||
| watch(() => props.pageSize, (newPageSize) => { | ||
| pageSizeInternal.value = newPageSize; | ||
| }); | ||
|
|
||
| watch(pageSizeInternal, (newPageSize) => { | ||
| emits('update:pageSize', newPageSize); | ||
| }); | ||
|
|
||
| const rowRefs = useTemplateRef<HTMLElement[]>('rowRefs'); | ||
| const headerRefs = useTemplateRef<HTMLElement[]>('headerRefs'); | ||
| const rowHeights = ref<number[]>([]); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -171,6 +171,8 @@ | |
| @update:sort="sort = $event" | ||
| @update:checkboxes="checkboxes = $event" | ||
| @update:records="getListInner" | ||
| :pageSizeOptions="PAGE_SIZE_OPTIONS" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove it |
||
| @update:pageSize="pageSize = $event" | ||
| :sort="sort" | ||
| :pageSize="pageSize" | ||
| :totalRows="totalRows" | ||
|
|
@@ -260,8 +262,46 @@ const customActionLoadingStates = ref<{[key: string]: boolean}>({}); | |
|
|
||
| const DEFAULT_PAGE_SIZE = 10; | ||
|
|
||
| const PAGE_SIZE_OPTIONS = computed(() => { | ||
| const array = coreStore.resource?.options?.listPageSizeOptions; | ||
|
|
||
| if (!Array.isArray(array)) return undefined; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. null |
||
|
|
||
| return array.map((size: number) => ({ | ||
| label: size.toString(), | ||
| value: size | ||
| })); | ||
| }); | ||
|
|
||
| const pageSize = computed({ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can remove it |
||
| get() { | ||
| if (route.query.pageSize) { | ||
| const parsed = parseInt(route.query.pageSize as string); | ||
| if (PAGE_SIZE_OPTIONS.value?.some(o => o.value === parsed)) { | ||
| return parsed; | ||
| } | ||
| } | ||
|
|
||
| if (coreStore.resource?.options?.listPageSize) { | ||
| return coreStore.resource.options.listPageSize; | ||
| } | ||
|
|
||
| return DEFAULT_PAGE_SIZE; | ||
| }, | ||
|
|
||
| set(newSize) { | ||
| if (initInProcess) return; | ||
|
|
||
| page.value = 1; | ||
|
|
||
| setQuery({ | ||
| page: 1, | ||
| pageSize: newSize, | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
|
|
||
| const pageSize = computed(() => coreStore.resource?.options?.listPageSize || DEFAULT_PAGE_SIZE); | ||
| const isVirtualScrollEnabled = computed(() => coreStore.resource?.options?.listVirtualScrollEnabled || false); | ||
| const listBufferSize = computed(() => coreStore.resource?.options?.listBufferSize || 30); | ||
|
|
||
|
|
@@ -427,7 +467,7 @@ async function init() { | |
| // page init should be also in same tick | ||
| if (route.query.page) { | ||
| page.value = parseInt(route.query.page as string); | ||
| } | ||
| } | ||
|
|
||
| // getList(); - Not needed here, watch will trigger it | ||
| columnsMinMax.value = await callAdminForthApi({ | ||
|
|
@@ -446,7 +486,7 @@ async function init() { | |
| } | ||
| } | ||
|
|
||
| watch([page, sort, () => filtersStore.filters], async () => { | ||
| watch([page, pageSize, sort, () => filtersStore.filters], async () => { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove it |
||
| // console.log('🔄️ page/sort/filter change fired, page:', page.value); | ||
| await getListInner(); | ||
| }, { deep: true }); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.