@qingflow-tech/qingflow-app-user-mcp 1.0.6 → 1.0.7
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/builder_facade/models.py +269 -2
- package/src/qingflow_mcp/builder_facade/service.py +3549 -172
- package/src/qingflow_mcp/cli/commands/builder.py +39 -26
- package/src/qingflow_mcp/cli/commands/record.py +3 -3
- package/src/qingflow_mcp/public_surface.py +2 -5
- package/src/qingflow_mcp/response_trim.py +3 -6
- package/src/qingflow_mcp/server_app_builder.py +33 -20
- package/src/qingflow_mcp/tools/ai_builder_tools.py +395 -117
- package/src/qingflow_mcp/tools/record_tools.py +9 -2
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @qingflow-tech/qingflow-app-user-mcp@1.0.
|
|
6
|
+
npm install @qingflow-tech/qingflow-app-user-mcp@1.0.7
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @qingflow-tech/qingflow-app-user-mcp@1.0.
|
|
12
|
+
npx -y -p @qingflow-tech/qingflow-app-user-mcp@1.0.7 qingflow-app-user-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -115,6 +115,13 @@ class PublicViewButtonType(str, Enum):
|
|
|
115
115
|
class PublicViewButtonConfigType(str, Enum):
|
|
116
116
|
top = "TOP"
|
|
117
117
|
detail = "DETAIL"
|
|
118
|
+
list = "LIST"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class PublicButtonPlacement(str, Enum):
|
|
122
|
+
header = "header"
|
|
123
|
+
detail = "detail"
|
|
124
|
+
list = "list"
|
|
118
125
|
|
|
119
126
|
|
|
120
127
|
class PublicChartType(str, Enum):
|
|
@@ -739,6 +746,8 @@ class FieldPatch(StrictModel):
|
|
|
739
746
|
default=None,
|
|
740
747
|
validation_alias=AliasChoices("custom_button_text", "customButtonText", "custom_btn_text", "customBtnText"),
|
|
741
748
|
)
|
|
749
|
+
as_data_title: bool | None = Field(default=None, validation_alias=AliasChoices("as_data_title", "asDataTitle"))
|
|
750
|
+
as_data_cover: bool | None = Field(default=None, validation_alias=AliasChoices("as_data_cover", "asDataCover"))
|
|
742
751
|
subfields: list["FieldPatch"] = Field(default_factory=list)
|
|
743
752
|
|
|
744
753
|
@model_validator(mode="after")
|
|
@@ -819,6 +828,8 @@ class FieldMutation(StrictModel):
|
|
|
819
828
|
default=None,
|
|
820
829
|
validation_alias=AliasChoices("custom_button_text", "customButtonText", "custom_btn_text", "customBtnText"),
|
|
821
830
|
)
|
|
831
|
+
as_data_title: bool | None = Field(default=None, validation_alias=AliasChoices("as_data_title", "asDataTitle"))
|
|
832
|
+
as_data_cover: bool | None = Field(default=None, validation_alias=AliasChoices("as_data_cover", "asDataCover"))
|
|
822
833
|
subfields: list[FieldPatch] | None = None
|
|
823
834
|
subfield_updates: list["FieldUpdatePatch"] | None = Field(
|
|
824
835
|
default=None,
|
|
@@ -1013,6 +1024,27 @@ class FlowTransitionPatch(StrictModel):
|
|
|
1013
1024
|
target: str = Field(alias="to")
|
|
1014
1025
|
|
|
1015
1026
|
|
|
1027
|
+
class ViewQueryConditionsPatch(StrictModel):
|
|
1028
|
+
enabled: bool = Field(default=True, validation_alias=AliasChoices("enabled", "queryConditionStatus", "status"))
|
|
1029
|
+
exact: bool = Field(default=False, validation_alias=AliasChoices("exact", "queryConditionExact"))
|
|
1030
|
+
hide_before_query: bool = Field(default=False, validation_alias=AliasChoices("hide_before_query", "hideBeforeQuery", "hideBeforeQueryCondition"))
|
|
1031
|
+
rows: list[list[str | int]] = Field(default_factory=list, validation_alias=AliasChoices("rows", "fields", "queryCondition"))
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
class ViewAssociatedResourcesPatch(StrictModel):
|
|
1035
|
+
visible: bool = Field(default=True, validation_alias=AliasChoices("visible", "enabled", "asosChartVisible"))
|
|
1036
|
+
limit_type: str | None = Field(default=None, validation_alias=AliasChoices("limit_type", "limitType"))
|
|
1037
|
+
associated_item_ids: list[Any] = Field(
|
|
1038
|
+
default_factory=list,
|
|
1039
|
+
validation_alias=AliasChoices(
|
|
1040
|
+
"associated_item_ids",
|
|
1041
|
+
"associatedItemIds",
|
|
1042
|
+
"asosChartIdList",
|
|
1043
|
+
"items",
|
|
1044
|
+
),
|
|
1045
|
+
)
|
|
1046
|
+
|
|
1047
|
+
|
|
1016
1048
|
class ViewUpsertPatch(StrictModel):
|
|
1017
1049
|
name: str
|
|
1018
1050
|
view_key: str | None = Field(default=None, validation_alias=AliasChoices("view_key", "viewKey"))
|
|
@@ -1025,6 +1057,17 @@ class ViewUpsertPatch(StrictModel):
|
|
|
1025
1057
|
title_field: str | None = Field(default=None, validation_alias=AliasChoices("title_field", "titleField"))
|
|
1026
1058
|
buttons: list["ViewButtonBindingPatch"] | None = None
|
|
1027
1059
|
visibility: VisibilityPatch | None = None
|
|
1060
|
+
query_conditions: ViewQueryConditionsPatch | None = Field(default=None, validation_alias=AliasChoices("query_conditions", "queryConditions", "query_condition", "queryCondition"))
|
|
1061
|
+
associated_resources: ViewAssociatedResourcesPatch | None = Field(
|
|
1062
|
+
default=None,
|
|
1063
|
+
validation_alias=AliasChoices(
|
|
1064
|
+
"associated_resources",
|
|
1065
|
+
"associatedResources",
|
|
1066
|
+
"associated_reports",
|
|
1067
|
+
"associatedReports",
|
|
1068
|
+
"asosChartConfig",
|
|
1069
|
+
),
|
|
1070
|
+
)
|
|
1028
1071
|
|
|
1029
1072
|
@model_validator(mode="before")
|
|
1030
1073
|
@classmethod
|
|
@@ -1042,6 +1085,20 @@ class ViewUpsertPatch(StrictModel):
|
|
|
1042
1085
|
payload["filters"] = payload.pop("filter_rules")
|
|
1043
1086
|
if "filterRules" in payload and "filters" not in payload:
|
|
1044
1087
|
payload["filters"] = payload.pop("filterRules")
|
|
1088
|
+
if "queryConditions" in payload and "query_conditions" not in payload:
|
|
1089
|
+
payload["query_conditions"] = payload.pop("queryConditions")
|
|
1090
|
+
if "query_condition" in payload and "query_conditions" not in payload:
|
|
1091
|
+
payload["query_conditions"] = payload.pop("query_condition")
|
|
1092
|
+
if "queryCondition" in payload and "query_conditions" not in payload:
|
|
1093
|
+
payload["query_conditions"] = payload.pop("queryCondition")
|
|
1094
|
+
if "associatedResources" in payload and "associated_resources" not in payload:
|
|
1095
|
+
payload["associated_resources"] = payload.pop("associatedResources")
|
|
1096
|
+
if "associated_reports" in payload and "associated_resources" not in payload:
|
|
1097
|
+
payload["associated_resources"] = payload.pop("associated_reports")
|
|
1098
|
+
if "associatedReports" in payload and "associated_resources" not in payload:
|
|
1099
|
+
payload["associated_resources"] = payload.pop("associatedReports")
|
|
1100
|
+
if "asosChartConfig" in payload and "associated_resources" not in payload:
|
|
1101
|
+
payload["associated_resources"] = payload.pop("asosChartConfig")
|
|
1045
1102
|
raw_type = payload.get("type")
|
|
1046
1103
|
if isinstance(raw_type, str):
|
|
1047
1104
|
normalized = raw_type.strip().lower()
|
|
@@ -1128,13 +1185,29 @@ class CustomButtonMatchRulePatch(StrictModel):
|
|
|
1128
1185
|
return payload
|
|
1129
1186
|
|
|
1130
1187
|
|
|
1188
|
+
class CustomButtonFieldMappingPatch(StrictModel):
|
|
1189
|
+
source_field: Any = Field(validation_alias=AliasChoices("source_field", "sourceField", "source"))
|
|
1190
|
+
target_field: Any = Field(validation_alias=AliasChoices("target_field", "targetField", "target"))
|
|
1191
|
+
|
|
1192
|
+
|
|
1131
1193
|
class CustomButtonAddDataConfigPatch(StrictModel):
|
|
1132
|
-
related_app_key: str | None = Field(
|
|
1194
|
+
related_app_key: str | None = Field(
|
|
1195
|
+
default=None,
|
|
1196
|
+
validation_alias=AliasChoices("related_app_key", "relatedAppKey", "target_app_key", "targetAppKey"),
|
|
1197
|
+
)
|
|
1133
1198
|
related_app_name: str | None = Field(default=None, validation_alias=AliasChoices("related_app_name", "relatedAppName"))
|
|
1134
1199
|
que_relation: list[CustomButtonMatchRulePatch] = Field(
|
|
1135
1200
|
default_factory=list,
|
|
1136
1201
|
validation_alias=AliasChoices("que_relation", "queRelation"),
|
|
1137
1202
|
)
|
|
1203
|
+
field_mappings: list[CustomButtonFieldMappingPatch] = Field(
|
|
1204
|
+
default_factory=list,
|
|
1205
|
+
validation_alias=AliasChoices("field_mappings", "fieldMappings", "mappings"),
|
|
1206
|
+
)
|
|
1207
|
+
default_values: dict[str, Any] = Field(
|
|
1208
|
+
default_factory=dict,
|
|
1209
|
+
validation_alias=AliasChoices("default_values", "defaultValues", "defaults"),
|
|
1210
|
+
)
|
|
1138
1211
|
|
|
1139
1212
|
|
|
1140
1213
|
class CustomButtonExternalQRobotConfigPatch(StrictModel):
|
|
@@ -1241,6 +1314,184 @@ class CustomButtonPatch(StrictModel):
|
|
|
1241
1314
|
return self
|
|
1242
1315
|
|
|
1243
1316
|
|
|
1317
|
+
class CustomButtonUpsertPatch(CustomButtonPatch):
|
|
1318
|
+
button_id: int | None = Field(default=None, validation_alias=AliasChoices("button_id", "buttonId", "id"))
|
|
1319
|
+
client_key: str | None = Field(default=None, validation_alias=AliasChoices("client_key", "clientKey"))
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
class CustomButtonRemovePatch(StrictModel):
|
|
1323
|
+
button_id: int | None = Field(default=None, validation_alias=AliasChoices("button_id", "buttonId", "id"))
|
|
1324
|
+
button_text: str | None = Field(default=None, validation_alias=AliasChoices("button_text", "buttonText", "name"))
|
|
1325
|
+
|
|
1326
|
+
@model_validator(mode="after")
|
|
1327
|
+
def validate_selector(self) -> "CustomButtonRemovePatch":
|
|
1328
|
+
if self.button_id is None and not str(self.button_text or "").strip():
|
|
1329
|
+
raise ValueError("remove_buttons[] requires button_id or button_text")
|
|
1330
|
+
return self
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
class CustomButtonViewButtonBindingPatch(StrictModel):
|
|
1334
|
+
button_ref: Any = Field(validation_alias=AliasChoices("button_ref", "buttonRef", "button_id", "buttonId", "id"))
|
|
1335
|
+
placement: PublicButtonPlacement = Field(default=PublicButtonPlacement.detail, validation_alias=AliasChoices("placement", "position"))
|
|
1336
|
+
primary: bool = Field(default=False, validation_alias=AliasChoices("primary", "being_main", "beingMain"))
|
|
1337
|
+
button_limit: list[list[ViewFilterRulePatch]] = Field(
|
|
1338
|
+
default_factory=list,
|
|
1339
|
+
validation_alias=AliasChoices("button_limit", "buttonLimit", "visible_when", "visibleWhen"),
|
|
1340
|
+
)
|
|
1341
|
+
button_formula: str | None = Field(default=None, validation_alias=AliasChoices("button_formula", "buttonFormula"))
|
|
1342
|
+
button_formula_type: int = Field(default=1, validation_alias=AliasChoices("button_formula_type", "buttonFormulaType"))
|
|
1343
|
+
print_tpls: list[Any] = Field(default_factory=list, validation_alias=AliasChoices("print_tpls", "printTpls"))
|
|
1344
|
+
|
|
1345
|
+
@model_validator(mode="before")
|
|
1346
|
+
@classmethod
|
|
1347
|
+
def normalize_aliases(cls, value: Any) -> Any:
|
|
1348
|
+
if not isinstance(value, dict):
|
|
1349
|
+
return value
|
|
1350
|
+
payload = dict(value)
|
|
1351
|
+
raw_placement = payload.get("placement", payload.get("position", payload.get("config_type", payload.get("configType"))))
|
|
1352
|
+
if isinstance(raw_placement, str):
|
|
1353
|
+
normalized = raw_placement.strip().lower()
|
|
1354
|
+
if normalized in {"top", "header"}:
|
|
1355
|
+
payload["placement"] = PublicButtonPlacement.header.value
|
|
1356
|
+
elif normalized in {"detail", "data_detail"}:
|
|
1357
|
+
payload["placement"] = PublicButtonPlacement.detail.value
|
|
1358
|
+
elif normalized in {"list", "row", "row_action"}:
|
|
1359
|
+
payload["placement"] = PublicButtonPlacement.list.value
|
|
1360
|
+
raw_limits = payload.get("button_limit", payload.get("buttonLimit", payload.get("visible_when", payload.get("visibleWhen"))))
|
|
1361
|
+
if isinstance(raw_limits, list) and raw_limits and all(isinstance(item, dict) for item in raw_limits):
|
|
1362
|
+
payload["button_limit"] = [raw_limits]
|
|
1363
|
+
return payload
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
class CustomButtonViewConfigPatch(StrictModel):
|
|
1367
|
+
view_key: str = Field(validation_alias=AliasChoices("view_key", "viewKey", "viewgraphKey", "viewGraphKey"))
|
|
1368
|
+
mode: str = Field(default="merge", validation_alias=AliasChoices("mode", "apply_mode", "applyMode"))
|
|
1369
|
+
buttons: list[CustomButtonViewButtonBindingPatch] = Field(default_factory=list)
|
|
1370
|
+
|
|
1371
|
+
@model_validator(mode="after")
|
|
1372
|
+
def validate_mode(self) -> "CustomButtonViewConfigPatch":
|
|
1373
|
+
normalized = str(self.mode or "").strip().lower()
|
|
1374
|
+
if normalized not in {"merge", "replace"}:
|
|
1375
|
+
raise ValueError("view_configs[].mode must be merge or replace")
|
|
1376
|
+
self.mode = normalized
|
|
1377
|
+
if normalized == "merge" and "buttons" not in getattr(self, "model_fields_set", set()):
|
|
1378
|
+
raise ValueError("view_configs[] in merge mode requires buttons; pass buttons: [] or mode=replace to clear existing bindings")
|
|
1379
|
+
return self
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
class CustomButtonsApplyRequest(StrictModel):
|
|
1383
|
+
app_key: str
|
|
1384
|
+
upsert_buttons: list[CustomButtonUpsertPatch] = Field(default_factory=list)
|
|
1385
|
+
remove_buttons: list[CustomButtonRemovePatch] = Field(default_factory=list)
|
|
1386
|
+
view_configs: list[CustomButtonViewConfigPatch] = Field(default_factory=list)
|
|
1387
|
+
|
|
1388
|
+
@model_validator(mode="before")
|
|
1389
|
+
@classmethod
|
|
1390
|
+
def normalize_aliases(cls, value: Any) -> Any:
|
|
1391
|
+
if not isinstance(value, dict):
|
|
1392
|
+
return value
|
|
1393
|
+
payload = dict(value)
|
|
1394
|
+
if "buttons" in payload and "upsert_buttons" not in payload:
|
|
1395
|
+
payload["upsert_buttons"] = payload.pop("buttons")
|
|
1396
|
+
if "upsertButtons" in payload and "upsert_buttons" not in payload:
|
|
1397
|
+
payload["upsert_buttons"] = payload.pop("upsertButtons")
|
|
1398
|
+
if "removeButtons" in payload and "remove_buttons" not in payload:
|
|
1399
|
+
payload["remove_buttons"] = payload.pop("removeButtons")
|
|
1400
|
+
if "viewConfigs" in payload and "view_configs" not in payload:
|
|
1401
|
+
payload["view_configs"] = payload.pop("viewConfigs")
|
|
1402
|
+
return payload
|
|
1403
|
+
|
|
1404
|
+
@model_validator(mode="after")
|
|
1405
|
+
def validate_shape(self) -> "CustomButtonsApplyRequest":
|
|
1406
|
+
if not self.upsert_buttons and not self.remove_buttons and not self.view_configs:
|
|
1407
|
+
raise ValueError("custom button apply requires at least one upsert, remove, or view config operation")
|
|
1408
|
+
return self
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
class AssociatedResourceUpsertPatch(StrictModel):
|
|
1412
|
+
client_key: str | None = Field(default=None, validation_alias=AliasChoices("client_key", "clientKey"))
|
|
1413
|
+
associated_item_id: int | None = Field(
|
|
1414
|
+
default=None,
|
|
1415
|
+
validation_alias=AliasChoices("associated_item_id", "associatedItemId", "asosChartId", "id"),
|
|
1416
|
+
)
|
|
1417
|
+
graph_type: str = Field(validation_alias=AliasChoices("graph_type", "graphType"))
|
|
1418
|
+
target_app_key: str = Field(validation_alias=AliasChoices("target_app_key", "targetAppKey", "app_key", "appKey"))
|
|
1419
|
+
chart_key: str | None = Field(default=None, validation_alias=AliasChoices("chart_key", "chartKey"))
|
|
1420
|
+
view_key: str | None = Field(default=None, validation_alias=AliasChoices("view_key", "viewKey", "viewgraphKey", "viewGraphKey"))
|
|
1421
|
+
report_source: str | None = Field(default=None, validation_alias=AliasChoices("report_source", "reportSource"))
|
|
1422
|
+
source_type: str | None = Field(default=None, validation_alias=AliasChoices("source_type", "sourceType"))
|
|
1423
|
+
match_rules: list[CustomButtonMatchRulePatch] = Field(default_factory=list, validation_alias=AliasChoices("match_rules", "matchRules"))
|
|
1424
|
+
|
|
1425
|
+
@model_validator(mode="before")
|
|
1426
|
+
@classmethod
|
|
1427
|
+
def normalize_aliases(cls, value: Any) -> Any:
|
|
1428
|
+
if not isinstance(value, dict):
|
|
1429
|
+
return value
|
|
1430
|
+
payload = dict(value)
|
|
1431
|
+
if "chart_id" in payload and "chart_key" not in payload and "chartKey" not in payload:
|
|
1432
|
+
payload["chart_key"] = str(payload.pop("chart_id"))
|
|
1433
|
+
raw_graph_type = str(payload.get("graph_type", payload.get("graphType", "")) or "").strip().lower()
|
|
1434
|
+
raw_source_type = payload.get("source_type", payload.get("sourceType"))
|
|
1435
|
+
has_report_source = "report_source" in payload or "reportSource" in payload
|
|
1436
|
+
if isinstance(raw_source_type, str):
|
|
1437
|
+
normalized_source = raw_source_type.strip().upper()
|
|
1438
|
+
if normalized_source == "BI_QINGFLOW" and not has_report_source:
|
|
1439
|
+
payload["report_source"] = "app"
|
|
1440
|
+
payload.pop("source_type", None)
|
|
1441
|
+
payload.pop("sourceType", None)
|
|
1442
|
+
elif normalized_source == "BI_DATASET" and not has_report_source:
|
|
1443
|
+
payload["report_source"] = "dataset"
|
|
1444
|
+
payload.pop("source_type", None)
|
|
1445
|
+
payload.pop("sourceType", None)
|
|
1446
|
+
elif normalized_source == "QINGFLOW" and raw_graph_type in {"view", "viewgraph"}:
|
|
1447
|
+
payload.pop("source_type", None)
|
|
1448
|
+
payload.pop("sourceType", None)
|
|
1449
|
+
return payload
|
|
1450
|
+
|
|
1451
|
+
|
|
1452
|
+
class AssociatedResourceViewConfigPatch(StrictModel):
|
|
1453
|
+
view_key: str = Field(validation_alias=AliasChoices("view_key", "viewKey", "viewgraphKey", "viewGraphKey"))
|
|
1454
|
+
visible: bool = Field(default=True, validation_alias=AliasChoices("visible", "enabled", "asosChartVisible"))
|
|
1455
|
+
limit_type: str | None = Field(default=None, validation_alias=AliasChoices("limit_type", "limitType"))
|
|
1456
|
+
associated_item_ids: list[Any] = Field(
|
|
1457
|
+
default_factory=list,
|
|
1458
|
+
validation_alias=AliasChoices("associated_item_ids", "associatedItemIds", "asosChartIdList"),
|
|
1459
|
+
)
|
|
1460
|
+
associated_item_refs: list[str] = Field(default_factory=list, validation_alias=AliasChoices("associated_item_refs", "associatedItemRefs", "refs"))
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
class AssociatedResourcesApplyRequest(StrictModel):
|
|
1464
|
+
app_key: str
|
|
1465
|
+
upsert_resources: list[AssociatedResourceUpsertPatch] = Field(default_factory=list)
|
|
1466
|
+
remove_associated_item_ids: list[int] = Field(default_factory=list)
|
|
1467
|
+
reorder_associated_item_ids: list[int] = Field(default_factory=list)
|
|
1468
|
+
view_configs: list[AssociatedResourceViewConfigPatch] = Field(default_factory=list)
|
|
1469
|
+
|
|
1470
|
+
@model_validator(mode="before")
|
|
1471
|
+
@classmethod
|
|
1472
|
+
def normalize_aliases(cls, value: Any) -> Any:
|
|
1473
|
+
if not isinstance(value, dict):
|
|
1474
|
+
return value
|
|
1475
|
+
payload = dict(value)
|
|
1476
|
+
if "upsertResources" in payload and "upsert_resources" not in payload:
|
|
1477
|
+
payload["upsert_resources"] = payload.pop("upsertResources")
|
|
1478
|
+
if "resources" in payload and "upsert_resources" not in payload:
|
|
1479
|
+
payload["upsert_resources"] = payload.pop("resources")
|
|
1480
|
+
if "removeAssociatedItemIds" in payload and "remove_associated_item_ids" not in payload:
|
|
1481
|
+
payload["remove_associated_item_ids"] = payload.pop("removeAssociatedItemIds")
|
|
1482
|
+
if "reorderAssociatedItemIds" in payload and "reorder_associated_item_ids" not in payload:
|
|
1483
|
+
payload["reorder_associated_item_ids"] = payload.pop("reorderAssociatedItemIds")
|
|
1484
|
+
if "viewConfigs" in payload and "view_configs" not in payload:
|
|
1485
|
+
payload["view_configs"] = payload.pop("viewConfigs")
|
|
1486
|
+
return payload
|
|
1487
|
+
|
|
1488
|
+
@model_validator(mode="after")
|
|
1489
|
+
def validate_shape(self) -> "AssociatedResourcesApplyRequest":
|
|
1490
|
+
if not self.upsert_resources and not self.remove_associated_item_ids and not self.reorder_associated_item_ids and not self.view_configs:
|
|
1491
|
+
raise ValueError("associated resources apply requires at least one resource or view config operation")
|
|
1492
|
+
return self
|
|
1493
|
+
|
|
1494
|
+
|
|
1244
1495
|
class ViewButtonBindingPatch(StrictModel):
|
|
1245
1496
|
button_type: PublicViewButtonType = Field(validation_alias=AliasChoices("button_type", "buttonType"))
|
|
1246
1497
|
config_type: PublicViewButtonConfigType = Field(validation_alias=AliasChoices("config_type", "configType"))
|
|
@@ -1278,10 +1529,12 @@ class ViewButtonBindingPatch(StrictModel):
|
|
|
1278
1529
|
raw_config_type = payload.get("config_type", payload.get("configType"))
|
|
1279
1530
|
if isinstance(raw_config_type, str):
|
|
1280
1531
|
normalized_config = raw_config_type.strip().lower()
|
|
1281
|
-
if normalized_config
|
|
1532
|
+
if normalized_config in {"top", "header"}:
|
|
1282
1533
|
payload["config_type"] = "TOP"
|
|
1283
1534
|
elif normalized_config == "detail":
|
|
1284
1535
|
payload["config_type"] = "DETAIL"
|
|
1536
|
+
elif normalized_config in {"list", "row", "row_action"}:
|
|
1537
|
+
payload["config_type"] = "LIST"
|
|
1285
1538
|
raw_limits = payload.get("button_limit", payload.get("buttonLimit"))
|
|
1286
1539
|
if isinstance(raw_limits, list) and raw_limits and all(isinstance(item, dict) for item in raw_limits):
|
|
1287
1540
|
payload["button_limit"] = [raw_limits]
|
|
@@ -1597,15 +1850,25 @@ class AppGetResponse(StrictModel):
|
|
|
1597
1850
|
field_count: int = 0
|
|
1598
1851
|
layout_section_count: int = 0
|
|
1599
1852
|
view_count: int = 0
|
|
1853
|
+
chart_count: int = 0
|
|
1854
|
+
associated_resource_count: int = 0
|
|
1855
|
+
custom_button_count: int = 0
|
|
1600
1856
|
workflow_enabled: bool = False
|
|
1857
|
+
counts: dict[str, int] = Field(default_factory=dict)
|
|
1858
|
+
views: list[dict[str, Any]] = Field(default_factory=list)
|
|
1859
|
+
charts: list[dict[str, Any]] = Field(default_factory=list)
|
|
1860
|
+
associated_resources: list[dict[str, Any]] = Field(default_factory=list)
|
|
1861
|
+
custom_buttons: list[dict[str, Any]] = Field(default_factory=list)
|
|
1601
1862
|
verification_hints: list[str] = Field(default_factory=list)
|
|
1602
1863
|
editability: dict[str, bool | None] = Field(default_factory=dict)
|
|
1864
|
+
form_settings: dict[str, Any] = Field(default_factory=dict)
|
|
1603
1865
|
|
|
1604
1866
|
|
|
1605
1867
|
class AppGetFieldsResponse(StrictModel):
|
|
1606
1868
|
app_key: str
|
|
1607
1869
|
fields: list[dict[str, Any]] = Field(default_factory=list)
|
|
1608
1870
|
field_count: int = 0
|
|
1871
|
+
form_settings: dict[str, Any] = Field(default_factory=dict)
|
|
1609
1872
|
|
|
1610
1873
|
|
|
1611
1874
|
class AppGetLayoutResponse(StrictModel):
|
|
@@ -1681,6 +1944,7 @@ class ViewGetResponse(StrictModel):
|
|
|
1681
1944
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
1682
1945
|
questions: list[dict[str, Any]] = Field(default_factory=list)
|
|
1683
1946
|
associations: list[dict[str, Any]] = Field(default_factory=list)
|
|
1947
|
+
associated_resources_config: dict[str, Any] = Field(default_factory=dict)
|
|
1684
1948
|
|
|
1685
1949
|
|
|
1686
1950
|
class ChartGetResponse(StrictModel):
|
|
@@ -1879,7 +2143,10 @@ def _normalize_public_department_scope_mode(value: Any) -> str | None:
|
|
|
1879
2143
|
|
|
1880
2144
|
|
|
1881
2145
|
CustomButtonMatchRulePatch.model_rebuild()
|
|
2146
|
+
CustomButtonFieldMappingPatch.model_rebuild()
|
|
1882
2147
|
CustomButtonAddDataConfigPatch.model_rebuild()
|
|
2148
|
+
CustomButtonViewButtonBindingPatch.model_rebuild()
|
|
2149
|
+
CustomButtonViewConfigPatch.model_rebuild()
|
|
1883
2150
|
CodeBlockAliasPathPatch.model_rebuild()
|
|
1884
2151
|
ViewButtonBindingPatch.model_rebuild()
|
|
1885
2152
|
ViewUpsertPatch.model_rebuild()
|