@@ -977,6 +977,11 @@ def _init_view(self):
977977 color = "default" , margin = 0 , visible = False ,
978978 description = "Annotate the report with an AI-written story" ,
979979 )
980+ self ._arrange = IconButton (
981+ icon = "reorder" , on_click = self ._open_arrange_dialog , size = "large" ,
982+ color = "default" , margin = 0 , visible = False ,
983+ description = "Arrange the report (reorder sections and add headings)" ,
984+ )
980985 self ._export = MenuButton (
981986 label = "" , icon = "get_app" , variant = "text" , color = "default" ,
982987 margin = 0 , size = "large" , visible = False ,
@@ -1011,13 +1016,24 @@ def _init_view(self):
10111016 close_on_click = True ,
10121017 title = f"Report Settings: { self .title } " ,
10131018 )
1019+ self ._outline_editor = pn .widgets .JSONEditor (
1020+ mode = "tree" , sizing_mode = "stretch_width" , height = 400 ,
1021+ )
1022+ self ._outline_editor .param .watch (self ._on_outline_change , "value" )
1023+ self ._outline_dialog = Dialog (
1024+ self ._outline_editor ,
1025+ show_close_button = True ,
1026+ title = "Arrange Report" ,
1027+ width_option = "md" ,
1028+ )
10141029 self ._menu = Row (
10151030 self ._header_title ,
10161031 self ._run ,
10171032 self ._stop ,
10181033 self ._clear ,
10191034 self ._collapse ,
10201035 self ._annotate ,
1036+ self ._arrange ,
10211037 self ._export ,
10221038 self ._settings ,
10231039 sizing_mode = "stretch_width"
@@ -1028,6 +1044,7 @@ def _init_view(self):
10281044 {"label" : "Stop Report" , "icon" : "stop" },
10291045 {"label" : "Clear Report" , "icon" : "clear" },
10301046 {"label" : "Annotate Report" , "icon" : "auto_stories" },
1047+ {"label" : "Arrange Report" , "icon" : "reorder" },
10311048 {"label" : "Export as Notebook" , "icon" : "description" , "format" : "ipynb" },
10321049 {"label" : "Export as HTML" , "icon" : "language" , "format" : "html" },
10331050 {"label" : "Configure Report" , "icon" : "settings" }
@@ -1054,6 +1071,7 @@ def _init_view(self):
10541071 self ._container = Column (
10551072 self ._view ,
10561073 self ._dialog ,
1074+ self ._outline_dialog ,
10571075 margin = (0 , 0 , 0 , 5 ),
10581076 sizing_mode = "stretch_both" ,
10591077 height_policy = 'fit' ,
@@ -1074,6 +1092,8 @@ async def _trigger_event(self, item: dict):
10741092 self .reset ()
10751093 elif icon == "auto_stories" :
10761094 await self ._annotate_report ()
1095+ elif icon == "reorder" :
1096+ self ._open_arrange_dialog ()
10771097 elif icon in ("description" , "language" ):
10781098 fmt = item .get ("format" , "ipynb" )
10791099 self ._export .value = {"format" : fmt }
@@ -1094,6 +1114,7 @@ def _update_icon_visibility(self):
10941114 self ._collapse .visible = has_outputs
10951115 self ._annotate .visible = has_outputs
10961116 self ._annotate .disabled = self .llm is None
1117+ self ._arrange .visible = has_outputs
10971118 self ._export .visible = has_outputs
10981119 self ._settings .visible = has_outputs
10991120 # Only animate play button when no outputs
@@ -1212,6 +1233,14 @@ def _expand_all(self, event=None):
12121233 def _open_settings (self , event = None ):
12131234 self ._dialog .open = True
12141235
1236+ def _open_arrange_dialog (self , event = None ):
1237+ # Seed from the current arrangement, or the default section order.
1238+ self ._outline_editor .value = self ._story_outline or self ._build_default_outline ()
1239+ self ._outline_dialog .open = True
1240+
1241+ def _on_outline_change (self , event ):
1242+ self ._story_outline = event .new or []
1243+
12151244 async def _annotate_report (self , event = None ):
12161245 """Write an AI story over the selected sections and insert it into the report."""
12171246 if self .llm is None or not len (self ):
0 commit comments