7f95b312 by Ean Schuessler

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
1 parent 0153ca18
...@@ -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,12 +944,27 @@ def convertToAriaTree = { semanticState, targetScreenPath -> ...@@ -944,12 +944,27 @@ 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
958 ]
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
952 ] 966 ]
967 }
953 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 }
...@@ -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 }
......