Add nextCursor pagination to grid responses
- FTL: Capture Moqui pagination vars (pageIndex, pageSize, pageMaxIndex, listCount)
- Compact mode: Add nextCursor object with pageIndex, pageSize, hasMore
- ARIA mode: Add nextCursor to grid nodes
- Add totalCount to show full result size
Usage: Pass nextCursor values as parameters to get next page:
parameters: {pageIndex: 1, pageSize: 20}
Response format:
nextCursor: {pageIndex: 1, pageSize: 20, hasMore: true}
totalCount: 29
Showing
2 changed files
with
38 additions
and
4 deletions
| ... | @@ -266,11 +266,18 @@ | ... | @@ -266,11 +266,18 @@ |
| 266 | <#assign formListColumnList = formListInfo.getAllColInfo()> | 266 | <#assign formListColumnList = formListInfo.getAllColInfo()> |
| 267 | <#assign listObject = formListInfo.getListObject(false)!> | 267 | <#assign listObject = formListInfo.getListObject(false)!> |
| 268 | <#assign totalItems = (listObject?size)!0> | 268 | <#assign totalItems = (listObject?size)!0> |
| 269 | <#-- Get pagination variables from context (set by Moqui's XmlActions) --> | ||
| 270 | <#assign listName = formNode["@list"]!""> | ||
| 271 | <#assign pageIndex = (ec.context[listName + "PageIndex"])!0> | ||
| 272 | <#assign pageSize = (ec.context[listName + "PageSize"])!20> | ||
| 273 | <#assign listCount = (ec.context[listName + "Count"])!totalItems> | ||
| 274 | <#assign pageMaxIndex = (ec.context[listName + "PageMaxIndex"])!0> | ||
| 269 | 275 | ||
| 270 | <#if mcpSemanticData??> | 276 | <#if mcpSemanticData??> |
| 271 | <#assign formName = (.node["@name"]!"")?string> | 277 | <#assign formName = (.node["@name"]!"")?string> |
| 272 | <#assign displayedItems = (totalItems > 50)?then(50, totalItems)> | 278 | <#assign displayedItems = (totalItems > 50)?then(50, totalItems)> |
| 273 | <#assign isTruncated = (totalItems > 50)> | 279 | <#assign isTruncated = (totalItems > 50)> |
| 280 | <#assign hasMorePages = (pageIndex < pageMaxIndex)> | ||
| 274 | <#assign columnNames = []> | 281 | <#assign columnNames = []> |
| 275 | <#list formListColumnList as columnFieldList> | 282 | <#list formListColumnList as columnFieldList> |
| 276 | <#assign fieldNode = columnFieldList[0]> | 283 | <#assign fieldNode = columnFieldList[0]> |
| ... | @@ -395,7 +402,7 @@ | ... | @@ -395,7 +402,7 @@ |
| 395 | <#assign dummy = ec.context.put("tempListObject", listObject)!> | 402 | <#assign dummy = ec.context.put("tempListObject", listObject)!> |
| 396 | <#assign dummy = ec.context.put("tempColumnNames", columnNames)!> | 403 | <#assign dummy = ec.context.put("tempColumnNames", columnNames)!> |
| 397 | <#assign dummy = ec.context.put("tempFieldMetaList", fieldMetaList)!> | 404 | <#assign dummy = ec.context.put("tempFieldMetaList", fieldMetaList)!> |
| 398 | <#assign dummy = ec.resource.expression("mcpSemanticData.put('" + formName?js_string + "', tempListObject); if (mcpSemanticData.formMetadata == null) mcpSemanticData.formMetadata = [:]; mcpSemanticData.formMetadata.put('" + formName?js_string + "', [name: '" + formName?js_string + "', type: 'form-list', map: '', fields: tempFieldMetaList]); if (mcpSemanticData.listMetadata == null) mcpSemanticData.listMetadata = [:]; mcpSemanticData.listMetadata.put('" + formName?js_string + "', [name: '" + formName?js_string + "', totalItems: " + totalItems + ", displayedItems: " + displayedItems + ", truncated: " + isTruncated?string + ", columns: tempColumnNames])", "")!> | 405 | <#assign dummy = ec.resource.expression("mcpSemanticData.put('" + formName?js_string + "', tempListObject); if (mcpSemanticData.formMetadata == null) mcpSemanticData.formMetadata = [:]; mcpSemanticData.formMetadata.put('" + formName?js_string + "', [name: '" + formName?js_string + "', type: 'form-list', map: '', fields: tempFieldMetaList, pageIndex: " + pageIndex + ", pageSize: " + pageSize + ", pageMaxIndex: " + pageMaxIndex + ", listCount: " + listCount + "]); if (mcpSemanticData.listMetadata == null) mcpSemanticData.listMetadata = [:]; mcpSemanticData.listMetadata.put('" + formName?js_string + "', [name: '" + formName?js_string + "', totalItems: " + totalItems + ", displayedItems: " + displayedItems + ", truncated: " + isTruncated?string + ", columns: tempColumnNames])", "")!> |
| 399 | </#if> | 406 | </#if> |
| 400 | 407 | ||
| 401 | <#-- Header Row --> | 408 | <#-- Header Row --> | ... | ... |
| ... | @@ -944,13 +944,28 @@ def convertToAriaTree = { semanticState, targetScreenPath -> | ... | @@ -944,13 +944,28 @@ def convertToAriaTree = { semanticState, targetScreenPath -> |
| 944 | children << searchNode | 944 | children << searchNode |
| 945 | } | 945 | } |
| 946 | 946 | ||
| 947 | // Get pagination info from formData | ||
| 948 | def pageIndex = formData.pageIndex ?: 0 | ||
| 949 | def pageSize = formData.pageSize ?: 20 | ||
| 950 | def pageMaxIndex = formData.pageMaxIndex ?: 0 | ||
| 951 | def listCount = formData.listCount ?: itemCount | ||
| 952 | |||
| 947 | def gridNode = [ | 953 | def gridNode = [ |
| 948 | role: "grid", | 954 | role: "grid", |
| 949 | name: formData.name ?: formName, | 955 | name: formData.name ?: formName, |
| 950 | ref: formName, | 956 | ref: formName, |
| 951 | rowcount: itemCount | 957 | rowcount: listCount |
| 952 | ] | 958 | ] |
| 953 | 959 | ||
| 960 | // Add pagination cursor if there are more pages | ||
| 961 | if (pageIndex < pageMaxIndex) { | ||
| 962 | gridNode.nextCursor = [ | ||
| 963 | pageIndex: pageIndex + 1, | ||
| 964 | pageSize: pageSize, | ||
| 965 | hasMore: (pageIndex + 1) < pageMaxIndex | ||
| 966 | ] | ||
| 967 | } | ||
| 968 | |||
| 954 | // Add column info (only non-searchable display columns) | 969 | // Add column info (only non-searchable display columns) |
| 955 | def displayColumns = formData.fields?.findAll { !it.searchable }?.collect { it.title ?: it.name } | 970 | def displayColumns = formData.fields?.findAll { !it.searchable }?.collect { it.title ?: it.name } |
| 956 | if (displayColumns) gridNode.columns = displayColumns | 971 | if (displayColumns) gridNode.columns = displayColumns |
| ... | @@ -1260,9 +1275,21 @@ def convertToCompactFormat = { semanticState, targetScreenPath -> | ... | @@ -1260,9 +1275,21 @@ def convertToCompactFormat = { semanticState, targetScreenPath -> |
| 1260 | 1275 | ||
| 1261 | rowInfo | 1276 | rowInfo |
| 1262 | } | 1277 | } |
| 1263 | if (listData.size() > 10) { | 1278 | // Add pagination cursor if there are more pages |
| 1264 | gridInfo.more = listData.size() - 10 | 1279 | def gridPageIndex = formData.pageIndex ?: 0 |
| 1280 | def gridPageSize = formData.pageSize ?: 20 | ||
| 1281 | def gridPageMaxIndex = formData.pageMaxIndex ?: 0 | ||
| 1282 | def gridListCount = formData.listCount ?: listData.size() | ||
| 1283 | |||
| 1284 | if (gridPageIndex < gridPageMaxIndex) { | ||
| 1285 | // There are more pages - provide nextCursor | ||
| 1286 | gridInfo.nextCursor = [ | ||
| 1287 | pageIndex: gridPageIndex + 1, | ||
| 1288 | pageSize: gridPageSize, | ||
| 1289 | hasMore: (gridPageIndex + 1) < gridPageMaxIndex | ||
| 1290 | ] | ||
| 1265 | } | 1291 | } |
| 1292 | gridInfo.totalCount = gridListCount | ||
| 1266 | } else { | 1293 | } else { |
| 1267 | gridInfo.rowCount = 0 | 1294 | gridInfo.rowCount = 0 |
| 1268 | } | 1295 | } | ... | ... |
-
Please register or sign in to post a comment