@carthooks/arcubase-cli 0.1.22 → 0.1.24
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/bundle/arcubase-admin.mjs +158 -2
- package/bundle/arcubase.mjs +158 -2
- package/dist/generated/command_registry.generated.d.ts +15 -0
- package/dist/generated/command_registry.generated.d.ts.map +1 -1
- package/dist/generated/command_registry.generated.js +21 -0
- package/dist/generated/help_examples.generated.d.ts +53 -0
- package/dist/generated/help_examples.generated.d.ts.map +1 -1
- package/dist/generated/help_examples.generated.js +89 -0
- package/dist/runtime/execute.d.ts.map +1 -1
- package/dist/runtime/execute.js +46 -0
- package/package.json +3 -3
- package/sdk-dist/docs/runtime-reference/dashboard.md +16 -1
- package/sdk-dist/docs/runtime-reference/help-examples/admin/dashboard/update-options.json +23 -0
- package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/preview-data.json +24 -0
- package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/update-ingress-options.json +21 -0
- package/sdk-dist/docs/runtime-reference/widgets.md +24 -0
- package/sdk-dist/generated/command_registry.generated.ts +21 -0
- package/sdk-dist/generated/help_examples.generated.ts +89 -0
- package/src/generated/command_registry.generated.ts +21 -0
- package/src/generated/help_examples.generated.ts +89 -0
- package/src/runtime/execute.ts +46 -0
- package/src/tests/command_registry.test.ts +2 -1
- package/src/tests/execute_validation.test.ts +97 -0
- package/src/tests/help.test.ts +27 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAShJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAe1D;AAaD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AA8BD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAUlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA8HpI;
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAShJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAe1D;AAaD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AA8BD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAUlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA8HpI;AAquED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAyOrI"}
|
package/dist/runtime/execute.js
CHANGED
|
@@ -948,15 +948,37 @@ function buildBodyGuidance(requestType) {
|
|
|
948
948
|
dataSourceType: 'entity',
|
|
949
949
|
dimensions: [{ IsField: true, FieldID: 1004, Name: 'Source' }],
|
|
950
950
|
measures: [{ FieldID: 1005, Aggregate: 'sum', Name: 'Total Amount' }],
|
|
951
|
+
conditions: { mode: 'and', conditions: [{ column: ':1006', operator: '$eq', value: 'yes' }] },
|
|
951
952
|
},
|
|
952
953
|
commonMistakes: [
|
|
953
954
|
'widget preview-data body is the chart query itself',
|
|
954
955
|
'do not send a saved widget object with id, entity_id, or options',
|
|
955
956
|
'field dimensions with FieldID must set IsField:true',
|
|
957
|
+
'use conditions, not filters, for chart data filtering',
|
|
958
|
+
'do not retry without conditions and then hand-calculate filtered statistics',
|
|
956
959
|
'unsupported aggregates are invalid; use sum, avg, max, min, count, or distinct_count',
|
|
957
960
|
],
|
|
958
961
|
suggestions: [
|
|
959
962
|
'retry with: arcubase-admin widget preview-data --app-id <app_id> --body-json \'{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}]}\'',
|
|
963
|
+
'conditional stats: arcubase-admin widget preview-data --app-id <app_id> --body-json \'{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<source_field_id>,"Name":"Source"}],"conditions":{"mode":"and","conditions":[{"column":":1006","operator":"$eq","value":"yes"}]},"measures":[{"FieldID":<customer_field_id>,"Aggregate":"distinct_count","Name":"Distinct Customers"}]}\'',
|
|
964
|
+
],
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
if (requestType === 'AppNewWidgetsReqVO') {
|
|
968
|
+
return {
|
|
969
|
+
shapeHint: {
|
|
970
|
+
type: 'list',
|
|
971
|
+
options: { ingress_id: 2188893001 },
|
|
972
|
+
},
|
|
973
|
+
commonMistakes: [
|
|
974
|
+
'dashboard widgets use options.dashboard_id',
|
|
975
|
+
'ingress widgets use options.ingress_id',
|
|
976
|
+
'do not put entity_id at body top level or under options when creating a widget',
|
|
977
|
+
'after creating an ingress widget, use widget update-ingress-options to adjust display configuration',
|
|
978
|
+
],
|
|
979
|
+
suggestions: [
|
|
980
|
+
'dashboard chart: arcubase-admin widget create --app-id <app_id> --body-json \'{"type":"chart","options":{"dashboard_id":<dashboard_id>}}\'',
|
|
981
|
+
'ingress list: arcubase-admin widget create --app-id <app_id> --body-json \'{"type":"list","options":{"ingress_id":<ingress_id>}}\'',
|
|
960
982
|
],
|
|
961
983
|
};
|
|
962
984
|
}
|
|
@@ -969,15 +991,39 @@ function buildBodyGuidance(requestType) {
|
|
|
969
991
|
entity_id: 2188891001,
|
|
970
992
|
dimensions: [{ IsField: true, FieldID: 1004, Name: 'Source' }],
|
|
971
993
|
measures: [{ FieldID: 1005, Aggregate: 'sum', Name: 'Total Amount' }],
|
|
994
|
+
conditions: { mode: 'and', conditions: [{ column: ':1006', operator: '$eq', value: 'yes' }] },
|
|
972
995
|
type: 'bar',
|
|
973
996
|
},
|
|
974
997
|
},
|
|
975
998
|
},
|
|
976
999
|
commonMistakes: [
|
|
977
1000
|
'dashboard chart config belongs in body.options.charts',
|
|
1001
|
+
'ingress/list display settings use widget update-ingress-options, not widget update',
|
|
1002
|
+
'do not put ingress_id, list, default_cols, page_size, or entry display settings in widget update',
|
|
978
1003
|
'field dimensions with FieldID must set IsField:true',
|
|
1004
|
+
'use options.charts.conditions, not filters, for chart data filtering',
|
|
1005
|
+
'do not retry without conditions and then hand-calculate filtered statistics',
|
|
979
1006
|
'verify persistence with widget get or widget list after update',
|
|
980
1007
|
],
|
|
1008
|
+
suggestions: [
|
|
1009
|
+
'dashboard chart: arcubase-admin widget update --app-id <app_id> --widget-id <widget_id> --body-json \'{"entity_id":<table_id>,"options":{"charts":{"entity_id":<table_id>,"dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}],"type":"bar"}}}\'',
|
|
1010
|
+
'ingress list display: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json \'{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}\'',
|
|
1011
|
+
],
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
if (requestType === 'AppUpdateWidgetsIngressOptionsReqVO') {
|
|
1015
|
+
return {
|
|
1016
|
+
shapeHint: {
|
|
1017
|
+
options: { cond_follow: true, cond_follow_tab: true, cond_follow_cols: [':1001', ':1002'] },
|
|
1018
|
+
},
|
|
1019
|
+
commonMistakes: [
|
|
1020
|
+
'widget update-ingress-options is for ingress widgets, not dashboard chart widgets',
|
|
1021
|
+
'put display settings under body.options',
|
|
1022
|
+
'verify the ingress widget with widget get after update',
|
|
1023
|
+
],
|
|
1024
|
+
suggestions: [
|
|
1025
|
+
'retry with: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json \'{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}\'',
|
|
1026
|
+
],
|
|
981
1027
|
};
|
|
982
1028
|
}
|
|
983
1029
|
return {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carthooks/arcubase-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "Arcubase runtime CLI for admin and user command execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
".": "./dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"arcubase-admin": "
|
|
13
|
-
"arcubase": "
|
|
12
|
+
"arcubase-admin": "dist/bin/arcubase-admin.js",
|
|
13
|
+
"arcubase": "dist/bin/arcubase.js"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
# Dashboard
|
|
2
2
|
|
|
3
|
-
Use `arcubase
|
|
3
|
+
Use `arcubase app get`, `arcubase dashboard get`, and `arcubase dashboard widgets` to read dashboards as a tenant user.
|
|
4
|
+
|
|
5
|
+
User dashboard discovery:
|
|
6
|
+
|
|
7
|
+
- `arcubase entry` lists the current user's visible apps and tables.
|
|
8
|
+
- `arcubase app get --app-id <app_id>` returns app detail, including dashboards visible to the current user.
|
|
9
|
+
- To find a dashboard by name, run `app get` for candidate apps from `entry`, match `Dashboard[].Name`, then use that app id and dashboard id with `dashboard get`, `dashboard widgets`, and `widget data`.
|
|
10
|
+
- Do not use admin dashboard commands to prove a normal user's dashboard visibility.
|
|
4
11
|
|
|
5
12
|
Use `arcubase-admin dashboard list`, `arcubase-admin dashboard create`, `arcubase-admin dashboard get-options`, `arcubase-admin dashboard update-options`, `arcubase-admin dashboard update-layout`, and `arcubase-admin dashboard rename` to manage dashboards as an admin.
|
|
6
13
|
|
|
14
|
+
Dashboard visibility:
|
|
15
|
+
|
|
16
|
+
- A dashboard is user-visible only when its options include a matching user scope.
|
|
17
|
+
- After `dashboard create`, call `dashboard update-options` with `{"changed":["users"],"users":[{"type":"user","id":<arcubaseUserId>}]}`
|
|
18
|
+
for the current or target Arcubase user.
|
|
19
|
+
- For the current BotWorks human speaker, use `currentSpeaker.arcubaseUserId`; do not call organization lookup only to resolve yourself.
|
|
20
|
+
- Before claiming a normal user can see a dashboard, run user-side `arcubase app get --app-id <app_id>` and require `dashboards[]` to include that dashboard.
|
|
21
|
+
|
|
7
22
|
Dashboard title updates use body `{"name":"..."}`.
|
|
8
23
|
|
|
9
24
|
Dashboard layout updates use a top-level JSON array of layout positions, not an object wrapper. Example:
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scope": "admin",
|
|
3
|
+
"command": ["dashboard", "update-options"],
|
|
4
|
+
"examples": [
|
|
5
|
+
{
|
|
6
|
+
"title": "make a dashboard visible to one Arcubase user",
|
|
7
|
+
"body": {
|
|
8
|
+
"changed": ["users"],
|
|
9
|
+
"users": [
|
|
10
|
+
{
|
|
11
|
+
"type": "user",
|
|
12
|
+
"id": 2188889901
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"notes": [
|
|
17
|
+
"dashboard visibility is controlled by DashboardUpdateOptionsReqVO.users",
|
|
18
|
+
"use the currentSpeaker.arcubaseUserId value for the current human speaker",
|
|
19
|
+
"after updating, verify from the user side with arcubase app get and require dashboards to include the dashboard"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -37,6 +37,30 @@
|
|
|
37
37
|
"supported Aggregate values are sum, avg, max, min, count, and distinct_count",
|
|
38
38
|
"unsupported aggregate names fail local body validation before the request is sent"
|
|
39
39
|
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"title": "preview filtered distinct_count grouped by source",
|
|
43
|
+
"body": {
|
|
44
|
+
"dataSource": 2188891001,
|
|
45
|
+
"dataSourceType": "entity",
|
|
46
|
+
"dimensions": [
|
|
47
|
+
{"IsField": true, "FieldID": 1004, "Name": "Source"}
|
|
48
|
+
],
|
|
49
|
+
"conditions": {
|
|
50
|
+
"mode": "and",
|
|
51
|
+
"conditions": [
|
|
52
|
+
{"column": ":1006", "operator": "$eq", "value": "yes"}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"measures": [
|
|
56
|
+
{"FieldID": 1002, "Aggregate": "distinct_count", "Name": "Distinct Customers"}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"notes": [
|
|
60
|
+
"use conditions, not filters, for chart data filtering",
|
|
61
|
+
"for saved charts put the same condition set under options.charts.conditions",
|
|
62
|
+
"do not remove the condition and hand-calculate filtered statistics from row query results"
|
|
63
|
+
]
|
|
40
64
|
}
|
|
41
65
|
]
|
|
42
66
|
}
|
package/sdk-dist/docs/runtime-reference/help-examples/admin/widget/update-ingress-options.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scope": "admin",
|
|
3
|
+
"command": ["widget", "update-ingress-options"],
|
|
4
|
+
"examples": [
|
|
5
|
+
{
|
|
6
|
+
"title": "adjust an ingress list widget display configuration",
|
|
7
|
+
"body": {
|
|
8
|
+
"options": {
|
|
9
|
+
"cond_follow": true,
|
|
10
|
+
"cond_follow_tab": true,
|
|
11
|
+
"cond_follow_cols": [":1001", ":1002"]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"notes": [
|
|
15
|
+
"use this only for widgets created with options.ingress_id",
|
|
16
|
+
"do not use dashboard update-layout for ingress widgets",
|
|
17
|
+
"verify with widget get after updating ingress options"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -8,6 +8,14 @@ Use `arcubase widget data --app-id <app_id> --body-json '<FetchWidgetsDataReqVO>
|
|
|
8
8
|
|
|
9
9
|
Create dashboard widgets with `{"type":"chart","options":{"dashboard_id":<dashboard_id>}}`. Do not set `options.type` by hand; the backend derives dashboard versus ingress widget type from `dashboard_id` or `ingress_id`.
|
|
10
10
|
|
|
11
|
+
Create ingress list widgets with `{"type":"list","options":{"ingress_id":<ingress_id>}}`, where `ingress_id` is the entry/access-rule id. Do not put `entity_id` at the top level or under `options` when creating a widget. After creation, adjust entry list display settings with `widget update-ingress-options`, then verify with `widget get`. Ingress widgets have `dashboard_id:0` and must not be placed with `dashboard update-layout`.
|
|
12
|
+
|
|
13
|
+
If ingress/list display settings such as `ingress_id`, `list`, `default_cols`, or `page_size` are rejected by `widget update`, switch to `widget update-ingress-options`; do not retry `widget update` with empty options.
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}
|
|
17
|
+
```
|
|
18
|
+
|
|
11
19
|
Most widget commands use `--widget-id`; `widget preview-data` is the exception. Preview data does not read a saved widget by id and does not accept `--widget-id`, `widget_id`, or `id`. Its body is the chart query itself:
|
|
12
20
|
|
|
13
21
|
```json
|
|
@@ -20,6 +28,22 @@ Fastfail rule: `widget preview-data` accepts only the chart query body. If valid
|
|
|
20
28
|
|
|
21
29
|
After `widget update`, verify persistence with `widget get` or `widget list`. The saved widget must contain non-null `options.charts`; an update response alone is not enough evidence that the chart configuration was persisted.
|
|
22
30
|
|
|
31
|
+
## Chart conditions
|
|
32
|
+
|
|
33
|
+
Use `conditions`, not `filters`, to filter dashboard chart statistics. The condition set shape is:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{"mode":"and","conditions":[{"column":":1006","operator":"$eq","value":"yes"}]}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For saved widgets, place this under `options.charts.conditions`. For `widget preview-data`, place it at top level beside `dataSource`, `dimensions`, and `measures`.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{"dataSource":2188891001,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":1004,"Name":"Source"}],"conditions":{"mode":"and","conditions":[{"column":":1006","operator":"$eq","value":"yes"}]},"measures":[{"FieldID":1002,"Aggregate":"distinct_count","Name":"Distinct Customers"}]}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Fastfail rule: if a chart statistic requires filtering and validation rejects a guessed key such as `filters`, retry with `conditions`. Do not remove the filter and then hand-calculate filtered statistics from row data.
|
|
46
|
+
|
|
23
47
|
## Chart measures
|
|
24
48
|
|
|
25
49
|
Dashboard chart widgets use `ChartOption.measures[]` to define statistics. Supported `Aggregate` values are:
|
|
@@ -953,6 +953,27 @@ export const userCommands = [
|
|
|
953
953
|
],
|
|
954
954
|
"responseType": "GlobalActionEntryRespVO"
|
|
955
955
|
},
|
|
956
|
+
{
|
|
957
|
+
"scope": "user",
|
|
958
|
+
"module": "app",
|
|
959
|
+
"functionName": "getAppDetail",
|
|
960
|
+
"commandPath": [
|
|
961
|
+
"app",
|
|
962
|
+
"get"
|
|
963
|
+
],
|
|
964
|
+
"method": "GET",
|
|
965
|
+
"endpoint": "/api/apps/:id",
|
|
966
|
+
"pathParams": [
|
|
967
|
+
{
|
|
968
|
+
"param": "id",
|
|
969
|
+
"flag": "app-id"
|
|
970
|
+
}
|
|
971
|
+
],
|
|
972
|
+
"controller": "UserAction.AppDetail",
|
|
973
|
+
"requestType": null,
|
|
974
|
+
"queryParams": [],
|
|
975
|
+
"responseType": "AppDetailRespVO"
|
|
976
|
+
},
|
|
956
977
|
{
|
|
957
978
|
"scope": "user",
|
|
958
979
|
"module": "dashboard",
|
|
@@ -370,6 +370,33 @@ export const helpExamplesIndex = {
|
|
|
370
370
|
}
|
|
371
371
|
]
|
|
372
372
|
},
|
|
373
|
+
"admin.dashboard.update-options": {
|
|
374
|
+
"command": [
|
|
375
|
+
"dashboard",
|
|
376
|
+
"update-options"
|
|
377
|
+
],
|
|
378
|
+
"examples": [
|
|
379
|
+
{
|
|
380
|
+
"title": "make a dashboard visible to one Arcubase user",
|
|
381
|
+
"body": {
|
|
382
|
+
"changed": [
|
|
383
|
+
"users"
|
|
384
|
+
],
|
|
385
|
+
"users": [
|
|
386
|
+
{
|
|
387
|
+
"type": "user",
|
|
388
|
+
"id": 2188889901
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
"notes": [
|
|
393
|
+
"dashboard visibility is controlled by DashboardUpdateOptionsReqVO.users",
|
|
394
|
+
"use the currentSpeaker.arcubaseUserId value for the current human speaker",
|
|
395
|
+
"after updating, verify from the user side with arcubase app get and require dashboards to include the dashboard"
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
},
|
|
373
400
|
"admin.widget.create": {
|
|
374
401
|
"command": [
|
|
375
402
|
"widget",
|
|
@@ -465,6 +492,68 @@ export const helpExamplesIndex = {
|
|
|
465
492
|
"supported Aggregate values are sum, avg, max, min, count, and distinct_count",
|
|
466
493
|
"unsupported aggregate names fail local body validation before the request is sent"
|
|
467
494
|
]
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"title": "preview filtered distinct_count grouped by source",
|
|
498
|
+
"body": {
|
|
499
|
+
"dataSource": 2188891001,
|
|
500
|
+
"dataSourceType": "entity",
|
|
501
|
+
"dimensions": [
|
|
502
|
+
{
|
|
503
|
+
"IsField": true,
|
|
504
|
+
"FieldID": 1004,
|
|
505
|
+
"Name": "Source"
|
|
506
|
+
}
|
|
507
|
+
],
|
|
508
|
+
"conditions": {
|
|
509
|
+
"mode": "and",
|
|
510
|
+
"conditions": [
|
|
511
|
+
{
|
|
512
|
+
"column": ":1006",
|
|
513
|
+
"operator": "$eq",
|
|
514
|
+
"value": "yes"
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
"measures": [
|
|
519
|
+
{
|
|
520
|
+
"FieldID": 1002,
|
|
521
|
+
"Aggregate": "distinct_count",
|
|
522
|
+
"Name": "Distinct Customers"
|
|
523
|
+
}
|
|
524
|
+
]
|
|
525
|
+
},
|
|
526
|
+
"notes": [
|
|
527
|
+
"use conditions, not filters, for chart data filtering",
|
|
528
|
+
"for saved charts put the same condition set under options.charts.conditions",
|
|
529
|
+
"do not remove the condition and hand-calculate filtered statistics from row query results"
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
},
|
|
534
|
+
"admin.widget.update-ingress-options": {
|
|
535
|
+
"command": [
|
|
536
|
+
"widget",
|
|
537
|
+
"update-ingress-options"
|
|
538
|
+
],
|
|
539
|
+
"examples": [
|
|
540
|
+
{
|
|
541
|
+
"title": "adjust an ingress list widget display configuration",
|
|
542
|
+
"body": {
|
|
543
|
+
"options": {
|
|
544
|
+
"cond_follow": true,
|
|
545
|
+
"cond_follow_tab": true,
|
|
546
|
+
"cond_follow_cols": [
|
|
547
|
+
":1001",
|
|
548
|
+
":1002"
|
|
549
|
+
]
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
"notes": [
|
|
553
|
+
"use this only for widgets created with options.ingress_id",
|
|
554
|
+
"do not use dashboard update-layout for ingress widgets",
|
|
555
|
+
"verify with widget get after updating ingress options"
|
|
556
|
+
]
|
|
468
557
|
}
|
|
469
558
|
]
|
|
470
559
|
},
|
|
@@ -953,6 +953,27 @@ export const userCommands = [
|
|
|
953
953
|
],
|
|
954
954
|
"responseType": "GlobalActionEntryRespVO"
|
|
955
955
|
},
|
|
956
|
+
{
|
|
957
|
+
"scope": "user",
|
|
958
|
+
"module": "app",
|
|
959
|
+
"functionName": "getAppDetail",
|
|
960
|
+
"commandPath": [
|
|
961
|
+
"app",
|
|
962
|
+
"get"
|
|
963
|
+
],
|
|
964
|
+
"method": "GET",
|
|
965
|
+
"endpoint": "/api/apps/:id",
|
|
966
|
+
"pathParams": [
|
|
967
|
+
{
|
|
968
|
+
"param": "id",
|
|
969
|
+
"flag": "app-id"
|
|
970
|
+
}
|
|
971
|
+
],
|
|
972
|
+
"controller": "UserAction.AppDetail",
|
|
973
|
+
"requestType": null,
|
|
974
|
+
"queryParams": [],
|
|
975
|
+
"responseType": "AppDetailRespVO"
|
|
976
|
+
},
|
|
956
977
|
{
|
|
957
978
|
"scope": "user",
|
|
958
979
|
"module": "dashboard",
|
|
@@ -370,6 +370,33 @@ export const helpExamplesIndex = {
|
|
|
370
370
|
}
|
|
371
371
|
]
|
|
372
372
|
},
|
|
373
|
+
"admin.dashboard.update-options": {
|
|
374
|
+
"command": [
|
|
375
|
+
"dashboard",
|
|
376
|
+
"update-options"
|
|
377
|
+
],
|
|
378
|
+
"examples": [
|
|
379
|
+
{
|
|
380
|
+
"title": "make a dashboard visible to one Arcubase user",
|
|
381
|
+
"body": {
|
|
382
|
+
"changed": [
|
|
383
|
+
"users"
|
|
384
|
+
],
|
|
385
|
+
"users": [
|
|
386
|
+
{
|
|
387
|
+
"type": "user",
|
|
388
|
+
"id": 2188889901
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
"notes": [
|
|
393
|
+
"dashboard visibility is controlled by DashboardUpdateOptionsReqVO.users",
|
|
394
|
+
"use the currentSpeaker.arcubaseUserId value for the current human speaker",
|
|
395
|
+
"after updating, verify from the user side with arcubase app get and require dashboards to include the dashboard"
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
},
|
|
373
400
|
"admin.widget.create": {
|
|
374
401
|
"command": [
|
|
375
402
|
"widget",
|
|
@@ -465,6 +492,68 @@ export const helpExamplesIndex = {
|
|
|
465
492
|
"supported Aggregate values are sum, avg, max, min, count, and distinct_count",
|
|
466
493
|
"unsupported aggregate names fail local body validation before the request is sent"
|
|
467
494
|
]
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"title": "preview filtered distinct_count grouped by source",
|
|
498
|
+
"body": {
|
|
499
|
+
"dataSource": 2188891001,
|
|
500
|
+
"dataSourceType": "entity",
|
|
501
|
+
"dimensions": [
|
|
502
|
+
{
|
|
503
|
+
"IsField": true,
|
|
504
|
+
"FieldID": 1004,
|
|
505
|
+
"Name": "Source"
|
|
506
|
+
}
|
|
507
|
+
],
|
|
508
|
+
"conditions": {
|
|
509
|
+
"mode": "and",
|
|
510
|
+
"conditions": [
|
|
511
|
+
{
|
|
512
|
+
"column": ":1006",
|
|
513
|
+
"operator": "$eq",
|
|
514
|
+
"value": "yes"
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
"measures": [
|
|
519
|
+
{
|
|
520
|
+
"FieldID": 1002,
|
|
521
|
+
"Aggregate": "distinct_count",
|
|
522
|
+
"Name": "Distinct Customers"
|
|
523
|
+
}
|
|
524
|
+
]
|
|
525
|
+
},
|
|
526
|
+
"notes": [
|
|
527
|
+
"use conditions, not filters, for chart data filtering",
|
|
528
|
+
"for saved charts put the same condition set under options.charts.conditions",
|
|
529
|
+
"do not remove the condition and hand-calculate filtered statistics from row query results"
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
},
|
|
534
|
+
"admin.widget.update-ingress-options": {
|
|
535
|
+
"command": [
|
|
536
|
+
"widget",
|
|
537
|
+
"update-ingress-options"
|
|
538
|
+
],
|
|
539
|
+
"examples": [
|
|
540
|
+
{
|
|
541
|
+
"title": "adjust an ingress list widget display configuration",
|
|
542
|
+
"body": {
|
|
543
|
+
"options": {
|
|
544
|
+
"cond_follow": true,
|
|
545
|
+
"cond_follow_tab": true,
|
|
546
|
+
"cond_follow_cols": [
|
|
547
|
+
":1001",
|
|
548
|
+
":1002"
|
|
549
|
+
]
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
"notes": [
|
|
553
|
+
"use this only for widgets created with options.ingress_id",
|
|
554
|
+
"do not use dashboard update-layout for ingress widgets",
|
|
555
|
+
"verify with widget get after updating ingress options"
|
|
556
|
+
]
|
|
468
557
|
}
|
|
469
558
|
]
|
|
470
559
|
},
|
package/src/runtime/execute.ts
CHANGED
|
@@ -1032,15 +1032,37 @@ function buildBodyGuidance(requestType: string): Pick<CLIErrorDetails, 'retryToo
|
|
|
1032
1032
|
dataSourceType: 'entity',
|
|
1033
1033
|
dimensions: [{ IsField: true, FieldID: 1004, Name: 'Source' }],
|
|
1034
1034
|
measures: [{ FieldID: 1005, Aggregate: 'sum', Name: 'Total Amount' }],
|
|
1035
|
+
conditions: { mode: 'and', conditions: [{ column: ':1006', operator: '$eq', value: 'yes' }] },
|
|
1035
1036
|
},
|
|
1036
1037
|
commonMistakes: [
|
|
1037
1038
|
'widget preview-data body is the chart query itself',
|
|
1038
1039
|
'do not send a saved widget object with id, entity_id, or options',
|
|
1039
1040
|
'field dimensions with FieldID must set IsField:true',
|
|
1041
|
+
'use conditions, not filters, for chart data filtering',
|
|
1042
|
+
'do not retry without conditions and then hand-calculate filtered statistics',
|
|
1040
1043
|
'unsupported aggregates are invalid; use sum, avg, max, min, count, or distinct_count',
|
|
1041
1044
|
],
|
|
1042
1045
|
suggestions: [
|
|
1043
1046
|
'retry with: arcubase-admin widget preview-data --app-id <app_id> --body-json \'{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}]}\'',
|
|
1047
|
+
'conditional stats: arcubase-admin widget preview-data --app-id <app_id> --body-json \'{"dataSource":<table_id>,"dataSourceType":"entity","dimensions":[{"IsField":true,"FieldID":<source_field_id>,"Name":"Source"}],"conditions":{"mode":"and","conditions":[{"column":":1006","operator":"$eq","value":"yes"}]},"measures":[{"FieldID":<customer_field_id>,"Aggregate":"distinct_count","Name":"Distinct Customers"}]}\'',
|
|
1048
|
+
],
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (requestType === 'AppNewWidgetsReqVO') {
|
|
1052
|
+
return {
|
|
1053
|
+
shapeHint: {
|
|
1054
|
+
type: 'list',
|
|
1055
|
+
options: { ingress_id: 2188893001 },
|
|
1056
|
+
},
|
|
1057
|
+
commonMistakes: [
|
|
1058
|
+
'dashboard widgets use options.dashboard_id',
|
|
1059
|
+
'ingress widgets use options.ingress_id',
|
|
1060
|
+
'do not put entity_id at body top level or under options when creating a widget',
|
|
1061
|
+
'after creating an ingress widget, use widget update-ingress-options to adjust display configuration',
|
|
1062
|
+
],
|
|
1063
|
+
suggestions: [
|
|
1064
|
+
'dashboard chart: arcubase-admin widget create --app-id <app_id> --body-json \'{"type":"chart","options":{"dashboard_id":<dashboard_id>}}\'',
|
|
1065
|
+
'ingress list: arcubase-admin widget create --app-id <app_id> --body-json \'{"type":"list","options":{"ingress_id":<ingress_id>}}\'',
|
|
1044
1066
|
],
|
|
1045
1067
|
}
|
|
1046
1068
|
}
|
|
@@ -1053,15 +1075,39 @@ function buildBodyGuidance(requestType: string): Pick<CLIErrorDetails, 'retryToo
|
|
|
1053
1075
|
entity_id: 2188891001,
|
|
1054
1076
|
dimensions: [{ IsField: true, FieldID: 1004, Name: 'Source' }],
|
|
1055
1077
|
measures: [{ FieldID: 1005, Aggregate: 'sum', Name: 'Total Amount' }],
|
|
1078
|
+
conditions: { mode: 'and', conditions: [{ column: ':1006', operator: '$eq', value: 'yes' }] },
|
|
1056
1079
|
type: 'bar',
|
|
1057
1080
|
},
|
|
1058
1081
|
},
|
|
1059
1082
|
},
|
|
1060
1083
|
commonMistakes: [
|
|
1061
1084
|
'dashboard chart config belongs in body.options.charts',
|
|
1085
|
+
'ingress/list display settings use widget update-ingress-options, not widget update',
|
|
1086
|
+
'do not put ingress_id, list, default_cols, page_size, or entry display settings in widget update',
|
|
1062
1087
|
'field dimensions with FieldID must set IsField:true',
|
|
1088
|
+
'use options.charts.conditions, not filters, for chart data filtering',
|
|
1089
|
+
'do not retry without conditions and then hand-calculate filtered statistics',
|
|
1063
1090
|
'verify persistence with widget get or widget list after update',
|
|
1064
1091
|
],
|
|
1092
|
+
suggestions: [
|
|
1093
|
+
'dashboard chart: arcubase-admin widget update --app-id <app_id> --widget-id <widget_id> --body-json \'{"entity_id":<table_id>,"options":{"charts":{"entity_id":<table_id>,"dimensions":[{"IsField":true,"FieldID":<field_id>,"Name":"Source"}],"measures":[{"FieldID":<number_field_id>,"Aggregate":"sum","Name":"Total Amount"}],"type":"bar"}}}\'',
|
|
1094
|
+
'ingress list display: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json \'{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}\'',
|
|
1095
|
+
],
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
if (requestType === 'AppUpdateWidgetsIngressOptionsReqVO') {
|
|
1099
|
+
return {
|
|
1100
|
+
shapeHint: {
|
|
1101
|
+
options: { cond_follow: true, cond_follow_tab: true, cond_follow_cols: [':1001', ':1002'] },
|
|
1102
|
+
},
|
|
1103
|
+
commonMistakes: [
|
|
1104
|
+
'widget update-ingress-options is for ingress widgets, not dashboard chart widgets',
|
|
1105
|
+
'put display settings under body.options',
|
|
1106
|
+
'verify the ingress widget with widget get after update',
|
|
1107
|
+
],
|
|
1108
|
+
suggestions: [
|
|
1109
|
+
'retry with: arcubase-admin widget update-ingress-options --app-id <app_id> --widget-id <widget_id> --body-json \'{"options":{"cond_follow":true,"cond_follow_tab":true,"cond_follow_cols":[":1001",":1002"]}}\'',
|
|
1110
|
+
],
|
|
1065
1111
|
}
|
|
1066
1112
|
}
|
|
1067
1113
|
return {}
|
|
@@ -54,6 +54,7 @@ test('admin surface is restricted to reset white list', () => {
|
|
|
54
54
|
test('user surface is restricted to reset white list', () => {
|
|
55
55
|
const actual = commandPaths(userCommands)
|
|
56
56
|
const expected = [
|
|
57
|
+
'app get',
|
|
57
58
|
'dashboard get',
|
|
58
59
|
'dashboard widgets',
|
|
59
60
|
'entry',
|
|
@@ -93,7 +94,7 @@ test('generated modules use CLI namespaces only', () => {
|
|
|
93
94
|
const adminModules = [...new Set(adminCommands.map((item) => item.module))].sort()
|
|
94
95
|
const userModules = [...new Set(userCommands.map((item) => item.module))].sort()
|
|
95
96
|
assert.deepEqual(adminModules, ['access-rule', 'app', 'dashboard', 'table', 'widget', 'workflow'])
|
|
96
|
-
assert.deepEqual(userModules, ['dashboard', 'entry', 'profile', 'row', 'table', 'upload', 'widget', 'workflow'])
|
|
97
|
+
assert.deepEqual(userModules, ['app', 'dashboard', 'entry', 'profile', 'row', 'table', 'upload', 'widget', 'workflow'])
|
|
97
98
|
})
|
|
98
99
|
|
|
99
100
|
test('black list commands are removed from registry', () => {
|