flowbase-cli 0.1.16__tar.gz → 0.1.18__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowbase-cli
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Command line client for the FlowBase OpenAPI
5
5
  Author: DeepFlowAI
6
6
  License: Apache-2.0
@@ -76,7 +76,7 @@ flowbase
76
76
  ├── docs list | show | example | operations Offline endpoint catalog
77
77
  ├── guide Offline product and task guide (--format markdown|json)
78
78
  ├── organization employees | departments
79
- ├── apps list | get | create | update | set-enabled | delete
79
+ ├── apps list | get | create | update | set-enabled | delete | navigation
80
80
  │ add-objects | remove-object | set-group | reorder-objects
81
81
  │ add-dashboards | remove-dashboard | set-dashboard-group | reorder-members
82
82
  ├── groups create | reorder | update | delete App groups (under an app)
@@ -88,6 +88,7 @@ flowbase
88
88
  ├── approvals list | get | create | update | reorder | set-enabled | delete
89
89
  ├── pages list | options | get | create | update | set-default | clear-default | delete | restore | evaluate
90
90
  ├── dashboards list | get | create | update | copy | delete | run
91
+ │ record-view-options | record-view-preview | records
91
92
  ├── changes commit | release | direct-release
92
93
  ├── versions list | show | releases Read-only history
93
94
  ├── environments restart Destructive test-env reset
@@ -138,7 +139,8 @@ Most `update` commands replace a **full snapshot** and accept an optional `baseR
138
139
 
139
140
  ```bash
140
141
  flowbase dashboards get dsh_xxx > current.json # authoritative snapshot
141
- # edit current.json: change fields, keep filters/components, use draftRevision as baseRevision
142
+ # Keep only label/description/icon/filters/components; use draftRevision as baseRevision.
143
+ # Edit the desired fields while preserving all other components and filters.
142
144
  flowbase dashboards update dsh_xxx --json-file current.json
143
145
  ```
144
146
 
@@ -186,6 +188,31 @@ flowbase changes release --message "Ship sales dashboard" --yes
186
188
 
187
189
  Dashboard component code runs server-side in a sandbox and returns ECharts config / metric / table / markdown. Components and filters are validated on save; use `flowbase dashboards get <id>` to discover component IDs, then `flowbase dashboards run <dashboard_id> <component_id>` to inspect `ok/output/error/logs` in a read-only draft preview (requires metadata:read and records:read). Visual chart rendering still requires the web UI.
188
190
 
191
+ App sections and record-view components:
192
+
193
+ ```bash
194
+ flowbase apps get app_xxx
195
+ flowbase docs catalogs app-sections
196
+ flowbase apps navigation app_xxx --json '{"type":"appSection.create","name":"Sales"}' --yes
197
+ flowbase groups create app_xxx --name Orders --section-id sec_xxx
198
+ flowbase apps add-objects app_xxx --object-ids obj_xxx --section-id sec_xxx
199
+ # add-dashboards and add-iframes also accept --section-id.
200
+ flowbase apps navigation app_xxx --json '{"type":"appMember.move","id":"obj_xxx","sectionId":"sec_xxx","groupId":"grp_xxx","expectedSectionId":"sec_xxx","expectedGroupId":null}' --yes
201
+
202
+ flowbase docs catalogs dashboard-record-views
203
+ flowbase dashboards record-view-options
204
+ flowbase docs example dashboards.record-view-preview --output preview.json
205
+ # Replace placeholder IDs and configure component/filters before previewing.
206
+ flowbase dashboards record-view-preview dsh_xxx --json-file preview.json
207
+ flowbase dashboards records dsh_xxx dcm_xxx --page 1 --query Orders --json '{"filterValues":{}}'
208
+ ```
209
+
210
+ `apps get` preserves section definitions and group/member `sectionId`. Navigation supports section creation, rename, empty-section deletion, full section ordering, group moves and member moves. Moves require explicit source and target positions; use JSON `null` for unassigned/ungrouped. See `app-sections` for all six request bodies. Navigation requires confirmation (`--yes` for automation), and writes only a draft.
211
+
212
+ Record-view previews and queries require both `metadata:read` and `records:read`, use the current Host's records and draft configuration, and return `mode: draft-preview` plus `draftRevision`. They use API-key visibility rather than an employee's workspace identity; hidden fields stay excluded and hidden filter fields are rejected. Page size is configured on the component (10/20/50). Search is ignored when `showSearch` is false. `dashboards run` is for code components.
213
+
214
+ For `dashboards update`, construct the body from the latest `get`: preserve `label`, `description`, `icon`, `filters`, and **all** `components`; set `baseRevision` to the returned `draftRevision`. Omit response-only fields. Keep existing component IDs and `recordView` unchanged when editing other properties; omit IDs on new components. Omitting `components` or `filters` clears them.
215
+
189
216
  ### 6.3 Production hotfix
190
217
 
191
218
  ```bash
@@ -291,9 +318,10 @@ Transport requests time out after 60 seconds. A lost write response has an unkno
291
318
 
292
319
  ### Recent feature authoring
293
320
 
321
+ - `flowbase docs catalogs field-types`: includes template autonumber configuration and date/time/datetime v2 creation examples. Numbering rules and temporal precision are immutable after creation; legacy numbering and temporal v1 remain supported.
294
322
  - `flowbase docs catalogs planning`: tree/Gantt view snapshots, candidate queries and optimistic plan updates. Read a full view with `views list` before updating; preserve `displayMode`, `parentFieldId` and `gantt`.
295
323
  - `flowbase docs catalogs record-bundles`: initialize, atomically submit and recover a parent/detail submission. Reuse a submission ID only with the identical request body.
296
- - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Derived values are read-only.
324
+ - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Supports reuse of calculated results through single relations and multi-level rollups (up to 10 dependency levels). Validation returns `dependencyGraph`, or `valid=false` with `code`/`errorPath` for invalid dependencies. Pass `fieldId` when validating an existing field. Derived values are read-only.
297
325
  - `flowbase docs catalogs workflow-python`: record creation examples and failed-task retry. `workflows python-runtime OBJECT new` discovers current object bindings; `workflows executions` includes Python attempts, logs and `canRetry`.
298
326
 
299
327
  Use `records list OBJECT --view-id VIEW --view-layout` for tree/Gantt projections; the default remains a flat list. `records update` accepts `updatedAt` and `planViewId` in its JSON body for version-checked plan edits. Formula validation/trials require both metadata read and record read; workflow retry requires both metadata write and record write and explicit CLI confirmation (`--yes` in automation).
@@ -67,7 +67,7 @@ flowbase
67
67
  ├── docs list | show | example | operations Offline endpoint catalog
68
68
  ├── guide Offline product and task guide (--format markdown|json)
69
69
  ├── organization employees | departments
70
- ├── apps list | get | create | update | set-enabled | delete
70
+ ├── apps list | get | create | update | set-enabled | delete | navigation
71
71
  │ add-objects | remove-object | set-group | reorder-objects
72
72
  │ add-dashboards | remove-dashboard | set-dashboard-group | reorder-members
73
73
  ├── groups create | reorder | update | delete App groups (under an app)
@@ -79,6 +79,7 @@ flowbase
79
79
  ├── approvals list | get | create | update | reorder | set-enabled | delete
80
80
  ├── pages list | options | get | create | update | set-default | clear-default | delete | restore | evaluate
81
81
  ├── dashboards list | get | create | update | copy | delete | run
82
+ │ record-view-options | record-view-preview | records
82
83
  ├── changes commit | release | direct-release
83
84
  ├── versions list | show | releases Read-only history
84
85
  ├── environments restart Destructive test-env reset
@@ -129,7 +130,8 @@ Most `update` commands replace a **full snapshot** and accept an optional `baseR
129
130
 
130
131
  ```bash
131
132
  flowbase dashboards get dsh_xxx > current.json # authoritative snapshot
132
- # edit current.json: change fields, keep filters/components, use draftRevision as baseRevision
133
+ # Keep only label/description/icon/filters/components; use draftRevision as baseRevision.
134
+ # Edit the desired fields while preserving all other components and filters.
133
135
  flowbase dashboards update dsh_xxx --json-file current.json
134
136
  ```
135
137
 
@@ -177,6 +179,31 @@ flowbase changes release --message "Ship sales dashboard" --yes
177
179
 
178
180
  Dashboard component code runs server-side in a sandbox and returns ECharts config / metric / table / markdown. Components and filters are validated on save; use `flowbase dashboards get <id>` to discover component IDs, then `flowbase dashboards run <dashboard_id> <component_id>` to inspect `ok/output/error/logs` in a read-only draft preview (requires metadata:read and records:read). Visual chart rendering still requires the web UI.
179
181
 
182
+ App sections and record-view components:
183
+
184
+ ```bash
185
+ flowbase apps get app_xxx
186
+ flowbase docs catalogs app-sections
187
+ flowbase apps navigation app_xxx --json '{"type":"appSection.create","name":"Sales"}' --yes
188
+ flowbase groups create app_xxx --name Orders --section-id sec_xxx
189
+ flowbase apps add-objects app_xxx --object-ids obj_xxx --section-id sec_xxx
190
+ # add-dashboards and add-iframes also accept --section-id.
191
+ flowbase apps navigation app_xxx --json '{"type":"appMember.move","id":"obj_xxx","sectionId":"sec_xxx","groupId":"grp_xxx","expectedSectionId":"sec_xxx","expectedGroupId":null}' --yes
192
+
193
+ flowbase docs catalogs dashboard-record-views
194
+ flowbase dashboards record-view-options
195
+ flowbase docs example dashboards.record-view-preview --output preview.json
196
+ # Replace placeholder IDs and configure component/filters before previewing.
197
+ flowbase dashboards record-view-preview dsh_xxx --json-file preview.json
198
+ flowbase dashboards records dsh_xxx dcm_xxx --page 1 --query Orders --json '{"filterValues":{}}'
199
+ ```
200
+
201
+ `apps get` preserves section definitions and group/member `sectionId`. Navigation supports section creation, rename, empty-section deletion, full section ordering, group moves and member moves. Moves require explicit source and target positions; use JSON `null` for unassigned/ungrouped. See `app-sections` for all six request bodies. Navigation requires confirmation (`--yes` for automation), and writes only a draft.
202
+
203
+ Record-view previews and queries require both `metadata:read` and `records:read`, use the current Host's records and draft configuration, and return `mode: draft-preview` plus `draftRevision`. They use API-key visibility rather than an employee's workspace identity; hidden fields stay excluded and hidden filter fields are rejected. Page size is configured on the component (10/20/50). Search is ignored when `showSearch` is false. `dashboards run` is for code components.
204
+
205
+ For `dashboards update`, construct the body from the latest `get`: preserve `label`, `description`, `icon`, `filters`, and **all** `components`; set `baseRevision` to the returned `draftRevision`. Omit response-only fields. Keep existing component IDs and `recordView` unchanged when editing other properties; omit IDs on new components. Omitting `components` or `filters` clears them.
206
+
180
207
  ### 6.3 Production hotfix
181
208
 
182
209
  ```bash
@@ -282,9 +309,10 @@ Transport requests time out after 60 seconds. A lost write response has an unkno
282
309
 
283
310
  ### Recent feature authoring
284
311
 
312
+ - `flowbase docs catalogs field-types`: includes template autonumber configuration and date/time/datetime v2 creation examples. Numbering rules and temporal precision are immutable after creation; legacy numbering and temporal v1 remain supported.
285
313
  - `flowbase docs catalogs planning`: tree/Gantt view snapshots, candidate queries and optimistic plan updates. Read a full view with `views list` before updating; preserve `displayMode`, `parentFieldId` and `gantt`.
286
314
  - `flowbase docs catalogs record-bundles`: initialize, atomically submit and recover a parent/detail submission. Reuse a submission ID only with the identical request body.
287
- - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Derived values are read-only.
315
+ - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Supports reuse of calculated results through single relations and multi-level rollups (up to 10 dependency levels). Validation returns `dependencyGraph`, or `valid=false` with `code`/`errorPath` for invalid dependencies. Pass `fieldId` when validating an existing field. Derived values are read-only.
288
316
  - `flowbase docs catalogs workflow-python`: record creation examples and failed-task retry. `workflows python-runtime OBJECT new` discovers current object bindings; `workflows executions` includes Python attempts, logs and `canRetry`.
289
317
 
290
318
  Use `records list OBJECT --view-id VIEW --view-layout` for tree/Gantt projections; the default remains a flat list. `records update` accepts `updatedAt` and `planViewId` in its JSON body for version-checked plan edits. Formula validation/trials require both metadata read and record read; workflow retry requires both metadata write and record write and explicit CLI confirmation (`--yes` in automation).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flowbase-cli"
7
- version = "0.1.16"
7
+ version = "0.1.18"
8
8
  description = "Command line client for the FlowBase OpenAPI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,3 +1,3 @@
1
1
  """FlowBase OpenAPI CLI."""
2
2
 
3
- __version__ = "0.1.16"
3
+ __version__ = "0.1.18"
@@ -22,6 +22,10 @@ class Endpoint:
22
22
 
23
23
 
24
24
  ENDPOINTS = (
25
+ Endpoint("apps.navigation", "flowbase_apps_navigation", "POST", "/apps/{app_id}/navigation", "metadata:write", "Edit app sections and navigation positions; read apps get first. See app-sections catalog.", "flowbase apps navigation app_xxx --json-file navigation.json --yes", True, request_body='{"type":"appSection.create","name":"Sales"}'),
26
+ Endpoint("dashboards.record-view-options", "flowbase_dashboards_record_view_options", "GET", "/dashboards/record-view-options", "metadata:read", "Discover draft objects and fields for record-view components.", "flowbase dashboards record-view-options"),
27
+ Endpoint("dashboards.record-view-preview", "flowbase_dashboards_record_view_preview", "POST", "/dashboards/{dashboard_id}/record-view-preview", "metadata:read", "Preview an unsaved record-view component; also requires records:read. No writes; current Host data and draft config.", "flowbase dashboards record-view-preview dsh_xxx --json-file preview.json", request_body='{"component":{"type":"record_view","title":"Orders","layout":{"x":0,"y":0,"w":6,"h":10},"recordView":{"objectId":"obj_xxx","match":"all","filters":[],"fieldIds":["fld_xxx"],"pageSize":10,"showSearch":true,"followFilters":true}},"filters":[],"filterValues":{},"page":1,"q":""}'),
28
+ Endpoint("dashboards.records", "flowbase_dashboards_records", "POST", "/dashboards/{dashboard_id}/components/{component_id}/records", "metadata:read", "Query a saved draft record-view component; also requires records:read. No writes; not employee workspace permissions.", "flowbase dashboards records dsh_xxx dcm_xxx --page 1 --json-file filters.json", request_body='{"filterValues":{},"page":1,"q":""}'),
25
29
  Endpoint("iframes.list", "flowbase_iframes_list", "GET", "/iframes", "metadata:read", "List iframe configuration.", "flowbase iframes list", requires_confirmation=False, request_body=None),
26
30
  Endpoint("iframes.get", "flowbase_iframes_get", "GET", "/iframes/{iframe_id}", "metadata:read", "Get iframe configuration.", "flowbase iframes get", requires_confirmation=False, request_body=None),
27
31
  Endpoint("iframes.create", "flowbase_iframes_create", "POST", "/iframes", "metadata:write", "Create iframe configuration.", "flowbase iframes create", requires_confirmation=False, request_body='{"label": "Help", "url": "https://example.com", "icon": "IconWorld", "color": "#2563EB"}'),
@@ -88,7 +92,7 @@ ENDPOINTS = (
88
92
  "POST",
89
93
  "/apps/{app_id}/groups",
90
94
  "metadata:write",
91
- "Create an app group draft.",
95
+ "Create an app group draft; optional sectionId selects a section (omitted means unassigned).",
92
96
  "flowbase groups create app_xxx --name Sales --icon IconFolder",
93
97
  request_body='{"name":"Sales","icon":"IconFolder"}',
94
98
  ),
@@ -659,7 +663,7 @@ def _field_type(
659
663
  ) -> dict:
660
664
  payload = {
661
665
  "type": type_name,
662
- "typeVersion": "v1",
666
+ "typeVersion": "v2" if type_name in ("date", "time", "datetime") else "v1",
663
667
  "writable": writable,
664
668
  "permissions": list(_PERMISSIONS),
665
669
  "constraints": list(constraints),
@@ -706,8 +710,9 @@ FIELD_TYPES = (
706
710
  }},
707
711
  ),
708
712
  _field_type(
709
- "date", ("minimum", "maximum", "unique", "displayFormat"),
710
- filter_operators=_DATE_FILTERS, record_value="YYYY-MM-DD | null",
713
+ "date", ("precision", "minimum", "maximum", "unique", "displayFormat"),
714
+ filter_operators=_DATE_FILTERS, record_value="YYYY | YYYY-MM | YYYY-MM-DD | null; precision year/month/day is immutable",
715
+ extra={"createExample": {"label": "Month", "key": "month", "description": "Reporting month", "type": "date", "typeVersion": "v2", "permission": "optional", "constraints": {"precision": "month"}}},
711
716
  ),
712
717
  _field_type(
713
718
  "select.single", ("options", "unique", "showColorDot"),
@@ -758,11 +763,13 @@ FIELD_TYPES = (
758
763
  ),
759
764
  _field_type(
760
765
  "time", ("precision", "minimum", "maximum", "unique", "displayFormat"),
761
- filter_operators=_DATE_FILTERS, record_value="HH:MM or HH:MM:SS | null",
766
+ filter_operators=_DATE_FILTERS, record_value="HH | HH:mm | HH:mm:ss | null; precision hour/minute/second is immutable",
767
+ extra={"createExample": {"label": "Hour", "key": "hour", "description": "Scheduled hour", "type": "time", "typeVersion": "v2", "permission": "optional", "constraints": {"precision": "hour"}}},
762
768
  ),
763
769
  _field_type(
764
- "datetime", ("minimum", "maximum", "unique", "displayFormat"),
765
- filter_operators=_DATE_FILTERS, record_value="ISO-8601 datetime | null",
770
+ "datetime", ("precision", "minimum", "maximum", "unique", "displayFormat"),
771
+ filter_operators=_DATE_FILTERS, record_value="UTC YYYY-MM-DDTHH:mm:ssZ | null; precision hour/minute/second, aligned in Asia/Shanghai; no fractional seconds",
772
+ extra={"createExample": {"label": "Occurred at", "key": "occurred_at", "description": "Event timestamp", "type": "datetime", "typeVersion": "v2", "permission": "optional", "constraints": {"precision": "second"}}},
766
773
  ),
767
774
  _field_type(
768
775
  "email", ("maxLength", "placeholder", "unique"),
@@ -786,12 +793,12 @@ FIELD_TYPES = (
786
793
  record_value="Markdown string | null",
787
794
  ),
788
795
  _field_type(
789
- "autonumber", ("prefix", "start", "minDigits"),
796
+ "autonumber", ("template", "start", "reset", "timezone", "prefix", "minDigits"),
790
797
  writable=False, filter_operators=_TEXT_FILTERS, record_value="server-assigned string; omit on write",
791
- extra={"createExample": {
798
+ extra={"ruleChanges": "Numbering rules are immutable after creation. Use template/start/reset/timezone, or legacy prefix/start/minDigits; never mix both forms. Omit the value on record writes.", "createExample": {
792
799
  "label": "Class no", "key": "class_no", "description": "Auto number",
793
800
  "type": "autonumber", "typeVersion": "v1", "permission": "readonly",
794
- "constraints": {"prefix": "CLS", "start": 2023001, "minDigits": 7},
801
+ "constraints": {"template": "CLS{DATE:yyyyMM}{SEQ:3}", "start": 1, "reset": "month", "timezone": "Asia/Shanghai"},
795
802
  }},
796
803
  ),
797
804
  _field_type(
@@ -1389,7 +1396,7 @@ PAGE_RULES = {
1389
1396
  }
1390
1397
 
1391
1398
  RESOURCE_ID_PREFIXES = {
1392
- "app_": "app", "grp_": "app group", "obj_": "object", "fld_": "field",
1399
+ "app_": "app", "grp_": "app group", "sec_": "app section", "obj_": "object", "fld_": "field",
1393
1400
  "viw_": "view", "wfl_": "workflow", "apr_": "approval flow", "pag_": "custom page",
1394
1401
  "reg_": "page region", "cmp_": "page component",
1395
1402
  "dsh_": "dashboard", "dcm_": "dashboard component", "rol_": "role",
@@ -1594,6 +1601,30 @@ FORMS = {
1594
1601
  }
1595
1602
 
1596
1603
  CATALOGS = {
1604
+ "app-sections": {
1605
+ "read": "apps get APP returns sections and sectionId on groups/objects/dashboards/iframes. Null means unassigned; groups define their members' section.",
1606
+ "write": "apps navigation APP --json-file navigation.json --yes writes one atomic draft operation and returns id/draftRevision. Read current locations first; stale moves fail without changes.",
1607
+ "operations": [
1608
+ {"type": "appSection.create", "name": "Sales"},
1609
+ {"type": "appSection.update", "id": "sec_xxx", "name": "Revenue"},
1610
+ {"type": "appSection.delete", "id": "sec_xxx"},
1611
+ {"type": "appSection.reorder", "sectionIds": ["sec_second", "sec_first"]},
1612
+ {"type": "appGroup.moveToSection", "id": "grp_xxx", "sectionId": "sec_target", "expectedSectionId": None},
1613
+ {"type": "appMember.move", "id": "obj_xxx", "sectionId": "sec_target", "groupId": None, "expectedSectionId": None, "expectedGroupId": None},
1614
+ ],
1615
+ "rules": "Names are trimmed, 1-50 characters, case-insensitively unique; Unassigned/未分栏 are reserved. Only empty sections can be deleted. Reorder supplies all section IDs. Moves require explicit source/target fields, using null for unassigned/ungrouped; target group must belong to target section. Member id may be obj_/dsh_/ifr_.",
1616
+ "add": "groups create and apps add-objects/add-dashboards/add-iframes accept --section-id; omit for unassigned. Existing associations are not moved by add; use navigation.",
1617
+ "order": "Use groups reorder or apps reorder-members for order within a location; preserve the complete app-level order and other sections/groups from apps get.",
1618
+ },
1619
+ "dashboard-record-views": {
1620
+ "discover": "dashboards record-view-options returns draft source object and field IDs; dashboards get returns components and draftRevision.",
1621
+ "component": {"type": "record_view", "title": "Orders", "layout": {"x": 0, "y": 0, "w": 6, "h": 10}, "recordView": {"objectId": "obj_xxx", "match": "all", "filters": [], "fieldIds": ["fld_xxx"], "pageSize": 10, "showSearch": True, "followFilters": True}},
1622
+ "update": "dashboards update is a full snapshot: copy label/description/icon/filters/components from get, preserve all components and their IDs (including code/recordView), set baseRevision from draftRevision. Omit response-only id/key/componentCount/appIds/updatedAt/draftRevision. New components omit id; save allocates it. Omitting components or filters clears them.",
1623
+ "query": "dashboards records DASHBOARD COMPONENT [--query TEXT] [--page N] --json '{\"filterValues\":{}}' queries a saved draft component. dashboards record-view-preview DASHBOARD --json-file preview.json uses unsaved component and filters; docs example dashboards.record-view-preview supplies the body.",
1624
+ "permissions": "Queries require metadata:read and records:read and use current Host data with draft config (mode=draft-preview). API-key identity, not employee workspace access; hidden fields are excluded, hidden filter fields rejected. No writes or app association required.",
1625
+ "rules": "pageSize is 10/20/50; fieldIds are ordered stable field IDs. Fixed all/any conditions intersect dashboard filters and search. showSearch=false ignores q; followFilters=false ignores dashboard filters. Conditions use view-filters catalog. No object-view dependency. Code components use dashboards run.",
1626
+ "response": "columns/records/total/page/pageSize/objectId/title/showSearch/filterValues/conditions/match/mode/draftRevision; resolved absolute dates are returned in filterValues. Iterate until total is covered.",
1627
+ },
1597
1628
  "custom-views": {
1598
1629
  "commands": "views list/create/update/set-enabled/delete; create/update accept --json-file.",
1599
1630
  "example": {"baseRevision": 4, "name": "Custom", "enabled": False, "defaultFieldIds": [], "displayMode": "custom", "custom": {"runtimeVersion": "cv1", "source": "import React from 'react'; export default function View(){return <div>Hello</div>}"}},
@@ -1615,6 +1646,7 @@ CATALOGS = {
1615
1646
  "rules": "Copy every visible component and its version. Update/delete rows also require recordId and updatedAt. Relation is injected by the server; omit it from row values. API-key receipts are isolated per key. Conflict: reload, reconcile and use a new submissionId. Max 200 resulting detail rows.",
1616
1647
  },
1617
1648
  "formula-authoring": {
1649
+ "dependencies": "Single relations and collections can reuse formula/rollup results. Maximum dependency depth is 10; cycles are rejected. sources returns depth/dependencyIds; collections includes calculation metadata. validate returns dependencyGraph, or valid=false with code/errorPath. Pass fieldId when validating an existing field.",
1618
1650
  "steps": ["formulas sources OBJECT discovers scalar paths; formulas collections OBJECT discovers stable object/field IDs.", "formulas validate OBJECT --json-file formula.json validates constraints; trial=true uses samples or a saved recordId.", "fields create/update saves metadata. records formula-preview previews runtime values without saving."],
1619
1651
  "rollupExample": {"fieldType": "rollup", "constraints": {"source": {"mode": "reverse", "objectId": "obj_lines", "relationFieldId": "fld_order", "fieldId": "fld_amount"}, "operation": "sum", "resultType": "number", "scale": 2}, "trial": True, "recordId": "rec_order"},
1620
1652
  "collectionExample": {"expression": "sum(lines)", "resultType": "number", "scale": 2, "languageVersion": 2, "collections": {"lines": {"mode": "reverse", "objectId": "obj_lines", "relationFieldId": "fld_order", "fieldId": "fld_amount"}}},
@@ -6,6 +6,8 @@ GUIDE = {
6
6
  "workflow": [
7
7
  "先确认 --host / FLOWBASE_HOST 和 API Key;环境只由 Host 决定。",
8
8
  "flowbase apps list;flowbase objects list:发现已有应用和对象,优先复用,不猜测 ID。",
9
+ "应用分栏先 apps get 和 docs catalogs app-sections;apps navigation --json-file --yes 修改分栏/位置,添加内容和创建分组可指定 --section-id。",
10
+ "仪表盘记录视图先 dashboards record-view-options 和 docs catalogs dashboard-record-views;record-view-preview 预览未保存配置,records 查询已保存草稿,run 仅运行代码组件。",
9
11
  "flowbase objects get <object_id>:读取字段 key、类型、约束和真实选项 ID;关联字段继续读取目标对象。",
10
12
  "flowbase docs catalogs authoring;flowbase docs list;flowbase docs show <endpoint_key>:查请求和更新方式。",
11
13
  "配置页面前读取 pages options、page-components、page-rules、page-buttons;配置流程前读取 workflow-nodes、workflow-branches 或 approval-rules;配置打印模板前读取 print-templates;配置自定义表单前读取 forms。",
@@ -376,6 +376,9 @@ def _payload_from_args(args: argparse.Namespace, direct: dict[str, Any], require
376
376
 
377
377
  def handle_apps(args: argparse.Namespace) -> int:
378
378
  action = args.apps_action
379
+ if action == "navigation":
380
+ body = _payload_from_args(args, {}, ("type",))
381
+ return run_request(args, "apps.navigation", path_params={"app_id": args.app_id}, body=body)
379
382
  if action == "list":
380
383
  return run_request(args, "apps.list")
381
384
  if action == "get":
@@ -409,7 +412,7 @@ def handle_apps(args: argparse.Namespace) -> int:
409
412
  args,
410
413
  "apps.objects.add",
411
414
  path_params={"app_id": args.app_id},
412
- body={"objectIds": ids},
415
+ body={"objectIds": ids, **({"sectionId": args.section_id} if args.section_id is not None else {})},
413
416
  )
414
417
  if action == "remove-object":
415
418
  return run_request(
@@ -446,7 +449,7 @@ def handle_apps(args: argparse.Namespace) -> int:
446
449
  args,
447
450
  "apps.dashboards.add",
448
451
  path_params={"app_id": args.app_id},
449
- body={"dashboardIds": ids},
452
+ body={"dashboardIds": ids, **({"sectionId": args.section_id} if args.section_id is not None else {})},
450
453
  )
451
454
  if action == "remove-dashboard":
452
455
  return run_request(
@@ -475,7 +478,7 @@ def handle_apps(args: argparse.Namespace) -> int:
475
478
  args,
476
479
  "apps.iframes.add",
477
480
  path_params={"app_id": args.app_id},
478
- body={"iframeIds": ids},
481
+ body={"iframeIds": ids, **({"sectionId": args.section_id} if args.section_id is not None else {})},
479
482
  )
480
483
  if action == "remove-iframe":
481
484
  return run_request(
@@ -511,6 +514,14 @@ def handle_apps(args: argparse.Namespace) -> int:
511
514
 
512
515
  def handle_dashboards(args: argparse.Namespace) -> int:
513
516
  action = args.dashboards_action
517
+ if action == "record-view-options":
518
+ return run_request(args, "dashboards.record-view-options")
519
+ if action in {"records", "record-view-preview"}:
520
+ body = _payload_from_args(args, {"q": args.query, "page": args.page}, ("component",) if action == "record-view-preview" else ())
521
+ path = {"dashboard_id": args.dashboard_id}
522
+ if action == "records":
523
+ path["component_id"] = args.component_id
524
+ return run_request(args, f"dashboards.{action}", path_params=path, body=body)
514
525
  if action == "run":
515
526
  return run_request(args, "dashboards.run", path_params={"dashboard_id": args.dashboard_id, "component_id": args.component_id}, body=load_json_payload(args.json, args.json_file))
516
527
  if action == "list":
@@ -596,7 +607,7 @@ def handle_groups(args: argparse.Namespace) -> int:
596
607
  action = args.groups_action
597
608
  path = {"app_id": args.app_id}
598
609
  if action == "create":
599
- body = _payload_from_args(args, {"name": args.name, "icon": args.icon}, ("name",))
610
+ body = _payload_from_args(args, {"name": args.name, "icon": args.icon, "sectionId": args.section_id}, ("name",))
600
611
  return run_request(args, "apps.groups.create", path_params=path, body=body)
601
612
  if action == "reorder":
602
613
  body = _payload_from_args(args, {}, ("groupIds",))
@@ -1136,6 +1147,10 @@ def build_parser() -> argparse.ArgumentParser:
1136
1147
  app_actions.add_parser("list")
1137
1148
  app_get = app_actions.add_parser("get")
1138
1149
  app_get.add_argument("app_id")
1150
+ app_navigation = app_actions.add_parser("navigation", help="Edit sections or move content; see docs catalogs app-sections.")
1151
+ app_navigation.add_argument("app_id")
1152
+ add_json_args(app_navigation, endpoint_key="apps.navigation")
1153
+ add_yes(app_navigation)
1139
1154
  app_create = app_actions.add_parser("create")
1140
1155
  app_create.add_argument("--label")
1141
1156
  app_create.add_argument("--key")
@@ -1162,6 +1177,7 @@ def build_parser() -> argparse.ArgumentParser:
1162
1177
  app_add_objects = app_actions.add_parser("add-objects")
1163
1178
  app_add_objects.add_argument("app_id")
1164
1179
  app_add_objects.add_argument("--object-ids", required=True, help="Comma-separated object IDs.")
1180
+ app_add_objects.add_argument("--section-id", help="Target section; omitted means unassigned.")
1165
1181
  app_remove_object = app_actions.add_parser("remove-object")
1166
1182
  app_remove_object.add_argument("app_id")
1167
1183
  app_remove_object.add_argument("object_id")
@@ -1180,6 +1196,7 @@ def build_parser() -> argparse.ArgumentParser:
1180
1196
  add_json_args(app_reorder_objects, endpoint_key="apps.objects.reorder")
1181
1197
  app_add_dashboards = app_actions.add_parser("add-dashboards")
1182
1198
  app_add_dashboards.add_argument("app_id")
1199
+ app_add_dashboards.add_argument("--section-id", help="Target section; omitted means unassigned.")
1183
1200
  app_add_dashboards.add_argument(
1184
1201
  "dashboard_ids",
1185
1202
  nargs="+",
@@ -1200,6 +1217,7 @@ def build_parser() -> argparse.ArgumentParser:
1200
1217
  )
1201
1218
  app_add_iframes = app_actions.add_parser("add-iframes")
1202
1219
  app_add_iframes.add_argument("app_id")
1220
+ app_add_iframes.add_argument("--section-id", help="Target section; omitted means unassigned.")
1203
1221
  app_add_iframes.add_argument(
1204
1222
  "iframe_ids",
1205
1223
  nargs="+",
@@ -1225,6 +1243,15 @@ def build_parser() -> argparse.ArgumentParser:
1225
1243
 
1226
1244
  dashboards = groups.add_parser("dashboards", help="Manage dashboard metadata.")
1227
1245
  dashboard_actions = dashboards.add_subparsers(dest="dashboards_action", required=True)
1246
+ dashboard_actions.add_parser("record-view-options", help="Discover draft objects and fields for record-view components.")
1247
+ for action in ("records", "record-view-preview"):
1248
+ command = dashboard_actions.add_parser(action, help="Read-only draft record-view query; requires metadata:read and records:read.")
1249
+ command.add_argument("dashboard_id")
1250
+ if action == "records":
1251
+ command.add_argument("component_id")
1252
+ command.add_argument("--query", help="Component search text; ignored when showSearch is false.")
1253
+ command.add_argument("--page", type=int, help="Page number, starting at 1.")
1254
+ add_json_args(command, endpoint_key=f"dashboards.{action}")
1228
1255
  dashboard_run = dashboard_actions.add_parser("run", help="Run a saved draft component; requires metadata:read and records:read.")
1229
1256
  dashboard_run.add_argument("dashboard_id")
1230
1257
  dashboard_run.add_argument("component_id")
@@ -1297,6 +1324,7 @@ def build_parser() -> argparse.ArgumentParser:
1297
1324
  group_create.add_argument("app_id")
1298
1325
  group_create.add_argument("--name")
1299
1326
  group_create.add_argument("--icon")
1327
+ group_create.add_argument("--section-id", help="Target section; omitted means unassigned.")
1300
1328
  add_json_args(group_create, endpoint_key="apps.groups.create")
1301
1329
  group_reorder = group_actions.add_parser("reorder")
1302
1330
  group_reorder.add_argument("app_id")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowbase-cli
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Command line client for the FlowBase OpenAPI
5
5
  Author: DeepFlowAI
6
6
  License: Apache-2.0
@@ -76,7 +76,7 @@ flowbase
76
76
  ├── docs list | show | example | operations Offline endpoint catalog
77
77
  ├── guide Offline product and task guide (--format markdown|json)
78
78
  ├── organization employees | departments
79
- ├── apps list | get | create | update | set-enabled | delete
79
+ ├── apps list | get | create | update | set-enabled | delete | navigation
80
80
  │ add-objects | remove-object | set-group | reorder-objects
81
81
  │ add-dashboards | remove-dashboard | set-dashboard-group | reorder-members
82
82
  ├── groups create | reorder | update | delete App groups (under an app)
@@ -88,6 +88,7 @@ flowbase
88
88
  ├── approvals list | get | create | update | reorder | set-enabled | delete
89
89
  ├── pages list | options | get | create | update | set-default | clear-default | delete | restore | evaluate
90
90
  ├── dashboards list | get | create | update | copy | delete | run
91
+ │ record-view-options | record-view-preview | records
91
92
  ├── changes commit | release | direct-release
92
93
  ├── versions list | show | releases Read-only history
93
94
  ├── environments restart Destructive test-env reset
@@ -138,7 +139,8 @@ Most `update` commands replace a **full snapshot** and accept an optional `baseR
138
139
 
139
140
  ```bash
140
141
  flowbase dashboards get dsh_xxx > current.json # authoritative snapshot
141
- # edit current.json: change fields, keep filters/components, use draftRevision as baseRevision
142
+ # Keep only label/description/icon/filters/components; use draftRevision as baseRevision.
143
+ # Edit the desired fields while preserving all other components and filters.
142
144
  flowbase dashboards update dsh_xxx --json-file current.json
143
145
  ```
144
146
 
@@ -186,6 +188,31 @@ flowbase changes release --message "Ship sales dashboard" --yes
186
188
 
187
189
  Dashboard component code runs server-side in a sandbox and returns ECharts config / metric / table / markdown. Components and filters are validated on save; use `flowbase dashboards get <id>` to discover component IDs, then `flowbase dashboards run <dashboard_id> <component_id>` to inspect `ok/output/error/logs` in a read-only draft preview (requires metadata:read and records:read). Visual chart rendering still requires the web UI.
188
190
 
191
+ App sections and record-view components:
192
+
193
+ ```bash
194
+ flowbase apps get app_xxx
195
+ flowbase docs catalogs app-sections
196
+ flowbase apps navigation app_xxx --json '{"type":"appSection.create","name":"Sales"}' --yes
197
+ flowbase groups create app_xxx --name Orders --section-id sec_xxx
198
+ flowbase apps add-objects app_xxx --object-ids obj_xxx --section-id sec_xxx
199
+ # add-dashboards and add-iframes also accept --section-id.
200
+ flowbase apps navigation app_xxx --json '{"type":"appMember.move","id":"obj_xxx","sectionId":"sec_xxx","groupId":"grp_xxx","expectedSectionId":"sec_xxx","expectedGroupId":null}' --yes
201
+
202
+ flowbase docs catalogs dashboard-record-views
203
+ flowbase dashboards record-view-options
204
+ flowbase docs example dashboards.record-view-preview --output preview.json
205
+ # Replace placeholder IDs and configure component/filters before previewing.
206
+ flowbase dashboards record-view-preview dsh_xxx --json-file preview.json
207
+ flowbase dashboards records dsh_xxx dcm_xxx --page 1 --query Orders --json '{"filterValues":{}}'
208
+ ```
209
+
210
+ `apps get` preserves section definitions and group/member `sectionId`. Navigation supports section creation, rename, empty-section deletion, full section ordering, group moves and member moves. Moves require explicit source and target positions; use JSON `null` for unassigned/ungrouped. See `app-sections` for all six request bodies. Navigation requires confirmation (`--yes` for automation), and writes only a draft.
211
+
212
+ Record-view previews and queries require both `metadata:read` and `records:read`, use the current Host's records and draft configuration, and return `mode: draft-preview` plus `draftRevision`. They use API-key visibility rather than an employee's workspace identity; hidden fields stay excluded and hidden filter fields are rejected. Page size is configured on the component (10/20/50). Search is ignored when `showSearch` is false. `dashboards run` is for code components.
213
+
214
+ For `dashboards update`, construct the body from the latest `get`: preserve `label`, `description`, `icon`, `filters`, and **all** `components`; set `baseRevision` to the returned `draftRevision`. Omit response-only fields. Keep existing component IDs and `recordView` unchanged when editing other properties; omit IDs on new components. Omitting `components` or `filters` clears them.
215
+
189
216
  ### 6.3 Production hotfix
190
217
 
191
218
  ```bash
@@ -291,9 +318,10 @@ Transport requests time out after 60 seconds. A lost write response has an unkno
291
318
 
292
319
  ### Recent feature authoring
293
320
 
321
+ - `flowbase docs catalogs field-types`: includes template autonumber configuration and date/time/datetime v2 creation examples. Numbering rules and temporal precision are immutable after creation; legacy numbering and temporal v1 remain supported.
294
322
  - `flowbase docs catalogs planning`: tree/Gantt view snapshots, candidate queries and optimistic plan updates. Read a full view with `views list` before updating; preserve `displayMode`, `parentFieldId` and `gantt`.
295
323
  - `flowbase docs catalogs record-bundles`: initialize, atomically submit and recover a parent/detail submission. Reuse a submission ID only with the identical request body.
296
- - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Derived values are read-only.
324
+ - `flowbase docs catalogs formula-authoring`: formula/rollup sources, validation, saved-record trials and runtime draft preview. Supports reuse of calculated results through single relations and multi-level rollups (up to 10 dependency levels). Validation returns `dependencyGraph`, or `valid=false` with `code`/`errorPath` for invalid dependencies. Pass `fieldId` when validating an existing field. Derived values are read-only.
297
325
  - `flowbase docs catalogs workflow-python`: record creation examples and failed-task retry. `workflows python-runtime OBJECT new` discovers current object bindings; `workflows executions` includes Python attempts, logs and `canRetry`.
298
326
 
299
327
  Use `records list OBJECT --view-id VIEW --view-layout` for tree/Gantt projections; the default remains a flat list. `records update` accepts `updatedAt` and `planViewId` in its JSON body for version-checked plan edits. Formula validation/trials require both metadata read and record read; workflow retry requires both metadata write and record write and explicit CLI confirmation (`--yes` in automation).
File without changes