@@ -45,6 +45,7 @@ export class KanbanView extends BasesViewBase {
4545 private draggedSourceSwimlanes : Map < string , string > = new Map ( ) ; // Track source swimlane per task for batch operations
4646 private taskInfoCache = new Map < string , TaskInfo > ( ) ;
4747 private sortScopeTaskPaths = new Map < string , string [ ] > ( ) ;
48+ private sortScopeCandidateTaskPaths = new Map < string , string [ ] > ( ) ;
4849 private containerListenersRegistered = false ;
4950 private columnScrollers = new Map < string , VirtualScroller < TaskInfo > > ( ) ; // columnKey -> scroller
5051 private expandedRelationshipFilterMode : TaskCardOptions [ "expandedRelationshipFilterMode" ] =
@@ -350,6 +351,7 @@ export class KanbanView extends BasesViewBase {
350351 this . destroyColumnScrollers ( ) ;
351352 this . boardEl . empty ( ) ;
352353 this . sortScopeTaskPaths . clear ( ) ;
354+ this . sortScopeCandidateTaskPaths . clear ( ) ;
353355
354356 if ( filteredTasks . length === 0 ) {
355357 // Show "no results" if search returned empty but we had tasks
@@ -375,17 +377,20 @@ export class KanbanView extends BasesViewBase {
375377
376378 // Group tasks
377379 const groups = this . groupTasks ( filteredTasks , groupByPropertyId , pathToProps ) ;
380+ const allGroups = this . groupTasks ( taskNotes , groupByPropertyId , pathToProps ) ;
378381
379382 // Render swimlanes if configured
380383 if ( this . swimLanePropertyId ) {
381384 await this . renderWithSwimLanes (
382385 groups ,
383386 filteredTasks ,
387+ allGroups ,
388+ taskNotes ,
384389 pathToProps ,
385390 groupByPropertyId
386391 ) ;
387392 } else {
388- await this . renderFlat ( groups ) ;
393+ await this . renderFlat ( groups , allGroups ) ;
389394 }
390395 } catch ( error : any ) {
391396 console . error ( "[TaskNotes][KanbanView] Error rendering:" , error ) ;
@@ -433,6 +438,17 @@ export class KanbanView extends BasesViewBase {
433438 return this . sortScopeTaskPaths . get ( this . getSortScopeKey ( groupKey , swimLaneKey ) ) ;
434439 }
435440
441+ private getCandidateSortScopePaths ( groupKey : string , swimLaneKey : string | null = null ) : string [ ] | undefined {
442+ return this . sortScopeCandidateTaskPaths . get ( this . getSortScopeKey ( groupKey , swimLaneKey ) ) ;
443+ }
444+
445+ private setSortScopeCandidatePaths ( entries : Iterable < [ string , string [ ] ] > ) : void {
446+ this . sortScopeCandidateTaskPaths . clear ( ) ;
447+ for ( const [ scopeKey , paths ] of entries ) {
448+ this . sortScopeCandidateTaskPaths . set ( scopeKey , [ ...paths ] ) ;
449+ }
450+ }
451+
436452 private async confirmLargeReorder (
437453 editCount : number ,
438454 groupKey : string ,
@@ -686,9 +702,18 @@ export class KanbanView extends BasesViewBase {
686702 }
687703 }
688704
689- private async renderFlat ( groups : Map < string , TaskInfo [ ] > ) : Promise < void > {
705+ private async renderFlat (
706+ groups : Map < string , TaskInfo [ ] > ,
707+ allGroups : Map < string , TaskInfo [ ] >
708+ ) : Promise < void > {
690709 if ( ! this . boardEl ) return ;
691710 this . sortScopeTaskPaths . clear ( ) ;
711+ this . setSortScopeCandidatePaths (
712+ Array . from ( allGroups . entries ( ) ) . map ( ( [ groupKey , tasks ] ) => [
713+ this . getSortScopeKey ( groupKey ) ,
714+ tasks . map ( ( task ) => task . path ) ,
715+ ] )
716+ ) ;
692717
693718 // Set CSS variable for column width (allows responsive override)
694719 this . boardEl . style . setProperty ( "--kanban-column-width" , `${ this . columnWidth } px` ) ;
@@ -729,6 +754,8 @@ export class KanbanView extends BasesViewBase {
729754 private async renderWithSwimLanes (
730755 groups : Map < string , TaskInfo [ ] > ,
731756 allTasks : TaskInfo [ ] ,
757+ allGroups : Map < string , TaskInfo [ ] > ,
758+ allTasksForCandidateScopes : TaskInfo [ ] ,
732759 pathToProps : Map < string , Record < string , any > > ,
733760 groupByPropertyId : string
734761 ) : Promise < void > {
@@ -784,6 +811,47 @@ export class KanbanView extends BasesViewBase {
784811 }
785812 }
786813
814+ const candidateSwimLanes = new Map < string , Map < string , TaskInfo [ ] > > ( ) ;
815+ const candidateSwimLaneValues = new Set < string > ( ) ;
816+
817+ for ( const task of allTasksForCandidateScopes ) {
818+ const props = pathToProps . get ( task . path ) || { } ;
819+ const swimLaneValue = this . getPropertyValue ( props , this . swimLanePropertyId ) ;
820+ const swimLaneKey = this . valueToString ( swimLaneValue ) ;
821+ candidateSwimLaneValues . add ( swimLaneKey ) ;
822+ }
823+
824+ for ( const swimLaneKey of candidateSwimLaneValues ) {
825+ const swimLaneMap = new Map < string , TaskInfo [ ] > ( ) ;
826+ candidateSwimLanes . set ( swimLaneKey , swimLaneMap ) ;
827+
828+ for ( const [ columnKey ] of allGroups ) {
829+ swimLaneMap . set ( columnKey , [ ] ) ;
830+ }
831+ }
832+
833+ for ( const [ columnKey , columnTasks ] of allGroups ) {
834+ for ( const task of columnTasks ) {
835+ const props = pathToProps . get ( task . path ) || { } ;
836+ const swimLaneValue = this . getPropertyValue ( props , this . swimLanePropertyId ) ;
837+ const swimLaneKey = this . valueToString ( swimLaneValue ) ;
838+ const swimLane = candidateSwimLanes . get ( swimLaneKey ) ;
839+ if ( ! swimLane ) continue ;
840+ if ( swimLane . has ( columnKey ) ) {
841+ swimLane . get ( columnKey ) ! . push ( task ) ;
842+ }
843+ }
844+ }
845+
846+ this . setSortScopeCandidatePaths (
847+ Array . from ( candidateSwimLanes . entries ( ) ) . flatMap ( ( [ swimLaneKey , columns ] ) =>
848+ Array . from ( columns . entries ( ) ) . map ( ( [ columnKey , tasks ] ) => [
849+ this . getSortScopeKey ( columnKey , swimLaneKey ) ,
850+ tasks . map ( ( task ) => task . path ) ,
851+ ] as [ string , string [ ] ] )
852+ )
853+ ) ;
854+
787855 // Apply column ordering
788856 const columnKeys = Array . from ( groups . keys ( ) ) ;
789857 const orderedKeys = this . applyColumnOrder ( groupByPropertyId , columnKeys ) ;
@@ -2409,6 +2477,7 @@ export class KanbanView extends BasesViewBase {
24092477 ? [ { property : cleanSwimLaneForSort , value : newSwimLaneValue } ]
24102478 : undefined ;
24112479 const visibleTaskPaths = this . getVisibleSortScopePaths ( newGroupValue , newSwimLaneValue ) ;
2480+ const candidateTaskPaths = this . getCandidateSortScopePaths ( newGroupValue , newSwimLaneValue ) ;
24122481
24132482 this . debugLog ( "SORT-ORDER-CHECK" , {
24142483 hasDropTarget : ! ! dropTarget ,
@@ -2474,6 +2543,7 @@ export class KanbanView extends BasesViewBase {
24742543 scopeFilters : sortScopeFilters ,
24752544 taskInfoCache : this . taskInfoCache ,
24762545 visibleTaskPaths,
2546+ candidateTaskPaths,
24772547 }
24782548 ) ;
24792549 if ( sortOrderPlan . sortOrder === null ) {
0 commit comments