@@ -1547,6 +1547,48 @@ function buildBoardGroupsWithMovedItem(itemId, targetGroupIndex, boardGroups = b
15471547 return groups ;
15481548}
15491549
1550+ function buildBoardGroupsWithPlacedItem ( itemId , targetGroupIndex , beforeItemId = "" , boardGroups = buildBoardGroupsPayload ( ) ) {
1551+ if ( ! itemId || ! Number . isInteger ( targetGroupIndex ) || targetGroupIndex < 0 || targetGroupIndex >= boardGroups . length ) {
1552+ return null ;
1553+ }
1554+
1555+ const sourceGroupIndex = boardGroups . findIndex ( ( group ) => group . itemIds . includes ( itemId ) ) ;
1556+ if ( sourceGroupIndex < 0 ) {
1557+ return null ;
1558+ }
1559+
1560+ const groups = boardGroups . map ( ( group ) => ( {
1561+ ...group ,
1562+ itemIds : group . itemIds . filter ( ( currentId ) => currentId !== itemId ) ,
1563+ } ) ) ;
1564+
1565+ const targetItems = [ ...groups [ targetGroupIndex ] . itemIds ] ;
1566+ let insertIndex = targetItems . length ;
1567+
1568+ if ( beforeItemId ) {
1569+ const nextIndex = targetItems . indexOf ( beforeItemId ) ;
1570+ if ( nextIndex >= 0 ) {
1571+ insertIndex = nextIndex ;
1572+ }
1573+ }
1574+
1575+ targetItems . splice ( insertIndex , 0 , itemId ) ;
1576+ groups [ targetGroupIndex ] = {
1577+ ...groups [ targetGroupIndex ] ,
1578+ itemIds : targetItems ,
1579+ } ;
1580+
1581+ const unchanged = boardGroups . every ( ( group , index ) => {
1582+ if ( group . itemIds . length !== groups [ index ] . itemIds . length ) {
1583+ return false ;
1584+ }
1585+ return group . itemIds . every ( ( currentId , itemIndex ) => currentId === groups [ index ] . itemIds [ itemIndex ] ) ;
1586+ } ) ;
1587+
1588+ return unchanged ? null : groups ;
1589+ }
1590+
1591+
15501592function clearBoardDragState ( ) {
15511593 state . dragItemId = null ;
15521594 state . dragColumnIndex = null ;
@@ -1624,6 +1666,43 @@ async function persistBoardColumnMove(itemId, targetGroupIndex) {
16241666 }
16251667}
16261668
1669+ async function persistBoardItemPlacement ( itemId , targetGroupIndex , beforeItemId = "" ) {
1670+ if ( ! state . workspace || ! itemId || ! Number . isInteger ( targetGroupIndex ) || targetGroupIndex < 0 || targetGroupIndex >= state . workspace . boardGroups . length ) {
1671+ return ;
1672+ }
1673+
1674+ const groups = buildBoardGroupsWithPlacedItem ( itemId , targetGroupIndex , beforeItemId ) ;
1675+ if ( ! groups ) {
1676+ return ;
1677+ }
1678+
1679+ setBanner ( "Updating board order..." ) ;
1680+
1681+ try {
1682+ const workspace = await fetchJson ( "/api/board" , {
1683+ method : "POST" ,
1684+ headers : { "Content-Type" : "application/json" } ,
1685+ body : JSON . stringify ( { groups } ) ,
1686+ } ) ;
1687+
1688+ const keepItemOpen = ! shouldUseEditorOverlay ( ) || ( state . editorOverlayOpen && state . selectedItemId === itemId ) ;
1689+ state . workspace = workspace ;
1690+ if ( ! keepItemOpen ) {
1691+ state . editorOverlayOpen = false ;
1692+ }
1693+ syncWorkspaceChrome ( ) ;
1694+ await syncVisibleSelection ( {
1695+ preferredItemId : keepItemOpen ? itemId : "" ,
1696+ replaceRoute : true ,
1697+ forceReloadItem : keepItemOpen ,
1698+ } ) ;
1699+ setBanner ( "Board updated." , "success" ) ;
1700+ } catch ( error ) {
1701+ setBanner ( error . message , "error" ) ;
1702+ }
1703+ }
1704+
1705+
16271706async function persistDerivedLensMove ( itemId , targetValue ) {
16281707 const activeLens = getActiveLensDefinition ( ) ;
16291708 if ( ! activeLens || activeLens . key === DEFAULT_LENS_KEY || ! activeLens . draggable || ! targetValue ) {
@@ -1695,9 +1774,12 @@ function renderBoardColumnsMode() {
16951774 const dragHandle = allowColumnDrag
16961775 ? `<span class="board-column-card-drag" data-drag-item-id="${ escapeHtml ( item . id ) } " draggable="true" role="button" tabindex="0" aria-label="Move ${ escapeHtml ( item . title ) } " title="Drag to move ${ escapeHtml ( item . title ) } ">::</span>`
16971776 : "" ;
1777+ const placementAttributes = boardGrouping && allowColumnDrag
1778+ ? `data-board-drop-group-index="${ group . originalIndex } " data-board-drop-before-id="${ escapeHtml ( item . id ) } "`
1779+ : "" ;
16981780
16991781 return `
1700- <article class="board-column-card${ activeClass } " title="${ escapeHtml ( item . title ) } ">
1782+ <article class="board-column-card${ activeClass } ${ placementAttributes ? " board-column-dropzone" : "" } " title="${ escapeHtml ( item . title ) } " ${ placementAttributes } >
17011783 <div class="board-column-card-main" data-item-dblopen="${ escapeHtml ( item . id ) } " title="${ escapeHtml ( item . title ) } ">
17021784 ${ buildBoardCardBodyMarkup ( item , activeLens ?. key ) }
17031785 </div>
@@ -1775,7 +1857,7 @@ function renderBoardColumnsMode() {
17751857 } ) ;
17761858 }
17771859
1778- for ( const dropZone of boardGroupsElement . querySelectorAll ( "[data-board-drop-group-index], [data-lens-drop-value]" ) ) {
1860+ for ( const dropZone of boardGroupsElement . querySelectorAll ( "[data-board-drop-group-index], [data-lens-drop-value], [data-board-drop-before-id] " ) ) {
17791861 dropZone . addEventListener ( "dragover" , ( event ) => {
17801862 if ( ! state . dragItemId ) {
17811863 return ;
@@ -1808,6 +1890,15 @@ function renderBoardColumnsMode() {
18081890 return ;
18091891 }
18101892
1893+ if ( dropZone . dataset . boardDropBeforeId ) {
1894+ void persistBoardItemPlacement (
1895+ itemId ,
1896+ Number ( dropZone . dataset . boardDropGroupIndex ) ,
1897+ dropZone . dataset . boardDropBeforeId || "" ,
1898+ ) ;
1899+ return ;
1900+ }
1901+
18111902 if ( dropZone . dataset . boardDropGroupIndex ) {
18121903 void persistBoardColumnMove ( itemId , Number ( dropZone . dataset . boardDropGroupIndex ) ) ;
18131904 return ;
0 commit comments