fix(sidebar): Unassigned chip resolves child projects through reference rows
The chip check now reuses the ancestor map built by _partitionSidebarSessionRows, so a child whose project parent is only a hidden reference row is not counted as unassigned. Document project inheritance for subagent sessions in README.
This commit is contained in:
1 parent
d04737ec87
commit
35c9b8ae96
4 files changed
+26
-6
No files matched your search
@@ -220,7 +220,7 @@ If an AI assistant is helping with install, reinstall, bootstrap, provider setup
|
||||
- Session actions via `⋯` dropdown per session — pin, move to project, archive, duplicate, delete
|
||||
- Pin/star sessions to the top of the sidebar (gold indicator)
|
||||
- Archive sessions (hide without deleting, toggle to show)
|
||||
- Session projects -- named groups with colors for organizing sessions
|
||||
- Session projects -- named groups with colors for organizing sessions; delegated subagent sessions have no project of their own and follow their nearest ancestor's project in the project filter and the Unassigned chip
|
||||
- Session tags -- add #tag to titles for colored chips and click-to-filter
|
||||
- Grouped by Today / Yesterday / Earlier in the sidebar (collapsible date groups)
|
||||
- Download as Markdown transcript, full JSON export, or import from JSON
|
||||
|
||||
+8
-2
@@ -7622,6 +7622,11 @@ function _sidebarRowsById(rows){
|
||||
return byId;
|
||||
}
|
||||
|
||||
// True when any row resolves to no project, using the filter's own ancestor map.
|
||||
function _sidebarHasUnprojectedRows(rows, rowsById){
|
||||
return rows.some(s=>!_sidebarProjectIdForRow(s, rowsById));
|
||||
}
|
||||
|
||||
function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
const rowsById=_sidebarRowsById([allMatched, typeof _sidebarReferenceSessions!=='undefined'?_sidebarReferenceSessions:null]);
|
||||
let cliSessionCount=0;
|
||||
@@ -7670,6 +7675,7 @@ function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
cliReferenceRaw,
|
||||
webuiSessionsRaw,
|
||||
cliSessionsRaw,
|
||||
rowsById,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7797,6 +7803,7 @@ function renderSessionListFromCache(){
|
||||
cliReferenceRaw,
|
||||
webuiSessionsRaw,
|
||||
cliSessionsRaw,
|
||||
rowsById,
|
||||
}=_partitionSidebarSessionRows(allMatched, activeSidForSidebar);
|
||||
const referenceRaw=_sessionSourceFilter==='cli'?cliReferenceRaw:webuiReferenceRaw;
|
||||
const isCliView=_sessionSourceFilter==='cli';
|
||||
@@ -7871,8 +7878,7 @@ function renderSessionListFromCache(){
|
||||
}
|
||||
// Project filter bar — show when there are real projects OR there are
|
||||
// unassigned sessions (so the Unassigned chip has something to filter to).
|
||||
const profileRowsById=_sidebarRowsById([profileFiltered]);
|
||||
const hasUnprojected=profileFiltered.some(s=>!_sidebarProjectIdForRow(s, profileRowsById));
|
||||
const hasUnprojected=_sidebarHasUnprojectedRows(profileFiltered, rowsById);
|
||||
if(_allProjects.length>0||hasUnprojected){
|
||||
const bar=document.createElement('div');
|
||||
bar.className='project-bar';
|
||||
|
||||
@@ -76,7 +76,7 @@ def test_unassigned_chip_only_shown_when_relevant():
|
||||
— though that's vanishingly rare).
|
||||
"""
|
||||
js = _js()
|
||||
assert "const hasUnprojected=profileFiltered.some(s=>!_sidebarProjectIdForRow(s, profileRowsById));" in js, (
|
||||
assert "const hasUnprojected=_sidebarHasUnprojectedRows(profileFiltered, rowsById);" in js, (
|
||||
"The render function must compute whether unassigned sessions exist"
|
||||
)
|
||||
assert "if(_allProjects.length>0||hasUnprojected){" in js, (
|
||||
|
||||
@@ -44,7 +44,7 @@ global._sessionSourceFilter = 'webui';
|
||||
for (const fn of ['_isSessionLocallyStreaming','_hasPendingUserMessageSignal','_isSessionEffectivelyStreaming',
|
||||
'_isChildSession','_isForkWithResolvableParent','_sessionLineageKey','_sidebarLineageKeyForRow',
|
||||
'_collapseSessionLineageForSidebar','_attachChildSessionsToSidebarRows','_sessionAttentionState',
|
||||
'_sidebarRowHasVisibleMessages','_sidebarProjectIdForRow','_sidebarRowsById',
|
||||
'_sidebarRowHasVisibleMessages','_sidebarProjectIdForRow','_sidebarRowsById','_sidebarHasUnprojectedRows',
|
||||
'_partitionSidebarSessionRows','_scopedSidebarReferenceRows','_renderSidebarRowsFromRawSessions']) {
|
||||
eval.call(global, extractFunc(fn));
|
||||
}
|
||||
@@ -115,4 +115,18 @@ console.log(JSON.stringify({raw: rows.raw, scoped}));
|
||||
|
||||
|
||||
def test_unassigned_chip_ignores_subagents_of_project_parents():
|
||||
assert "const hasUnprojected=profileFiltered.some(s=>!_sidebarProjectIdForRow(s, profileRowsById));" in SESSIONS_JS
|
||||
out = _run("console.log(JSON.stringify(_sidebarHasUnprojectedRows([parent, child], _sidebarRowsById([[parent, child]]))));")
|
||||
assert out is False
|
||||
|
||||
|
||||
def test_unassigned_chip_uses_reference_parent():
|
||||
"""A child whose project parent is only a reference row is not unassigned."""
|
||||
out = _run("""
|
||||
global._sidebarReferenceSessions = [parent];
|
||||
global._activeProject = null;
|
||||
const part = _partitionSidebarSessionRows([child], null);
|
||||
console.log(JSON.stringify({has: _sidebarHasUnprojectedRows(part.profileFiltered, part.rowsById),
|
||||
unassigned: render(NO_PROJECT_FILTER, [child]).raw}));
|
||||
""")
|
||||
assert out["unassigned"] == []
|
||||
assert out["has"] is False
|
||||
Reference in new issue
Block a user