mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
feat(base): add view visible fields get/set shortcuts (#326)
* feat: add base view visible fields shortcuts and docs * docs: add view-create guidance for visible fields read * docs(base): refine visible fields reference wording * refactor(base): remove noop validate hook from view-set-visible-fields * docs: unify view-set-visible-fields example placeholders * docs: update visible fields example field placeholder * fix(base): pass parse context in view-set-visible-fields * feat: add tips for view-set-visible-fields json usage --------- Co-authored-by: kongenpei <kongenpei@users.noreply.github.com>
This commit is contained in:
@@ -220,6 +220,7 @@ func TestDryRunViewOps(t *testing.T) {
|
||||
assertDryRunContains(t, dryRunViewSetWrapped(setWrappedInvalidRT, "group", "group_config"), "PUT /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/group")
|
||||
|
||||
assertDryRunContains(t, dryRunViewGetFilter(ctx, listRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/filter")
|
||||
assertDryRunContains(t, dryRunViewGetVisibleFields(ctx, listRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/visible_fields")
|
||||
assertDryRunContains(t, dryRunViewGetGroup(ctx, listRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/group")
|
||||
assertDryRunContains(t, dryRunViewGetSort(ctx, listRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/sort")
|
||||
assertDryRunContains(t, dryRunViewGetTimebar(ctx, listRT), "GET /open-apis/base/v3/bases/app_x/tables/tbl_1/views/viw_1/timebar")
|
||||
|
||||
@@ -874,6 +874,61 @@ func TestBaseViewExecuteReadCreateDeleteAndFilter(t *testing.T) {
|
||||
t.Fatalf("stdout=%s", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("get-visible-fields", func(t *testing.T) {
|
||||
factory, stdout, reg := newExecuteFactory(t)
|
||||
reg.Register(&httpmock.Stub{
|
||||
Method: "GET",
|
||||
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/views/vew_1/visible_fields",
|
||||
Body: map[string]interface{}{
|
||||
"code": 0,
|
||||
"data": []interface{}{"fld_primary", "fld_status"},
|
||||
},
|
||||
})
|
||||
if err := runShortcut(t, BaseViewGetVisibleFields, []string{"+view-get-visible-fields", "--base-token", "app_x", "--table-id", "tbl_x", "--view-id", "vew_1"}, factory, stdout); err != nil {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
if got := stdout.String(); !strings.Contains(got, `"visible_fields"`) || !strings.Contains(got, `"fld_primary"`) {
|
||||
t.Fatalf("stdout=%s", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("set-visible-fields-array-invalid", func(t *testing.T) {
|
||||
factory, stdout, _ := newExecuteFactory(t)
|
||||
err := runShortcut(
|
||||
t,
|
||||
BaseViewSetVisibleFields,
|
||||
[]string{"+view-set-visible-fields", "--base-token", "app_x", "--table-id", "tbl_x", "--view-id", "vew_1", "--json", `["fld_status"]`},
|
||||
factory,
|
||||
stdout,
|
||||
)
|
||||
if err == nil || !strings.Contains(err.Error(), "invalid JSON object") {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("set-visible-fields-object", func(t *testing.T) {
|
||||
factory, stdout, reg := newExecuteFactory(t)
|
||||
updateStub := &httpmock.Stub{
|
||||
Method: "PUT",
|
||||
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/views/vew_1/visible_fields",
|
||||
Body: map[string]interface{}{
|
||||
"code": 0,
|
||||
"data": []interface{}{"fld_primary", "fld_status"},
|
||||
},
|
||||
}
|
||||
reg.Register(updateStub)
|
||||
if err := runShortcut(t, BaseViewSetVisibleFields, []string{"+view-set-visible-fields", "--base-token", "app_x", "--table-id", "tbl_x", "--view-id", "vew_1", "--json", `{"visible_fields":["fld_status"]}`}, factory, stdout); err != nil {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
body := string(updateStub.CapturedBody)
|
||||
if !strings.Contains(body, `"visible_fields":["fld_status"]`) {
|
||||
t.Fatalf("request body=%s", body)
|
||||
}
|
||||
if strings.Contains(body, `{"visible_fields":{"visible_fields":`) {
|
||||
t.Fatalf("request body double wrapped: %s", body)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBaseTableExecuteListFallbackShapes(t *testing.T) {
|
||||
|
||||
@@ -120,12 +120,18 @@ func TestWrapViewPropertyBody(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestViewSetVisibleFieldsNoValidateHook(t *testing.T) {
|
||||
if BaseViewSetVisibleFields.Validate != nil {
|
||||
t.Fatalf("expected no validate hook, got non-nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortcutsCatalog(t *testing.T) {
|
||||
shortcuts := Shortcuts()
|
||||
want := []string{
|
||||
"+table-list", "+table-get", "+table-create", "+table-update", "+table-delete",
|
||||
"+field-list", "+field-get", "+field-create", "+field-update", "+field-delete", "+field-search-options",
|
||||
"+view-list", "+view-get", "+view-create", "+view-delete", "+view-get-filter", "+view-set-filter", "+view-get-group", "+view-set-group", "+view-get-sort", "+view-set-sort", "+view-get-timebar", "+view-set-timebar", "+view-get-card", "+view-set-card", "+view-rename",
|
||||
"+view-list", "+view-get", "+view-create", "+view-delete", "+view-get-filter", "+view-set-filter", "+view-get-visible-fields", "+view-set-visible-fields", "+view-get-group", "+view-set-group", "+view-get-sort", "+view-set-sort", "+view-get-timebar", "+view-set-timebar", "+view-get-card", "+view-set-card", "+view-rename",
|
||||
"+record-list", "+record-get", "+record-upsert", "+record-upload-attachment", "+record-delete",
|
||||
"+record-history-list",
|
||||
"+base-get", "+base-copy", "+base-create",
|
||||
|
||||
@@ -25,6 +25,8 @@ func Shortcuts() []common.Shortcut {
|
||||
BaseViewDelete,
|
||||
BaseViewGetFilter,
|
||||
BaseViewSetFilter,
|
||||
BaseViewGetVisibleFields,
|
||||
BaseViewSetVisibleFields,
|
||||
BaseViewGetGroup,
|
||||
BaseViewSetGroup,
|
||||
BaseViewGetSort,
|
||||
|
||||
24
shortcuts/base/view_get_visible_fields.go
Normal file
24
shortcuts/base/view_get_visible_fields.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/larksuite/cli/shortcuts/common"
|
||||
)
|
||||
|
||||
var BaseViewGetVisibleFields = common.Shortcut{
|
||||
Service: "base",
|
||||
Command: "+view-get-visible-fields",
|
||||
Description: "Get view visible fields configuration",
|
||||
Risk: "read",
|
||||
Scopes: []string{"base:view:read"},
|
||||
AuthTypes: authTypes(),
|
||||
Flags: []common.Flag{baseTokenFlag(true), tableRefFlag(true), viewRefFlag(true)},
|
||||
DryRun: dryRunViewGetVisibleFields,
|
||||
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
||||
return executeViewGetProperty(runtime, "visible_fields", "visible_fields")
|
||||
},
|
||||
}
|
||||
@@ -80,10 +80,18 @@ func dryRunViewGetFilter(_ context.Context, runtime *common.RuntimeContext) *com
|
||||
return dryRunViewGetProperty(runtime, "filter")
|
||||
}
|
||||
|
||||
func dryRunViewGetVisibleFields(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
||||
return dryRunViewGetProperty(runtime, "visible_fields")
|
||||
}
|
||||
|
||||
func dryRunViewSetFilter(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
||||
return dryRunViewSetJSONObject(runtime, "filter")
|
||||
}
|
||||
|
||||
func dryRunViewSetVisibleFields(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
||||
return dryRunViewSetJSONObject(runtime, "visible_fields")
|
||||
}
|
||||
|
||||
func dryRunViewGetGroup(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
||||
return dryRunViewGetProperty(runtime, "group")
|
||||
}
|
||||
@@ -249,6 +257,23 @@ func executeViewSetWrapped(runtime *common.RuntimeContext, segment string, wrapp
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeViewSetVisibleFields(runtime *common.RuntimeContext) error {
|
||||
pc := newParseCtx(runtime)
|
||||
baseToken := runtime.Str("base-token")
|
||||
tableIDValue := baseTableID(runtime)
|
||||
viewRef := runtime.Str("view-id")
|
||||
body, err := parseJSONObject(pc, runtime.Str("json"), "json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := baseV3CallAny(runtime, "PUT", baseV3Path("bases", baseToken, "tables", tableIDValue, "views", viewRef, "visible_fields"), nil, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.Out(map[string]interface{}{"visible_fields": data}, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeViewRename(runtime *common.RuntimeContext) error {
|
||||
baseToken := runtime.Str("base-token")
|
||||
tableIDValue := baseTableID(runtime)
|
||||
|
||||
33
shortcuts/base/view_set_visible_fields.go
Normal file
33
shortcuts/base/view_set_visible_fields.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/larksuite/cli/shortcuts/common"
|
||||
)
|
||||
|
||||
var BaseViewSetVisibleFields = common.Shortcut{
|
||||
Service: "base",
|
||||
Command: "+view-set-visible-fields",
|
||||
Description: "Set view visible fields",
|
||||
Risk: "write",
|
||||
Scopes: []string{"base:view:write_only"},
|
||||
AuthTypes: authTypes(),
|
||||
Flags: []common.Flag{
|
||||
baseTokenFlag(true),
|
||||
tableRefFlag(true),
|
||||
viewRefFlag(true),
|
||||
{Name: "json", Desc: `visible fields JSON object with "visible_fields"`, Required: true},
|
||||
},
|
||||
Tips: []string{
|
||||
`Example: --json '{"visible_fields":["fldXXX"]}'`,
|
||||
"Agent hint: use the lark-base skill's view-set-visible-fields guide for usage and limits.",
|
||||
},
|
||||
DryRun: dryRunViewSetVisibleFields,
|
||||
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
||||
return executeViewSetVisibleFields(runtime)
|
||||
},
|
||||
}
|
||||
@@ -71,6 +71,8 @@ POST /open-apis/base/v3/bases/:base_token/tables/:table_id/views
|
||||
|
||||
|
||||
1. 多视图批量创建时,优先用数组一次提交,减少重复调用。
|
||||
2. 如果用户要“查看视图字段顺序”或“查看可见字段”,使用 `+view-get-visible-fields` 读取当前 `visible_fields`。
|
||||
3. 如果用户同时要求“视图字段顺序”或“可见字段”,创建完成后必须继续调用 `+view-set-visible-fields` 设置 `visible_fields`;`+view-create` 本身不负责字段顺序/可见性配置。
|
||||
|
||||
## 坑点
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# base +view-get-visible-fields
|
||||
|
||||
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
|
||||
|
||||
获取可见字段配置。
|
||||
|
||||
## 推荐命令
|
||||
|
||||
```bash
|
||||
lark-cli base +view-get-visible-fields \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--view-id vewXXX
|
||||
```
|
||||
|
||||
## 参数
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-token <token>` | 是 | Base Token |
|
||||
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
||||
| `--view-id <id_or_name>` | 是 | 视图 ID 或视图名 |
|
||||
|
||||
## API 入参详情
|
||||
|
||||
**HTTP 方法和路径:**
|
||||
|
||||
```
|
||||
GET /open-apis/base/v3/bases/:base_token/tables/:table_id/views/:view_id/visible_fields
|
||||
```
|
||||
|
||||
## 返回重点
|
||||
|
||||
- 返回当前视图可见字段列表。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-base-view.md](lark-base-view.md) — view 索引页
|
||||
@@ -0,0 +1,73 @@
|
||||
# base +view-set-visible-fields
|
||||
|
||||
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
|
||||
|
||||
更新视图可见字段列表(同时控制视图中的字段顺序)。
|
||||
|
||||
## 推荐命令
|
||||
|
||||
```bash
|
||||
lark-cli base +view-set-visible-fields \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--view-id vewXXX \
|
||||
--json '{"visible_fields":["标题","fldXXX"]}'
|
||||
```
|
||||
|
||||
## JSON 结构
|
||||
|
||||
```json
|
||||
{
|
||||
"visible_fields": ["标题", "fldXXX"]
|
||||
}
|
||||
```
|
||||
|
||||
## 参数
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-token <token>` | 是 | Base Token |
|
||||
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
||||
| `--view-id <id_or_name>` | 是 | 视图 ID 或视图名 |
|
||||
| `--json <body>` | 是 | JSON 对象,且必须包含 `visible_fields` |
|
||||
|
||||
## API 入参详情
|
||||
|
||||
**HTTP 方法和路径:**
|
||||
|
||||
```
|
||||
PUT /open-apis/base/v3/bases/:base_token/tables/:table_id/views/:view_id/visible_fields
|
||||
```
|
||||
|
||||
**接口 body 格式:**
|
||||
|
||||
```json
|
||||
{
|
||||
"visible_fields": ["标题", "fldXXX"]
|
||||
}
|
||||
```
|
||||
|
||||
## 返回重点
|
||||
|
||||
- 返回可见字段列表与顺序(`primaryField` 会被强制置顶)。
|
||||
|
||||
## 结构规则
|
||||
|
||||
- `visible_fields`:字符串数组,每项可传字段 id 或字段名
|
||||
- 数组顺序用于控制视图字段顺序;主字段 `primaryField` 必须存在且位于第一位,否则 API 会强制将其提升到第一位
|
||||
- `--json` 必须传对象:`{ "visible_fields": [...] }`
|
||||
|
||||
## 工作流
|
||||
|
||||
1. 用户要求“改字段顺序”或“设置可见字段”时,直接使用本命令。
|
||||
2. 建议优先使用字段 id,避免字段重名或后续改名带来的歧义。
|
||||
|
||||
## 坑点
|
||||
|
||||
- ⚠️ 这是写入操作,执行前必须确认。
|
||||
- ⚠️ 接口最终结果会受后端 `primaryField` 强制显示规则影响,返回顺序可能与传入数组不同。
|
||||
- ⚠️ 如果传字段名,必须与当前表真实字段名精确匹配。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-base-view.md](lark-base-view.md) — view 索引页
|
||||
@@ -15,6 +15,8 @@ view 相关命令索引。
|
||||
| [lark-base-view-rename.md](lark-base-view-rename.md) | `+view-rename` | 重命名视图 |
|
||||
| [lark-base-view-get-filter.md](lark-base-view-get-filter.md) | `+view-get-filter` | 读取筛选配置 |
|
||||
| [lark-base-view-set-filter.md](lark-base-view-set-filter.md) | `+view-set-filter` | 更新筛选配置 |
|
||||
| [lark-base-view-get-visible-fields.md](lark-base-view-get-visible-fields.md) | `+view-get-visible-fields` | 读取可见字段列表 |
|
||||
| [lark-base-view-set-visible-fields.md](lark-base-view-set-visible-fields.md) | `+view-set-visible-fields` | 更新可见字段列表 |
|
||||
| [lark-base-view-get-group.md](lark-base-view-get-group.md) | `+view-get-group` | 读取分组配置 |
|
||||
| [lark-base-view-set-group.md](lark-base-view-set-group.md) | `+view-set-group` | 更新分组配置 |
|
||||
| [lark-base-view-get-sort.md](lark-base-view-get-sort.md) | `+view-get-sort` | 读取排序配置 |
|
||||
|
||||
Reference in New Issue
Block a user