diff --git a/adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md b/adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md index 8f6f1da61..d4bd3e304 100644 --- a/adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md +++ b/adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md @@ -542,6 +542,26 @@ And `edit` action will be available as quick action: +## Show + +### Next record button + +By default, when a user opens a record from the list view, a **Next** button appears on the show page. It allows navigating through records one by one, respecting the current filters and sorting applied in the list. When the user reaches the last record on the current page, AdminForth automatically fetches the next page and continues navigation seamlessly. + +To disable the Next button for a resource, set `showNextButton` to `false`: + +```typescript title="./resources/apartments.ts" +export default { + resourceId: 'aparts', + options: { +//diff-add + showNextButton: false, + } +} +``` + +> ☝️ The Next button is only shown when the user navigates to the show page from the list view. Opening a record directly via URL will not display the button. + ## Creating ### Fill with default values diff --git a/adminforth/modules/restApi.ts b/adminforth/modules/restApi.ts index d77c474be..dbb208641 100644 --- a/adminforth/modules/restApi.ts +++ b/adminforth/modules/restApi.ts @@ -318,6 +318,7 @@ const getResourceDataResponseSchema: AnySchemaObject = createErrorOrSuccessSchem items: genericObjectSchema, }, total: { type: 'number' }, + recordIds: { type: 'array', items: {} }, options: genericObjectSchema, }, additionalProperties: true, @@ -1599,6 +1600,11 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { } } + if (source === 'list') { + const pkField = resource.columns.find((col) => col.primaryKey).name; + (data as any).recordIds = data.data.map((item) => item[pkField]); + } + return data; }, }); diff --git a/adminforth/spa/src/components/ResourceListTable.vue b/adminforth/spa/src/components/ResourceListTable.vue index d4f034f0b..8b8a456fa 100644 --- a/adminforth/spa/src/components/ResourceListTable.vue +++ b/adminforth/spa/src/components/ResourceListTable.vue @@ -422,7 +422,8 @@ const props = withDefaults(defineProps<{ bufferSize?: number, customActionIconsThreeDotsMenuItems?: AdminForthComponentDeclaration[] tableRowReplaceInjection?: AdminForthComponentDeclaration, - isVirtualScrollEnabled: boolean + isVirtualScrollEnabled: boolean, + filters?: any[] }>(), { sort: () => [] }); @@ -615,6 +616,12 @@ async function onClick(e: any, row: any) { // user asked to nothing on click return; } + coreStore.listRecordIds = props.rows?.map(r => r._primaryKeyValue) ?? []; + coreStore.listResourceId = props.resource?.resourceId ?? null; + coreStore.listSort = props.sort; + coreStore.listPage = page.value; + coreStore.listPageSize = props.pageSize; + coreStore.listFilters = props.filters ?? []; if (e.ctrlKey || e.metaKey || row._clickUrl?.includes('target=_blank')) { if (row._clickUrl) { diff --git a/adminforth/spa/src/stores/core.ts b/adminforth/spa/src/stores/core.ts index eb0763e71..e7e7fb910 100644 --- a/adminforth/spa/src/stores/core.ts +++ b/adminforth/spa/src/stores/core.ts @@ -22,6 +22,12 @@ export const useCoreStore = defineStore('core', () => { const isResourceFetching = ref(false); const isInternetError = ref(false); const screenWidth = ref(window.innerWidth); + const listRecordIds: Ref = ref([]); + const listResourceId: Ref = ref(null); + const listFilters: Ref = ref([]); + const listSort: Ref = ref([]); + const listPage: Ref = ref(0); + const listPageSize: Ref = ref(0); onMounted(() => { window.addEventListener('resize', updateWidth); @@ -290,5 +296,11 @@ export const useCoreStore = defineStore('core', () => { isIos, isInternetError, isMobile, + listRecordIds, + listResourceId, + listFilters, + listSort, + listPage, + listPageSize, } }) diff --git a/adminforth/spa/src/utils/listUtils.ts b/adminforth/spa/src/utils/listUtils.ts index 213ab0b29..e8f3b3832 100644 --- a/adminforth/spa/src/utils/listUtils.ts +++ b/adminforth/spa/src/utils/listUtils.ts @@ -47,11 +47,12 @@ export async function getList(resource: AdminForthResourceFrontend, isPageLoaded return row; }); totalRows = data.total; - + const recordIds = data.recordIds || []; + // if checkboxes have items which are not in current data, remove them checkboxes.value = checkboxes.value.filter((pk: any) => rows.some((r: any) => r._primaryKeyValue === pk)); await nextTick(); - return { rows, totalRows }; + return { rows, totalRows, recordIds }; } diff --git a/adminforth/spa/src/views/ListView.vue b/adminforth/spa/src/views/ListView.vue index 2af88e6cd..a0dfe5f82 100644 --- a/adminforth/spa/src/views/ListView.vue +++ b/adminforth/spa/src/views/ListView.vue @@ -180,6 +180,7 @@ @update:records="getListInner" @update:pageSize="(newSize) => { pageSize = newSize; page = 1; }" :sort="sort" + :filters="filtersStore.filters" :pageSizeOptions="Array.isArray(coreStore.resource?.options?.listPageSizeOptions) ? coreStore.resource?.options?.listPageSizeOptions : []" :pageSize="pageSize" :totalRows="totalRows" diff --git a/adminforth/spa/src/views/ShowView.vue b/adminforth/spa/src/views/ShowView.vue index f9647f195..bb9616803 100644 --- a/adminforth/spa/src/views/ShowView.vue +++ b/adminforth/spa/src/views/ShowView.vue @@ -10,6 +10,17 @@ :adminUser="coreStore.adminUser" /> + + + {{ $t('Next') }} + +