@@ -119,8 +119,8 @@ def generate_report(self, output_dir: str = SECTIONS_DIR) -> None:
119119 """\
120120 import os
121121 import time
122-
123- import psutil
122+
123+ import psutil
124124 import streamlit as st
125125 """
126126 )
@@ -129,7 +129,10 @@ def generate_report(self, output_dir: str = SECTIONS_DIR) -> None:
129129 report_manag_content .append (
130130 textwrap .dedent (
131131 f"""\
132- st.set_page_config(layout="wide", page_title="{ self .report .title } ", page_icon="{ self .report .logo } ")
132+ st.set_page_config(layout="wide",
133+ page_title="{ self .report .title } ",
134+ page_icon="{ self .report .logo } "
135+ )
133136 st.logo("{ self .report .logo } ")
134137 """
135138 )
@@ -138,7 +141,8 @@ def generate_report(self, output_dir: str = SECTIONS_DIR) -> None:
138141 report_manag_content .append (
139142 textwrap .dedent (
140143 f"""\
141- st.set_page_config(layout="wide", page_title="{ self .report .title } ")
144+ st.set_page_config(layout="wide",
145+ page_title="{ self .report .title } ")
142146 """
143147 )
144148 )
@@ -227,9 +231,12 @@ def generate_report(self, output_dir: str = SECTIONS_DIR) -> None:
227231 textwrap .dedent (
228232 """\
229233 report_nav = st.navigation(sections_pages)
230-
231- # Following https://discuss.streamlit.io/t/close-streamlit-app-with-button-click/35132/5
232- exit_app = st.sidebar.button("Shut Down App", icon=":material/power_off:", use_container_width=True)
234+
235+ # Following https://discuss.streamlit.io/t/\
236+ close-streamlit-app-with-button-click/35132/5
237+ exit_app = st.sidebar.button("Shut Down App",
238+ icon=":material/power_off:",
239+ use_container_width=True)
233240 if exit_app:
234241 st.toast("Shutting down the app...")
235242 time.sleep(1)
@@ -238,7 +245,7 @@ def generate_report(self, output_dir: str = SECTIONS_DIR) -> None:
238245 p = psutil.Process(pid)
239246 p.terminate()
240247
241-
248+
242249 report_nav.run()
243250 """
244251 )
@@ -367,7 +374,17 @@ def _format_text(
367374 raise ValueError (
368375 f"Unsupported text type: { type } . Supported types are 'header', "
369376 "'paragraph', and 'caption'."
370- )
377+
378+ return textwrap .dedent (
379+ f"""
380+ st.markdown(
381+ (
382+ "<{ tag } style='text-align: { text_align } ; "
383+ "color: { color } ;'>{ text } </{ tag } >"
384+ ),
385+ unsafe_allow_html=True)
386+ """
387+ )
371388
372389 def _generate_home_section (
373390 self ,
@@ -665,9 +682,16 @@ def _generate_plot_content(self, plot) -> List[str]:
665682
666683 # Append the code for additional information (nodes and edges count)
667684 plot_content .append (
668- f"""
669- st.markdown(f"<p style='text-align: center; color: black;'> <b>Number of nodes:</b> { num_nodes } </p>", unsafe_allow_html=True)
670- st.markdown(f"<p style='text-align: center; color: black;'> <b>Number of relationships:</b> { num_edges } </p>", unsafe_allow_html=True)\n """
685+ textwrap .dedent (
686+ f"""
687+ st.markdown(("<p style='text-align: center; color: black;'> "
688+ f"<b>Number of nodes:</b> { num_nodes } </p>"),
689+ unsafe_allow_html=True)
690+ st.markdown(("<p style='text-align: center; color: black;'>"
691+ f" <b>Number of relationships:</b> { num_edges } </p>"),
692+ unsafe_allow_html=True)
693+ """
694+ )
671695 )
672696
673697 # Add the specific code for visualization
@@ -703,37 +727,51 @@ def _generate_plot_code(self, plot) -> str:
703727 """
704728 # If the file path is a URL, generate code to fetch content via requests
705729 if is_url (plot .file_path ):
706- plot_code = f"""
707- response = requests.get('{ plot .file_path } ')
708- response.raise_for_status()
709- plot_json = json.loads(response.text)\n """
730+ plot_code = textwrap .dedent (
731+ f"""
732+ response = requests.get('{ plot .file_path } ')
733+ response.raise_for_status()
734+ plot_json = json.loads(response.text)\n """
735+ )
710736 else : # If it's a local file
711737 plot_rel_path = get_relative_file_path (plot .file_path )
712- plot_code = f"""
713- with open('{ plot_rel_path .as_posix ()} ', 'r') as plot_file:
714- plot_json = json.load(plot_file)\n """
738+ plot_code = textwrap .dedent (
739+ f"""
740+ with open('{ plot_rel_path .as_posix ()} ', 'r') as plot_file:
741+ plot_json = json.load(plot_file)\n """
742+ )
715743
716744 # Add specific code for each visualization tool
717745 if plot .plot_type == r .PlotType .PLOTLY :
718- plot_code += """
719- # Keep only 'data' and 'layout' sections
720- plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}
721-
722- # Remove 'frame' section in 'data'
723- plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]
724- st.plotly_chart(plot_json, use_container_width=True)\n """
746+ plot_code += textwrap .dedent (
747+ """
748+ # Keep only 'data' and 'layout' sections
749+ plot_json = {key: plot_json[key] for key in plot_json
750+ if key in ['data', 'layout']}
751+
752+ # Remove 'frame' section in 'data'
753+ plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'}
754+ for entry in plot_json.get('data', [])]
755+ st.plotly_chart(plot_json, use_container_width=True)\n """
756+ )
725757
726758 elif plot .plot_type == r .PlotType .ALTAIR :
727- plot_code += """
728- altair_plot = alt.Chart.from_dict(plot_json)
729- st.vega_lite_chart(json.loads(altair_plot.to_json()), use_container_width=True)\n """
759+ plot_code += textwrap .dedent (
760+ """
761+ altair_plot = alt.Chart.from_dict(plot_json)
762+ st.vega_lite_chart(json.loads(altair_plot.to_json()),
763+ use_container_width=True)\n """
764+ )
730765
731766 elif plot .plot_type == r .PlotType .INTERACTIVE_NETWORK :
732- plot_code = """# Streamlit checkbox for controlling the layout
733- control_layout = st.checkbox('Add panel to control layout', value=True)
734- net_html_height = 1200 if control_layout else 630
735- # Load HTML into HTML component for display on Streamlit
736- st.components.v1.html(html_content, height=net_html_height)\n """
767+ plot_code = textwrap .dedent (
768+ """\
769+ # Streamlit checkbox for controlling the layout
770+ control_layout = st.checkbox('Add panel to control layout', value=True)
771+ net_html_height = 1200 if control_layout else 630
772+ # Load HTML into HTML component for display on Streamlit
773+ st.components.v1.html(html_content, height=net_html_height)\n """
774+ )
737775 return plot_code
738776
739777 def _generate_dataframe_content (self , dataframe ) -> List [str ]:
@@ -796,7 +834,8 @@ def _generate_dataframe_content(self, dataframe) -> List[str]:
796834 textwrap .dedent (
797835 f"""\
798836 sheet_names = table_utils.get_sheet_names("{ dataframe .file_path } ")
799- selected_sheet = st.selectbox("Select a sheet to display", options=sheet_names)
837+ selected_sheet = st.selectbox("Select a sheet to display",
838+ options=sheet_names)
800839 """
801840 )
802841 )
@@ -818,26 +857,35 @@ def _generate_dataframe_content(self, dataframe) -> List[str]:
818857 # ! Alternative to select box: iterate over sheets in DataFrame
819858 # Displays a DataFrame using AgGrid with configurable options.
820859 dataframe_content .append (
821- """
822- # Displays a DataFrame using AgGrid with configurable options.
823- grid_builder = GridOptionsBuilder.from_dataframe(df)
824- grid_builder.configure_default_column(editable=True, groupable=True, filter=True)
825- grid_builder.configure_side_bar(filters_panel=True, columns_panel=True)
826- grid_builder.configure_selection(selection_mode="multiple")
827- grid_builder.configure_pagination(enabled=True, paginationAutoPageSize=False, paginationPageSize=20)
828- grid_options = grid_builder.build()
829-
830- AgGrid(df, gridOptions=grid_options, enable_enterprise_modules=True)
831-
832- # Button to download the df
833- df_csv = df.to_csv(sep=',', header=True, index=False).encode('utf-8')
834- st.download_button(
835- label="Download dataframe as CSV",
836- data=df_csv,
837- file_name=f"dataframe_{df_index}.csv",
838- mime='text/csv',
839- key=f"download_button_{df_index}")
840- df_index += 1"""
860+ textwrap .dedent (
861+ """
862+ # Displays a DataFrame using AgGrid with configurable options.
863+ grid_builder = GridOptionsBuilder.from_dataframe(df)
864+ grid_builder.configure_default_column(editable=True,
865+ groupable=True,
866+ filter=True,
867+ )
868+ grid_builder.configure_side_bar(filters_panel=True,
869+ columns_panel=True)
870+ grid_builder.configure_selection(selection_mode="multiple")
871+ grid_builder.configure_pagination(enabled=True,
872+ paginationAutoPageSize=False,
873+ paginationPageSize=20,
874+ )
875+ grid_options = grid_builder.build()
876+
877+ AgGrid(df, gridOptions=grid_options, enable_enterprise_modules=True)
878+
879+ # Button to download the df
880+ df_csv = df.to_csv(sep=',', header=True, index=False).encode('utf-8')
881+ st.download_button(
882+ label="Download dataframe as CSV",
883+ data=df_csv,
884+ file_name=f"dataframe_{df_index}.csv",
885+ mime='text/csv',
886+ key=f"download_button_{df_index}")
887+ df_index += 1"""
888+ )
841889 )
842890 except Exception as e :
843891 self .report .logger .error (
0 commit comments