[bug]: Optimistic kanban drag/drop silently no-ops in epic-filtered views with 'Show sub-issues' off
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
Description
In a kanban view filtered by epic (epic_id__in), grouped by state, and ordered manually, dragging a card between state columns:
- Persists correctly to the backend (PATCH /issues/ returns 204)
- Does NOT update the local kanban. The card stays in the source column until I reload the page.
A reload reflects the new state correctly. There are no console errors, no toasts, and no exceptions in the optimistic-update path. So nothing visibly tells the user the drop "worked."
This makes drag/drop in epic-filtered kanban views feel broken: every move requires a refresh to confirm.
Affected version
web-commercial:v2.5.3(self-hosted)- The relevant code path is also present on current
main, so the OSS build is likely affected too.
Steps to reproduce
- Create a project view filtered by a specific epic (
epic_id__in: <epicId>). - Set Layout: Kanban, Group by: State, Order by: Manual.
- Open the view. Confirm
displayFilters.sub_issueisfalse(the default). - Drag any card from one state column to another.
- Card stays visually in the source column.
- Reload the page. Card now appears in the destination column.
Expected behavior
Card should optimistically move to the destination column right after the drop, matching the persisted server state.
Root cause
In apps/web/core/store/issue/helpers/base-issues.store.ts, inside BaseIssuesStore.updateIssueList (around line 1218):
for (const issueUpdate of issueUpdates) {
if (issueUpdate.action === EIssueGroupedAction.ADD) {
const isSubIssue = issue?.parent_id;
if (isSubIssue && !isShowWorkItemsEnabled) continue; // <-- this guard
update(this, ["groupedIssueIds", ...issueUpdate.path], (issueIds = []) =>
this.issuesSortWithOrderBy(uniq(concat(issueIds, issueId)), this.orderBy)
);
}
...
}
When isShowWorkItemsEnabled (derived from displayFilters.sub_issue) is false AND the issue has a parent_id, the ADD action is skipped.
In an epic-filtered view, every listed item is a child of the epic — its parent_id equals the epic's UUID. So this guard fires on every drop, and the optimistic move never runs.
The guard makes sense for the list-view case where users collapse sub-issues under their parents. It does not make sense in a kanban view that's explicitly filtered by epic, because in that view the epic's children ARE the primary content.
Live evidence (verified against the running MobX store)
Captured by walking the React fiber to the ProjectViewIssues instance, then calling pv.updateIssueList(newIssue, oldIssue) with controlled inputs:
| Test | parent_id | displayFilters.sub_issue | bucket moved? |
|---|---|---|---|
| 1 | <epicId> (real) |
false |
no |
| 2 | null (forced) |
false |
yes |
| 3 | <epicId> (real) |
true |
yes |
The PATCH succeeds in all three cases (the issue's state_id updates correctly in the issue map). Only the groupedIssueIds bucket move is suppressed.
Workaround
Toggle Display Settings → "Show sub-issues" to ON (displayFilters.sub_issue = true). This bypasses the guard and restores optimistic kanban behavior.
It works, but it's not at all obvious that "Show sub-issues" affects kanban drag/drop reactivity. Users will not connect those two things.
Suggested fix
The cleanest fix is to recognize that when a view's filters target items by epic/parent, those items aren't "sub-issues" in the display sense. They're the primary content. So the isSubIssue && !isShowWorkItemsEnabled guard should be skipped when:
- The active filter includes
epic_id__in(or any parent-targeted filter), or - The item's
parent_idis itself the filter target.
If a narrower fix is preferred, just removing the guard for the kanban layout entirely would also resolve this, since hiding a card in kanban mid-drag is a worse UX than showing all matching items.
Environment
- Self-hosted, image
artifacts.plane.so/makeplane/web-commercial:v2.5.3 - Browser: Chrome 148 on macOS
- Stack: api + web + space + live + worker + admin (12-container compose)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in apps/web/core/store/issue/helpers/base-issues.store.ts and inspect BaseIssuesStore.updateIssueList, especially the ADD path and its sub-issue guard. Reproduce the epic-filtered kanban drag/drop case with displayFilters.sub_issue disabled, then verify that the groupedIssueIds bucket moves immediately after the persisted update. Done when the optimistic move works for epic-filtered cards without breaking the intended list-view behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 67/100