Repository navigation
Commit 10bfd70
fix(plugin-calendar): no resize-end handle without an end field; a drop that changes no date writes nothing (#29146)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9Ubb65Wst5VpQJdataZHSzkMiF)_
Fixes #29020
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
-
**改了什么**:日历视图没有配置结束日期字段(`endDateField`)时,月视图卡片右侧不再画「调整结束」拖拽柄,周/日视图事件底部的「调整结束」柄也不再画;移动卡片、顶部「调整开始」柄照旧。另外,日历默认的拖放保存在「要写的日期与记录现值完全相同」时不再发写请求。做法:`CalendarView`
新增可选属性 `endEditable`(默认 true),`ObjectCalendar` 按是否声明 `endDateField` 传入。
- **为什么改**:只有开始日期的日历(如 showcase
任务日历)上,拖结束柄什么都不改,却把原样的开始日期写回去:`updated_at`
变了,所有「记录更新后」触发器和流程都为一次没人做的修改跑了一遍(通知、审计行、集成)。周视图里在事件上按下再松开(不移动)也会这样写一次。
- **风险与回滚**:低。声明了结束字段的视图两个柄都保留、照旧写结束日期(结束值为空的记录也能拖出结束日期);独立使用
`CalendarView` 不传新属性时行为不变。回滚即还原本 PR。
- **先看**:`ObjectCalendar.tsx` 的 `handleEventDropDefault` 开头新增的「无变化不写」判断与
`sameInstant`;`CalendarView.tsx` 月视图 `showResizeHandle`
与周/日视图底部柄的条件;`ObjectCalendar.tsx` 渲染 `CalendarView` 处新增的 `endEditable`。
- **两分钟验证**:在 `ui/` 下运行 `pnpm exec vitest run
packages/plugin-calendar/src/__tests__/ObjectCalendar.endEditable-29020.test.tsx`,预期
1 个文件、13 个测试全绿。
- **需要你做的**:无,席位落地。
## What changes
- **`CalendarViewProps.endEditable?: boolean`** (default `true`; the
type is exported from the `@object-ui/plugin-calendar` entry, hence the
widening declaration). When `false`:
- the month view draws no "Resize event end" handle, and a `resize-end`
drag payload dropped anyway hands nothing to `onEventDrop`;
- the week and day views draw no bottom "Resize end" handle.
Moving a card and the time grid's top "Resize start" handle are
unchanged.
- **`ObjectCalendar`** passes
`endEditable={Boolean(calendarConfig.endDateField)}`. A view that
declares an end field keeps both handles and keeps writing the end,
including on a record whose end is empty.
- **No write for a drop that changes no date.** `ObjectCalendar`'s
default drop handler (`handleEventDropDefault`) returns before the
optimistic update and `dataSource.update` when the start it would write
is the record's start, and either it writes no end or that end is the
record's end. Both are compared as instants, read the way the grid
placed the event (`toDisplayDate`), so a stored spelling that differs
from the one written back still counts as unchanged; an empty or
unparseable stored value never matches, so it still writes. This closes
the second door to the same write: a press and release on a week-view
event, without moving it, calls `onEventDrop` with the event's own dates
and wrote them back, with or without an end field. A host that supplies
its own `onEventDrop` is unaffected.
## Tests
New file
`ui/packages/plugin-calendar/src/__tests__/ObjectCalendar.endEditable-29020.test.tsx`,
13 cases:
- **Month view, `ObjectCalendar`:** no end field draws no "Resize event
end" handle; no end field still moves the card and writes the start
alone. Controls: with an end field the handle is drawn and dragging it
writes the new end; with an end field and an empty end on the record,
the handle is drawn and writes the end.
- **Week view, `ObjectCalendar`:** no end field (with `allDayField`
declared, so the record is drawn timed) draws the top handle and no
bottom handle. Control: with an end field, both handles.
- **No-op drop:** a press and release on a week-view event writes
nothing, both with no end field and with one. Control: the same event
moved two hours writes its new start.
- **`CalendarView` directly:** `endEditable` defaults to drawing the
handle; `false` hides the month handle while the card still moves;
`false` refuses a `resize-end` payload; `false` hides the week view's
bottom handle and keeps the top one.
## Acceptance notes
- With no `endDateField` and no `allDayField`, `ObjectCalendar` marks
every record all-day, so the week and day views draw it in the all-day
lane, which has no handles. The bottom-handle change matters only when
the view also declares `allDayField` and a record is flagged not
all-day.
- With no end field, the time grid's top "Resize start" handle still
writes the dragged start, and the event is then drawn an hour long from
it, so it reads as a move rather than a resize. It writes a real change,
so it is left as it is and reported to the seat.
- `calendar-view-renderer.tsx` (the schema-driven `calendar-view`
element) does not forward the new prop, so authored `calendar-view`
nodes keep the default `true`, as before.
## Verification
All readings on head `88ee38a1` (fix `ce572f2f`, changeset declaration
`50f1987b`, test fixture `88ee38a1`), base `5d3667e2`.
<details><summary>Tests</summary>
- New file alone: 13 of 13 passed.
- Red on main: with `CalendarView.tsx` and `ObjectCalendar.tsx` restored
from `5d3667e2` (the tests import the source, no rebuild involved), the
new file ran 7 failed and 6 passed. Every case asserting the new
behaviour failed; the six controls passed. Restored with `git checkout
HEAD`, `git diff HEAD` empty, blob equal to HEAD.
- Ablation of the no-op guard: `scripts/ablation-replace.mjs` turned the
guard's first condition into `false && …` (anchor 1 to 0, blob moved);
the two press-and-release cases failed, 11 passed; restored, `git diff
HEAD` empty.
- Full package: `pnpm --dir ui exec vitest run --maxWorkers=2
packages/plugin-calendar/` under the verify lock: 67 files passed, 490
tests passed, 95 skipped (the zone-driven cases that run only in their
forks child).
- `pnpm exec turbo run type-check --filter=@object-ui/plugin-calendar`:
50 of 50 tasks successful.
</details>
<details><summary>Gates</summary>
- `node scripts/pm/dispatch-gates.mjs --commands` derived 34 families;
all 34 ran with exit 0 on head `88ee38a1`, the 33 unlocked ones with
this body as the PR event (`check-adr-0087-registration`,
`check-changeset-no-major`, `check-closing-keyword-parity`,
`check-empty-changeset`, `check-sdui-manifest` among them), and `pnpm
--dir ui exec vitest run scripts/` locked: 169 files passed, 2 skipped
(4,900 tests passed).
- `dispatch-gates --ran`: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.
- `node ui/scripts/check-new-cross-file-line-citations.mjs`: 0 new
citations.
- `eslint` on the three changed ui files: 0 errors; 52 warnings, the
same counts (24 and 28) the two source files carry at the base, and none
in the new test file.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jTP5DLZwaztvKMgUJf)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1e4841a commit 10bfd70
4 files changed
Lines changed: 406 additions & 3 deletions
File tree
- .changeset
- ui/packages/plugin-calendar/src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
161 | 169 | | |
162 | 170 | | |
163 | 171 | | |
| |||
174 | 182 | | |
175 | 183 | | |
176 | 184 | | |
| 185 | + | |
177 | 186 | | |
178 | 187 | | |
179 | 188 | | |
| |||
442 | 451 | | |
443 | 452 | | |
444 | 453 | | |
| 454 | + | |
445 | 455 | | |
446 | 456 | | |
447 | 457 | | |
| |||
455 | 465 | | |
456 | 466 | | |
457 | 467 | | |
| 468 | + | |
458 | 469 | | |
459 | 470 | | |
460 | 471 | | |
| |||
468 | 479 | | |
469 | 480 | | |
470 | 481 | | |
| 482 | + | |
471 | 483 | | |
472 | 484 | | |
473 | 485 | | |
| |||
539 | 551 | | |
540 | 552 | | |
541 | 553 | | |
| 554 | + | |
| 555 | + | |
542 | 556 | | |
543 | 557 | | |
544 | | - | |
| 558 | + | |
545 | 559 | | |
546 | 560 | | |
547 | 561 | | |
| |||
675 | 689 | | |
676 | 690 | | |
677 | 691 | | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
678 | 695 | | |
679 | 696 | | |
680 | 697 | | |
| |||
784 | 801 | | |
785 | 802 | | |
786 | 803 | | |
787 | | - | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
788 | 807 | | |
789 | 808 | | |
790 | 809 | | |
| |||
867 | 886 | | |
868 | 887 | | |
869 | 888 | | |
| 889 | + | |
| 890 | + | |
870 | 891 | | |
871 | 892 | | |
872 | 893 | | |
| |||
1002 | 1023 | | |
1003 | 1024 | | |
1004 | 1025 | | |
| 1026 | + | |
1005 | 1027 | | |
1006 | 1028 | | |
1007 | 1029 | | |
| |||
1584 | 1606 | | |
1585 | 1607 | | |
1586 | 1608 | | |
1587 | | - | |
| 1609 | + | |
1588 | 1610 | | |
1589 | 1611 | | |
1590 | 1612 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
361 | 361 | | |
362 | 362 | | |
363 | 363 | | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
364 | 376 | | |
365 | 377 | | |
366 | 378 | | |
| |||
1272 | 1284 | | |
1273 | 1285 | | |
1274 | 1286 | | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
| 1294 | + | |
| 1295 | + | |
| 1296 | + | |
| 1297 | + | |
| 1298 | + | |
| 1299 | + | |
1275 | 1300 | | |
1276 | 1301 | | |
1277 | 1302 | | |
| |||
1666 | 1691 | | |
1667 | 1692 | | |
1668 | 1693 | | |
| 1694 | + | |
| 1695 | + | |
| 1696 | + | |
1669 | 1697 | | |
1670 | 1698 | | |
1671 | 1699 | | |
| |||
0 commit comments