feat(view-preset): shared view presets with fork-on-edit semantics
Lands the view-preset / server-persisted personal-layer feature that has been running in production, plus the hotfix for "the same preset shows different filter configs to different users" (物流问题-已出轨迹 on tblgsJTXhqwiDpsjeL5 / viwyszJmLQNOLhA9sh5). Root cause of the divergence: - usePersonalViewSync implicitly flushed any overlay edit by a view|update user INTO the shared preset row (last-writer-wins). Overlays are stale snapshots seeded at apply time, so one user's seed silently erased colleagues' filter changes (2026-09-17 02:55 the preset lost the 流转角色=售后 condition), and active overlays never converged because preset updates do not propagate. Fix (semantics: presets are shared definitions, edits are personal): - fork-on-edit: the first user edit strips the seed markers from the overlay (toolbar switches to the personal config); edits only ever write the user's personal row - shared presets change ONLY through the new explicit, confirmed "Update to current config" row action (canManage users) - un-edited preset overlays auto-follow redefinitions: applyPreset stamps a presetVersion (preset.lastModifiedTime); when the preset list refetches with a newer row the overlay re-seeds. Edited overlays carry no markers and are never clobbered. Legacy rows without a version re-seed exactly once - exits strip both seed markers from the persisted personal row Also lands the pending WIP shipped with the deployed build: select-choice visibility constraint, personal-view server sync + proxy, grid async records scope/request tracking, CLI resource display, preset i18n (10 locales), view_preset migrations, docs/skill updates, .zcode gitignore. Verified end-to-end on the live instance (headless chromium, real session): apply -> edit flips toolbar to Personal with ZERO shared-row PUTs; explicit update PUTs the shared row; API-side redefinition auto-reseeds an un-edited overlay on the next list refetch.
This commit is contained in:
@@ -43,14 +43,16 @@ inkreach-teable table create --name <n> [--base-id <id>] [--fields '<json>']
|
||||
inkreach-teable table update <tableId> --name <n>
|
||||
inkreach-teable table delete <tableId>
|
||||
|
||||
# field (get/update/delete take <tableId> <fieldId> — 2026-08 fix; old /api/field/:id routes never existed)
|
||||
inkreach-teable field list <tableId>
|
||||
inkreach-teable field get <tableId> <fieldId>
|
||||
# field (get/update/visible-choices take <tableId> <fieldIdOrName> — id or display name, auto-resolved)
|
||||
inkreach-teable field list <tableId> [--with-options]
|
||||
# --with-options: OPTIONS summary column + per-choice visibility conditions for select fields
|
||||
inkreach-teable field get <tableId> <fieldIdOrName>
|
||||
# human mode renders select choices with their visibilityFilter conditions; --json for raw
|
||||
inkreach-teable field create --table-id <tid> --name <n> [--type <t|alias>] [--options '<json>'] \
|
||||
[--description <d>] [--lookup-options '<json>'] [--is-lookup]
|
||||
# --type optional: inferred from --options shape / --name when omitted
|
||||
inkreach-teable field update <tableId> <fieldId> [--name <n>] [--options '<json>'] # --options goes via convert API
|
||||
inkreach-teable field visible-choices <tableId> <recordId> <fieldId> # evaluate select-choice visibilityFilter
|
||||
inkreach-teable field update <tableId> <fieldIdOrName> [--name <n>] [--options '<json>'] # --options goes via convert API
|
||||
inkreach-teable field visible-choices <tableId> <recordId> <fieldIdOrName> # evaluate select-choice visibilityFilter
|
||||
inkreach-teable field delete <tableId> <fieldId>
|
||||
|
||||
# record
|
||||
@@ -67,6 +69,13 @@ inkreach-teable view get <viewId>
|
||||
inkreach-teable view create --table-id <tid> --name <n> [--type <t>]
|
||||
inkreach-teable view update <viewId> [--name <n>]
|
||||
inkreach-teable view delete <viewId>
|
||||
|
||||
# view presets (view-scoped shared named filter/sort bundles, applied via toolbar)
|
||||
inkreach-teable preset list <tableId> [--view-id <vid>]
|
||||
inkreach-teable preset create --table-id <tid> --view-id <vid> --name <n> [--description <d>] \
|
||||
[--filter '<json>'] [--sort '<json>'] [--group '<json>'] [--options '<json>'] [--column-meta '<json>']
|
||||
inkreach-teable preset update <presetId> --table-id <tid> [--name <n>] [--description <d>] [--filter '<json>' ...]
|
||||
inkreach-teable preset delete <presetId> --table-id <tid>
|
||||
```
|
||||
|
||||
## workflow
|
||||
@@ -157,6 +166,21 @@ inkreach-teable fire webhook <baseId> <workflowId> [--body '<json>'] [--method <
|
||||
|
||||
Manually trigger for testing. Webhook needs no auth (backend is `@Public`).
|
||||
|
||||
## subscription
|
||||
|
||||
```bash
|
||||
inkreach-teable subscription list
|
||||
inkreach-teable subscription get <subscriptionId>
|
||||
inkreach-teable subscription create --name <n> --table-id <tid> [options]
|
||||
inkreach-teable subscription update <subscriptionId> [options]
|
||||
inkreach-teable subscription delete <subscriptionId>
|
||||
inkreach-teable subscription events <subscriptionId>
|
||||
inkreach-teable subscription send <subscriptionId>
|
||||
```
|
||||
|
||||
Record digest/instant email subscriptions. Options (`--filter`, `--send-mode`,
|
||||
`--schedule-*`, `--trigger-on-enter`, …) and semantics: [subscription.md](subscription.md).
|
||||
|
||||
## sql
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user