@@ -682,73 +682,147 @@ export const boardRouter = createTRPCRouter({
682682
683683 return await getFullBoardWithWhereAsync ( ctx . db , boardWhere , ctx . session ?. user . id ?? null ) ;
684684 } ) ,
685- saveLayout : protectedProcedure . input ( boardSaveLayoutSchema ) . mutation ( async ( { ctx, input } ) => {
686- await throwIfActionForbiddenAsync ( ctx , eq ( boards . id , input . id ) , "modify" ) ;
685+ saveLayout : protectedProcedure
686+ . meta ( {
687+ mcp : {
688+ enabled : true ,
689+ description :
690+ "Set a board's desktop column count and remove legacy responsive layouts. Requires modify permission. REQUIRED: id (board ID), columnCount (1-24)" ,
691+ } ,
692+ } )
693+ . input ( boardSaveLayoutSchema )
694+ . output ( z . void ( ) )
695+ . mutation ( async ( { ctx, input } ) => {
696+ await throwIfActionForbiddenAsync ( ctx , eq ( boards . id , input . id ) , "modify" ) ;
687697
688- const board = await getFullBoardWithWhereAsync ( ctx . db , eq ( boards . id , input . id ) , ctx . session . user . id ) ;
689- const desktopLayout = board . layouts
690- . toSorted (
691- ( layoutA , layoutB ) => layoutB . breakpoint - layoutA . breakpoint || layoutB . columnCount - layoutA . columnCount ,
692- )
693- . at ( 0 ) ;
698+ const board = await getFullBoardWithWhereAsync ( ctx . db , eq ( boards . id , input . id ) , ctx . session . user . id ) ;
699+ const desktopLayout = board . layouts
700+ . toSorted (
701+ ( layoutA , layoutB ) => layoutB . breakpoint - layoutA . breakpoint || layoutB . columnCount - layoutA . columnCount ,
702+ )
703+ . at ( 0 ) ;
694704
695- if ( ! desktopLayout ) {
696- throw new TRPCError ( { code : "INTERNAL_SERVER_ERROR" , message : "Board must have a layout" } ) ;
697- }
705+ if ( ! desktopLayout ) {
706+ throw new TRPCError ( { code : "INTERNAL_SERVER_ERROR" , message : "Board must have a layout" } ) ;
707+ }
698708
699- if ( desktopLayout . columnCount !== input . columnCount ) {
700- const updatedBoardLayout = getUpdatedBoardLayout ( board , {
701- previous : {
702- layoutId : desktopLayout . id ,
703- columnCount : desktopLayout . columnCount ,
704- } ,
705- current : {
706- layoutId : desktopLayout . id ,
707- columnCount : input . columnCount ,
708- } ,
709- } ) ;
709+ const updatedBoardLayout =
710+ desktopLayout . columnCount === input . columnCount
711+ ? null
712+ : getUpdatedBoardLayout ( board , {
713+ previous : {
714+ layoutId : desktopLayout . id ,
715+ columnCount : desktopLayout . columnCount ,
716+ } ,
717+ current : {
718+ layoutId : desktopLayout . id ,
719+ columnCount : input . columnCount ,
720+ } ,
721+ } ) ;
710722
711- for ( const itemSectionLayout of updatedBoardLayout . itemSectionLayouts ) {
712- await ctx . db
713- . update ( itemLayouts )
714- . set ( {
715- height : itemSectionLayout . height ,
716- width : itemSectionLayout . width ,
717- xOffset : itemSectionLayout . xOffset ,
718- yOffset : itemSectionLayout . yOffset ,
719- sectionId : itemSectionLayout . sectionId ,
720- } )
721- . where (
722- and ( eq ( itemLayouts . itemId , itemSectionLayout . itemId ) , eq ( itemLayouts . layoutId , itemSectionLayout . layoutId ) ) ,
723- ) ;
724- }
723+ await handleTransactionsAsync ( ctx . db , {
724+ async handleAsync ( db , schema ) {
725+ await db . transaction ( async ( transaction ) => {
726+ for ( const itemSectionLayout of updatedBoardLayout ?. itemSectionLayouts ?? [ ] ) {
727+ await transaction
728+ . update ( schema . itemLayouts )
729+ . set ( {
730+ height : itemSectionLayout . height ,
731+ width : itemSectionLayout . width ,
732+ xOffset : itemSectionLayout . xOffset ,
733+ yOffset : itemSectionLayout . yOffset ,
734+ sectionId : itemSectionLayout . sectionId ,
735+ } )
736+ . where (
737+ and (
738+ eq ( schema . itemLayouts . itemId , itemSectionLayout . itemId ) ,
739+ eq ( schema . itemLayouts . layoutId , itemSectionLayout . layoutId ) ,
740+ ) ,
741+ ) ;
742+ }
725743
726- for ( const sectionLayout of updatedBoardLayout . sectionLayouts ) {
727- await ctx . db
728- . update ( sectionLayouts )
729- . set ( {
730- height : sectionLayout . height ,
731- width : sectionLayout . width ,
732- xOffset : sectionLayout . xOffset ,
733- yOffset : sectionLayout . yOffset ,
734- parentSectionId : sectionLayout . parentSectionId ,
735- } )
736- . where (
737- and (
738- eq ( sectionLayouts . sectionId , sectionLayout . sectionId ) ,
739- eq ( sectionLayouts . layoutId , sectionLayout . layoutId ) ,
740- ) ,
741- ) ;
742- }
743- }
744+ for ( const sectionLayout of updatedBoardLayout ?. sectionLayouts ?? [ ] ) {
745+ await transaction
746+ . update ( schema . sectionLayouts )
747+ . set ( {
748+ height : sectionLayout . height ,
749+ width : sectionLayout . width ,
750+ xOffset : sectionLayout . xOffset ,
751+ yOffset : sectionLayout . yOffset ,
752+ parentSectionId : sectionLayout . parentSectionId ,
753+ } )
754+ . where (
755+ and (
756+ eq ( schema . sectionLayouts . sectionId , sectionLayout . sectionId ) ,
757+ eq ( schema . sectionLayouts . layoutId , sectionLayout . layoutId ) ,
758+ ) ,
759+ ) ;
760+ }
744761
745- await ctx . db
746- . update ( layouts )
747- . set ( { name : "Base" , columnCount : input . columnCount , breakpoint : 0 } )
748- . where ( eq ( layouts . id , desktopLayout . id ) ) ;
762+ await transaction
763+ . update ( schema . layouts )
764+ . set ( { name : "Base" , columnCount : input . columnCount , breakpoint : 0 } )
765+ . where ( eq ( schema . layouts . id , desktopLayout . id ) ) ;
749766
750- await ctx . db . delete ( layouts ) . where ( and ( eq ( layouts . boardId , board . id ) , not ( eq ( layouts . id , desktopLayout . id ) ) ) ) ;
751- } ) ,
767+ await transaction
768+ . delete ( schema . layouts )
769+ . where ( and ( eq ( schema . layouts . boardId , board . id ) , not ( eq ( schema . layouts . id , desktopLayout . id ) ) ) ) ;
770+ } ) ;
771+ } ,
772+ handleSync ( db ) {
773+ db . transaction ( ( transaction ) => {
774+ for ( const itemSectionLayout of updatedBoardLayout ?. itemSectionLayouts ?? [ ] ) {
775+ transaction
776+ . update ( itemLayouts )
777+ . set ( {
778+ height : itemSectionLayout . height ,
779+ width : itemSectionLayout . width ,
780+ xOffset : itemSectionLayout . xOffset ,
781+ yOffset : itemSectionLayout . yOffset ,
782+ sectionId : itemSectionLayout . sectionId ,
783+ } )
784+ . where (
785+ and (
786+ eq ( itemLayouts . itemId , itemSectionLayout . itemId ) ,
787+ eq ( itemLayouts . layoutId , itemSectionLayout . layoutId ) ,
788+ ) ,
789+ )
790+ . run ( ) ;
791+ }
792+
793+ for ( const sectionLayout of updatedBoardLayout ?. sectionLayouts ?? [ ] ) {
794+ transaction
795+ . update ( sectionLayouts )
796+ . set ( {
797+ height : sectionLayout . height ,
798+ width : sectionLayout . width ,
799+ xOffset : sectionLayout . xOffset ,
800+ yOffset : sectionLayout . yOffset ,
801+ parentSectionId : sectionLayout . parentSectionId ,
802+ } )
803+ . where (
804+ and (
805+ eq ( sectionLayouts . sectionId , sectionLayout . sectionId ) ,
806+ eq ( sectionLayouts . layoutId , sectionLayout . layoutId ) ,
807+ ) ,
808+ )
809+ . run ( ) ;
810+ }
811+
812+ transaction
813+ . update ( layouts )
814+ . set ( { name : "Base" , columnCount : input . columnCount , breakpoint : 0 } )
815+ . where ( eq ( layouts . id , desktopLayout . id ) )
816+ . run ( ) ;
817+
818+ transaction
819+ . delete ( layouts )
820+ . where ( and ( eq ( layouts . boardId , board . id ) , not ( eq ( layouts . id , desktopLayout . id ) ) ) )
821+ . run ( ) ;
822+ } ) ;
823+ } ,
824+ } ) ;
825+ } ) ,
752826 savePartialBoardSettings : protectedProcedure
753827 . meta ( {
754828 openapi : { method : "PATCH" , path : "/api/boards/{id}/settings" , tags : [ "boards" ] , protect : true } ,
0 commit comments