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.
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/PKG-INFO +32 -4
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/README.md +31 -3
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/pyproject.toml +1 -1
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli/__init__.py +1 -1
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli/endpoints.py +43 -11
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli/guide.py +2 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli/main.py +32 -4
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli.egg-info/PKG-INFO +32 -4
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/setup.cfg +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli.egg-info/SOURCES.txt +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli.egg-info/dependency_links.txt +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli.egg-info/entry_points.txt +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/src/flowbase_cli.egg-info/top_level.txt +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/tests/test_autonomy.py +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/tests/test_cli.py +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/tests/test_iframes.py +0 -0
- {flowbase_cli-0.1.16 → flowbase_cli-0.1.18}/tests/test_recent_commands.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowbase-cli
|
|
3
|
-
Version: 0.1.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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).
|
|
@@ -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:
|
|
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="
|
|
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", ("
|
|
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": {"
|
|
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.
|
|
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
|
-
#
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|