@josephyan/qingflow-app-builder-mcp 0.2.0-beta.1011 → 0.2.0-beta.1012
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/cli/commands/exports.py +8 -0
- package/src/qingflow_mcp/server.py +4 -0
- package/src/qingflow_mcp/server_app_user.py +8 -0
- package/src/qingflow_mcp/tools/export_tools.py +166 -6
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @josephyan/qingflow-app-builder-mcp@0.2.0-beta.
|
|
6
|
+
npm install @josephyan/qingflow-app-builder-mcp@0.2.0-beta.1012
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-app-builder-mcp@0.2.0-beta.
|
|
12
|
+
npx -y -p @josephyan/qingflow-app-builder-mcp@0.2.0-beta.1012 qingflow-app-builder-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -15,6 +15,7 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
|
|
|
15
15
|
start.add_argument("--view-id", default="system:all")
|
|
16
16
|
start.add_argument("--column", dest="columns", action="append", type=int, default=[], help="只导出这些 field_id;不传时导出当前视图全部字段")
|
|
17
17
|
start.add_argument("--columns-file", help="JSON/YAML list,内容与 --column 语义一致")
|
|
18
|
+
start.add_argument("--where-file", help="JSON/YAML list,内容与 record list 的 where DSL 一致;内部先查命中 record_id 再走原生导出")
|
|
18
19
|
start.add_argument("--record-id", dest="record_ids", action="append", default=[], help="只导出这些 record_id;不传时导出当前视图全部数据")
|
|
19
20
|
start.add_argument("--record-ids-file", help="JSON/YAML list,内容与 --record-id 语义一致")
|
|
20
21
|
start.add_argument("--include-workflow-log", action=argparse.BooleanOptionalAction, default=False, help="是否同时导出流程日志")
|
|
@@ -34,6 +35,7 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
|
|
|
34
35
|
direct.add_argument("--view-id", default="system:all")
|
|
35
36
|
direct.add_argument("--column", dest="columns", action="append", type=int, default=[], help="只导出这些 field_id;不传时导出当前视图全部字段")
|
|
36
37
|
direct.add_argument("--columns-file", help="JSON/YAML list,内容与 --column 语义一致")
|
|
38
|
+
direct.add_argument("--where-file", help="JSON/YAML list,内容与 record list 的 where DSL 一致;内部先查命中 record_id 再走原生导出")
|
|
37
39
|
direct.add_argument("--record-id", dest="record_ids", action="append", default=[], help="只导出这些 record_id;不传时导出当前视图全部数据")
|
|
38
40
|
direct.add_argument("--record-ids-file", help="JSON/YAML list,内容与 --record-id 语义一致")
|
|
39
41
|
direct.add_argument("--include-workflow-log", action=argparse.BooleanOptionalAction, default=False, help="是否同时导出流程日志")
|
|
@@ -56,12 +58,17 @@ def _record_ids(args: argparse.Namespace) -> list[str | int]:
|
|
|
56
58
|
return record_ids
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
def _where(args: argparse.Namespace) -> list[dict]:
|
|
62
|
+
return load_list_arg(args.where_file, option_name="--where-file") if args.where_file else []
|
|
63
|
+
|
|
64
|
+
|
|
59
65
|
def _handle_start(args: argparse.Namespace, context: CliContext) -> dict:
|
|
60
66
|
return context.exports.record_export_start(
|
|
61
67
|
profile=args.profile,
|
|
62
68
|
app_key=args.app_key,
|
|
63
69
|
view_id=args.view_id,
|
|
64
70
|
columns=_columns(args),
|
|
71
|
+
where=_where(args),
|
|
65
72
|
record_ids=_record_ids(args),
|
|
66
73
|
include_workflow_log=args.include_workflow_log,
|
|
67
74
|
)
|
|
@@ -88,6 +95,7 @@ def _handle_direct(args: argparse.Namespace, context: CliContext) -> dict:
|
|
|
88
95
|
app_key=args.app_key,
|
|
89
96
|
view_id=args.view_id,
|
|
90
97
|
columns=_columns(args),
|
|
98
|
+
where=_where(args),
|
|
91
99
|
record_ids=_record_ids(args),
|
|
92
100
|
include_workflow_log=args.include_workflow_log,
|
|
93
101
|
download_to_path=args.download_to_path,
|
|
@@ -158,6 +158,10 @@ Use `record_code_block_run` when the user wants to execute a form code-block fie
|
|
|
158
158
|
- `record_export_start` / `record_export_direct` support frontend-like row selection:
|
|
159
159
|
- omit `record_ids` to export all rows in the selected view
|
|
160
160
|
- pass `record_ids` to export selected rows only
|
|
161
|
+
- `record_export_start` / `record_export_direct` also support internal query selection:
|
|
162
|
+
- pass `where` to resolve matching `record_id` values first
|
|
163
|
+
- then run native export as selected rows
|
|
164
|
+
- `where` and `record_ids` are mutually exclusive
|
|
161
165
|
- `record_export_start` / `record_export_direct` also support frontend-like column selection:
|
|
162
166
|
- omit `columns` to export all current-view fields
|
|
163
167
|
- pass `columns` to export only selected fields, preserving the provided order
|
|
@@ -153,6 +153,10 @@ Use `record_code_block_run` when the user wants to execute a form code-block fie
|
|
|
153
153
|
- `record_export_start` / `record_export_direct` support frontend-like row selection:
|
|
154
154
|
- omit `record_ids` to export all rows in the selected view
|
|
155
155
|
- pass `record_ids` to export selected rows only
|
|
156
|
+
- `record_export_start` / `record_export_direct` also support internal query selection:
|
|
157
|
+
- pass `where` to resolve matching `record_id` values first
|
|
158
|
+
- then run native export as selected rows
|
|
159
|
+
- `where` and `record_ids` are mutually exclusive
|
|
156
160
|
- `record_export_start` / `record_export_direct` also support frontend-like column selection:
|
|
157
161
|
- omit `columns` to export all current-view fields
|
|
158
162
|
- pass `columns` to export only selected fields, preserving the provided order
|
|
@@ -241,6 +245,7 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
241
245
|
app_key: str = "",
|
|
242
246
|
view_id: str = "system:all",
|
|
243
247
|
columns: list[dict | int] | None = None,
|
|
248
|
+
where: list[dict] | None = None,
|
|
244
249
|
record_ids: list[str | int] | None = None,
|
|
245
250
|
include_workflow_log: bool = False,
|
|
246
251
|
) -> dict:
|
|
@@ -249,6 +254,7 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
249
254
|
app_key=app_key,
|
|
250
255
|
view_id=view_id,
|
|
251
256
|
columns=columns or [],
|
|
257
|
+
where=where or [],
|
|
252
258
|
record_ids=record_ids or [],
|
|
253
259
|
include_workflow_log=include_workflow_log,
|
|
254
260
|
)
|
|
@@ -278,6 +284,7 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
278
284
|
app_key: str = "",
|
|
279
285
|
view_id: str = "system:all",
|
|
280
286
|
columns: list[dict | int] | None = None,
|
|
287
|
+
where: list[dict] | None = None,
|
|
281
288
|
record_ids: list[str | int] | None = None,
|
|
282
289
|
include_workflow_log: bool = False,
|
|
283
290
|
download_to_path: str | None = None,
|
|
@@ -288,6 +295,7 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
288
295
|
app_key=app_key,
|
|
289
296
|
view_id=view_id,
|
|
290
297
|
columns=columns or [],
|
|
298
|
+
where=where or [],
|
|
291
299
|
record_ids=record_ids or [],
|
|
292
300
|
include_workflow_log=include_workflow_log,
|
|
293
301
|
download_to_path=download_to_path,
|
|
@@ -18,6 +18,7 @@ from ..json_types import JSONObject
|
|
|
18
18
|
from .base import ToolBase, tool_cn_name
|
|
19
19
|
from .record_tools import (
|
|
20
20
|
AccessibleViewRoute,
|
|
21
|
+
DEFAULT_LIST_PAGE_SIZE,
|
|
21
22
|
LAYOUT_ONLY_QUE_TYPES,
|
|
22
23
|
RecordTools,
|
|
23
24
|
_normalize_public_column_selectors,
|
|
@@ -58,6 +59,7 @@ class ExportTools(ToolBase):
|
|
|
58
59
|
app_key: str = "",
|
|
59
60
|
view_id: str = "system:all",
|
|
60
61
|
columns: list[JSONObject | int] | None = None,
|
|
62
|
+
where: list[JSONObject] | None = None,
|
|
61
63
|
record_ids: list[str | int] | None = None,
|
|
62
64
|
include_workflow_log: bool = False,
|
|
63
65
|
) -> dict[str, Any]:
|
|
@@ -66,6 +68,7 @@ class ExportTools(ToolBase):
|
|
|
66
68
|
app_key=app_key,
|
|
67
69
|
view_id=view_id,
|
|
68
70
|
columns=columns or [],
|
|
71
|
+
where=where or [],
|
|
69
72
|
record_ids=record_ids or [],
|
|
70
73
|
include_workflow_log=include_workflow_log,
|
|
71
74
|
)
|
|
@@ -98,6 +101,7 @@ class ExportTools(ToolBase):
|
|
|
98
101
|
app_key: str = "",
|
|
99
102
|
view_id: str = "system:all",
|
|
100
103
|
columns: list[JSONObject | int] | None = None,
|
|
104
|
+
where: list[JSONObject] | None = None,
|
|
101
105
|
record_ids: list[str | int] | None = None,
|
|
102
106
|
include_workflow_log: bool = False,
|
|
103
107
|
download_to_path: str | None = None,
|
|
@@ -108,6 +112,7 @@ class ExportTools(ToolBase):
|
|
|
108
112
|
app_key=app_key,
|
|
109
113
|
view_id=view_id,
|
|
110
114
|
columns=columns or [],
|
|
115
|
+
where=where or [],
|
|
111
116
|
record_ids=record_ids or [],
|
|
112
117
|
include_workflow_log=include_workflow_log,
|
|
113
118
|
download_to_path=download_to_path,
|
|
@@ -122,12 +127,14 @@ class ExportTools(ToolBase):
|
|
|
122
127
|
app_key: str,
|
|
123
128
|
view_id: str = "system:all",
|
|
124
129
|
columns: list[JSONObject | int] | None = None,
|
|
130
|
+
where: list[JSONObject] | None = None,
|
|
125
131
|
record_ids: list[str | int] | None = None,
|
|
126
132
|
include_workflow_log: bool = False,
|
|
127
133
|
) -> dict[str, Any]:
|
|
128
134
|
normalized_app_key = str(app_key or "").strip()
|
|
129
135
|
normalized_view_id = str(view_id or "").strip() or "system:all"
|
|
130
136
|
normalized_columns = _normalize_export_columns(columns or [])
|
|
137
|
+
normalized_where = self._record_tools._normalize_record_list_where(where or [])
|
|
131
138
|
normalized_record_ids = _normalize_export_record_ids(record_ids or [])
|
|
132
139
|
if not normalized_app_key:
|
|
133
140
|
return self._failed_export_result(
|
|
@@ -154,11 +161,20 @@ class ExportTools(ToolBase):
|
|
|
154
161
|
resolved_view=resolved_view,
|
|
155
162
|
column_selectors=normalized_columns,
|
|
156
163
|
)
|
|
164
|
+
effective_record_ids, row_scope = self._resolve_export_record_scope(
|
|
165
|
+
profile=profile,
|
|
166
|
+
context=context,
|
|
167
|
+
app_key=normalized_app_key,
|
|
168
|
+
resolved_view=resolved_view,
|
|
169
|
+
selected_record_ids=normalized_record_ids,
|
|
170
|
+
where_filters=normalized_where,
|
|
171
|
+
select_columns=cast(list[JSONObject], export_config.get("questionExportConfigList") or []),
|
|
172
|
+
)
|
|
157
173
|
result_amount = self._estimate_export_result_amount(
|
|
158
174
|
context,
|
|
159
175
|
app_key=normalized_app_key,
|
|
160
176
|
resolved_view=resolved_view,
|
|
161
|
-
selected_record_ids=
|
|
177
|
+
selected_record_ids=effective_record_ids,
|
|
162
178
|
)
|
|
163
179
|
self._validate_export_limits(
|
|
164
180
|
result_amount=result_amount,
|
|
@@ -167,7 +183,7 @@ class ExportTools(ToolBase):
|
|
|
167
183
|
)
|
|
168
184
|
filter_bean = self._build_export_filter_bean(
|
|
169
185
|
resolved_view,
|
|
170
|
-
selected_record_ids=
|
|
186
|
+
selected_record_ids=effective_record_ids,
|
|
171
187
|
include_workflow_log=include_workflow_log,
|
|
172
188
|
)
|
|
173
189
|
started_at = _utc_now().replace(microsecond=0).isoformat()
|
|
@@ -180,7 +196,6 @@ class ExportTools(ToolBase):
|
|
|
180
196
|
export_config=export_config,
|
|
181
197
|
result_amount=result_amount,
|
|
182
198
|
)
|
|
183
|
-
row_scope = "selected" if normalized_record_ids else "all"
|
|
184
199
|
column_scope = "selected" if normalized_columns else "all"
|
|
185
200
|
export_handle = uuid4().hex
|
|
186
201
|
self._job_store.put(
|
|
@@ -194,7 +209,7 @@ class ExportTools(ToolBase):
|
|
|
194
209
|
"started_at": started_at,
|
|
195
210
|
"uid": session_profile.uid,
|
|
196
211
|
"row_scope": row_scope,
|
|
197
|
-
"selected_record_count": len(
|
|
212
|
+
"selected_record_count": len(effective_record_ids),
|
|
198
213
|
"field_scope": column_scope,
|
|
199
214
|
"selected_field_count": len(cast(list[JSONObject], export_config.get("questionExportConfigList") or [])),
|
|
200
215
|
"include_workflow_log": bool(include_workflow_log),
|
|
@@ -212,7 +227,7 @@ class ExportTools(ToolBase):
|
|
|
212
227
|
"view_id": resolved_view.view_id,
|
|
213
228
|
"export_handle": export_handle,
|
|
214
229
|
"row_scope": row_scope,
|
|
215
|
-
"selected_record_count": len(
|
|
230
|
+
"selected_record_count": len(effective_record_ids),
|
|
216
231
|
"field_scope": column_scope,
|
|
217
232
|
"selected_field_count": len(cast(list[JSONObject], export_config.get("questionExportConfigList") or [])),
|
|
218
233
|
"include_workflow_log": bool(include_workflow_log),
|
|
@@ -223,7 +238,8 @@ class ExportTools(ToolBase):
|
|
|
223
238
|
"verification": {
|
|
224
239
|
"export_acknowledged": bool(socket_result.get("backend_export_id")),
|
|
225
240
|
"view_route_supported": True,
|
|
226
|
-
"row_selection_applied": bool(
|
|
241
|
+
"row_selection_applied": bool(effective_record_ids),
|
|
242
|
+
"query_filter_applied": bool(normalized_where),
|
|
227
243
|
"field_selection_applied": bool(normalized_columns),
|
|
228
244
|
},
|
|
229
245
|
"request_route": self.backend.describe_route(context),
|
|
@@ -407,6 +423,7 @@ class ExportTools(ToolBase):
|
|
|
407
423
|
app_key: str,
|
|
408
424
|
view_id: str = "system:all",
|
|
409
425
|
columns: list[JSONObject | int] | None = None,
|
|
426
|
+
where: list[JSONObject] | None = None,
|
|
410
427
|
record_ids: list[str | int] | None = None,
|
|
411
428
|
include_workflow_log: bool = False,
|
|
412
429
|
download_to_path: str | None = None,
|
|
@@ -428,6 +445,7 @@ class ExportTools(ToolBase):
|
|
|
428
445
|
app_key=normalized_app_key,
|
|
429
446
|
view_id=normalized_view_id,
|
|
430
447
|
columns=columns or [],
|
|
448
|
+
where=where or [],
|
|
431
449
|
record_ids=record_ids or [],
|
|
432
450
|
include_workflow_log=include_workflow_log,
|
|
433
451
|
)
|
|
@@ -552,6 +570,141 @@ class ExportTools(ToolBase):
|
|
|
552
570
|
extra={"app_key": normalized_app_key, "view_id": normalized_view_id},
|
|
553
571
|
)
|
|
554
572
|
|
|
573
|
+
def _resolve_export_record_scope(
|
|
574
|
+
self,
|
|
575
|
+
*,
|
|
576
|
+
profile: str,
|
|
577
|
+
context,
|
|
578
|
+
app_key: str,
|
|
579
|
+
resolved_view: AccessibleViewRoute,
|
|
580
|
+
selected_record_ids: list[int],
|
|
581
|
+
where_filters: list[JSONObject],
|
|
582
|
+
select_columns: list[JSONObject],
|
|
583
|
+
) -> tuple[list[int], str]:
|
|
584
|
+
if selected_record_ids and where_filters:
|
|
585
|
+
raise QingflowApiError(
|
|
586
|
+
category="config",
|
|
587
|
+
message="record export does not allow record_ids and where at the same time",
|
|
588
|
+
details={
|
|
589
|
+
"error_code": "EXPORT_ROW_SCOPE_CONFLICT",
|
|
590
|
+
"fix_hint": "Use record_ids for explicit selected rows or where for internal query selection, but not both.",
|
|
591
|
+
},
|
|
592
|
+
)
|
|
593
|
+
if selected_record_ids:
|
|
594
|
+
return selected_record_ids, "selected"
|
|
595
|
+
if not where_filters:
|
|
596
|
+
return [], "all"
|
|
597
|
+
resolved_ids = self._collect_record_ids_from_where(
|
|
598
|
+
profile=profile,
|
|
599
|
+
context=context,
|
|
600
|
+
app_key=app_key,
|
|
601
|
+
resolved_view=resolved_view,
|
|
602
|
+
where_filters=where_filters,
|
|
603
|
+
select_columns=select_columns,
|
|
604
|
+
)
|
|
605
|
+
if not resolved_ids:
|
|
606
|
+
raise QingflowApiError.config_error(
|
|
607
|
+
"record export query did not match any records",
|
|
608
|
+
details={
|
|
609
|
+
"error_code": "EXPORT_NO_MATCHED_RECORDS",
|
|
610
|
+
"view_id": resolved_view.view_id,
|
|
611
|
+
},
|
|
612
|
+
)
|
|
613
|
+
return resolved_ids, "queried"
|
|
614
|
+
|
|
615
|
+
def _collect_record_ids_from_where(
|
|
616
|
+
self,
|
|
617
|
+
*,
|
|
618
|
+
profile: str,
|
|
619
|
+
context,
|
|
620
|
+
app_key: str,
|
|
621
|
+
resolved_view: AccessibleViewRoute,
|
|
622
|
+
where_filters: list[JSONObject],
|
|
623
|
+
select_columns: list[JSONObject],
|
|
624
|
+
) -> list[int]:
|
|
625
|
+
browse_scope = self._record_tools._build_browse_write_scope(
|
|
626
|
+
profile,
|
|
627
|
+
context,
|
|
628
|
+
app_key,
|
|
629
|
+
resolved_view,
|
|
630
|
+
force_refresh=False,
|
|
631
|
+
)
|
|
632
|
+
index = browse_scope["index"]
|
|
633
|
+
match_rules = self._record_tools._resolve_match_rules(context, where_filters, index)
|
|
634
|
+
dept_member_cache: dict[int, set[int]] = {}
|
|
635
|
+
current_page = 1
|
|
636
|
+
selected_ids: list[int] = []
|
|
637
|
+
seen: set[int] = set()
|
|
638
|
+
primary_field_ids = [
|
|
639
|
+
_coerce_int(item.get("queId"))
|
|
640
|
+
for item in select_columns
|
|
641
|
+
if isinstance(item, dict)
|
|
642
|
+
]
|
|
643
|
+
primary_search_que_ids = [item for item in primary_field_ids if item is not None][:1] or None
|
|
644
|
+
|
|
645
|
+
while True:
|
|
646
|
+
page = self._record_tools._search_page(
|
|
647
|
+
context,
|
|
648
|
+
app_key=app_key,
|
|
649
|
+
view_selection=resolved_view.view_selection,
|
|
650
|
+
page_num=current_page,
|
|
651
|
+
page_size=DEFAULT_LIST_PAGE_SIZE,
|
|
652
|
+
query_key=None,
|
|
653
|
+
match_rules=match_rules,
|
|
654
|
+
sorts=[],
|
|
655
|
+
search_que_ids=primary_search_que_ids,
|
|
656
|
+
list_type=resolved_view.list_type if resolved_view.list_type is not None else DEFAULT_RECORD_LIST_TYPE,
|
|
657
|
+
)
|
|
658
|
+
raw_rows = page.get("list")
|
|
659
|
+
items = raw_rows if isinstance(raw_rows, list) else []
|
|
660
|
+
for item in items:
|
|
661
|
+
if not isinstance(item, dict):
|
|
662
|
+
continue
|
|
663
|
+
answers = item.get("answers")
|
|
664
|
+
answer_list = answers if isinstance(answers, list) else []
|
|
665
|
+
if not self._record_tools._matches_view_selection(
|
|
666
|
+
context,
|
|
667
|
+
answer_list,
|
|
668
|
+
view_selection=resolved_view.view_selection,
|
|
669
|
+
dept_member_cache=dept_member_cache,
|
|
670
|
+
):
|
|
671
|
+
continue
|
|
672
|
+
record_id = _coerce_int(item.get("applyId"))
|
|
673
|
+
if record_id is None:
|
|
674
|
+
record_id = _coerce_int(item.get("apply_id"))
|
|
675
|
+
if record_id is None:
|
|
676
|
+
record_id = _coerce_int(item.get("id"))
|
|
677
|
+
if record_id is None:
|
|
678
|
+
record_id = _coerce_int(item.get("record_id"))
|
|
679
|
+
if record_id is None or record_id in seen or record_id <= 0:
|
|
680
|
+
continue
|
|
681
|
+
seen.add(record_id)
|
|
682
|
+
selected_ids.append(record_id)
|
|
683
|
+
if len(selected_ids) > EXPORT_ROWS_LIMIT:
|
|
684
|
+
raise QingflowApiError.config_error(
|
|
685
|
+
f"record export exceeds the native row limit of {EXPORT_ROWS_LIMIT}",
|
|
686
|
+
details={
|
|
687
|
+
"error_code": "EXPORT_ROWS_LIMIT_EXCEEDED",
|
|
688
|
+
"result_amount": len(selected_ids),
|
|
689
|
+
"row_limit": EXPORT_ROWS_LIMIT,
|
|
690
|
+
},
|
|
691
|
+
)
|
|
692
|
+
if current_page == 1:
|
|
693
|
+
reported_total = _effective_total(page, page_size=DEFAULT_LIST_PAGE_SIZE)
|
|
694
|
+
if reported_total > EXPORT_ROWS_LIMIT:
|
|
695
|
+
raise QingflowApiError.config_error(
|
|
696
|
+
f"record export exceeds the native row limit of {EXPORT_ROWS_LIMIT}",
|
|
697
|
+
details={
|
|
698
|
+
"error_code": "EXPORT_ROWS_LIMIT_EXCEEDED",
|
|
699
|
+
"result_amount": reported_total,
|
|
700
|
+
"row_limit": EXPORT_ROWS_LIMIT,
|
|
701
|
+
},
|
|
702
|
+
)
|
|
703
|
+
if not _page_has_more(page, current_page=current_page, page_size=DEFAULT_LIST_PAGE_SIZE, returned_rows=len(items)):
|
|
704
|
+
break
|
|
705
|
+
current_page += 1
|
|
706
|
+
return selected_ids
|
|
707
|
+
|
|
555
708
|
def _build_export_filter_bean(
|
|
556
709
|
self,
|
|
557
710
|
resolved_view: AccessibleViewRoute,
|
|
@@ -1101,6 +1254,13 @@ def _effective_total(page: JSONObject, *, page_size: int) -> int:
|
|
|
1101
1254
|
return returned_rows
|
|
1102
1255
|
|
|
1103
1256
|
|
|
1257
|
+
def _page_has_more(page: JSONObject, *, current_page: int, page_size: int, returned_rows: int) -> bool:
|
|
1258
|
+
page_amount = _coerce_int(page.get("pageAmount"))
|
|
1259
|
+
if page_amount is not None:
|
|
1260
|
+
return current_page < page_amount
|
|
1261
|
+
return returned_rows >= page_size
|
|
1262
|
+
|
|
1263
|
+
|
|
1104
1264
|
def _resolve_download_targets(
|
|
1105
1265
|
destination_hint: str,
|
|
1106
1266
|
*,
|