@@ -36,31 +36,63 @@ def get_widget_description(title):
3636
3737 return " " .join (description_parts )
3838
39- def generate_html_report ( images_dir = 'dashboard_exports' , output_file = None ):
39+ def generate_section_html ( env_name , images_dir ):
4040 """
41- Generate an HTML report with all dashboard widget images.
42- Images are embedded as base64 for portability.
41+ Generate HTML for a specific environment section.
4342 """
44-
4543 images_path = Path (images_dir )
46-
4744 if not images_path .exists ():
48- print (f"Error: Directory { images_dir } not found" )
49- return None
45+ return f"<p>No data found for { env_name } </p>"
5046
51- # Find all PNG images
5247 image_files = sorted (images_path .glob ('*.png' ))
53-
5448 if not image_files :
55- print (f"Error: No PNG images found in { images_dir } " )
56- return None
49+ return f"<p>No images found for { env_name } </p>"
5750
58- print (f"Found { len (image_files )} images to include in report" )
51+ html = f"""
52+ <div class="env-section">
53+ <h2 class="env-title">{ env_name } </h2>
54+ """
55+
56+ for idx , image_file in enumerate (image_files , 1 ):
57+ filename = image_file .stem
58+ title = filename .split ('_' , 1 )[1 ] if '_' in filename else filename
59+ title = title .replace ('_' , ' ' )
60+ description = get_widget_description (title )
61+
62+ with open (image_file , 'rb' ) as f :
63+ image_data = base64 .b64encode (f .read ()).decode ('utf-8' )
64+
65+ html += f"""
66+ <div class="widget-card">
67+ <div class="widget-header">
68+ <div class="widget-title">{ idx } . { title } </div>
69+ <div class="widget-description">{ description } </div>
70+ </div>
71+ <div class="widget-image-container">
72+ <img class="widget-image"
73+ src="data:image/png;base64,{ image_data } "
74+ alt="{ title } ">
75+ </div>
76+ </div>
77+ """
78+
79+ html += "</div>"
80+ return html
81+
82+ def generate_html_report (base_dir = 'dashboard_exports' , output_file = None ):
83+ """
84+ Generate an HTML report with all dashboard widget images from multiple environments.
85+ """
86+ base_path = Path (base_dir )
87+
88+ if not base_path .exists ():
89+ print (f"Error: Base directory { base_dir } not found" )
90+ return None
5991
6092 # Default output filename
6193 if output_file is None :
6294 timestamp = datetime .now ().strftime ('%Y%m%d_%H%M%S' )
63- output_file = f'{ images_dir } /dashboard_report_{ timestamp } .html'
95+ output_file = f'{ base_dir } /dashboard_report_{ timestamp } .html'
6496
6597 # Get dashboard name and timestamp from definition file
6698 dashboard_name = "Monthly Demand And Capacity Report - EliD"
@@ -136,6 +168,32 @@ def generate_html_report(images_dir='dashboard_exports', output_file=None):
136168 padding-bottom: 48px;
137169 }}
138170
171+ .section-header {{
172+ background: var(--nhs-white);
173+ padding: 16px 24px;
174+ margin-bottom: 24px;
175+ border-left: 8px solid var(--nhs-blue);
176+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
177+ }}
178+
179+ .section-header h2 {{
180+ font-size: 24px;
181+ color: var(--nhs-blue);
182+ margin: 0;
183+ }}
184+
185+ .env-section {{
186+ margin-bottom: 48px;
187+ }}
188+
189+ .env-title {{
190+ font-size: 20px;
191+ color: var(--nhs-dark-grey);
192+ margin-bottom: 20px;
193+ padding-bottom: 8px;
194+ border-bottom: 2px solid #d8dde0;
195+ }}
196+
139197 .widget-card {{
140198 background: var(--nhs-white);
141199 border: 1px solid #d8dde0;
@@ -199,6 +257,11 @@ def generate_html_report(images_dir='dashboard_exports', output_file=None):
199257 border: none;
200258 border-bottom: 1px solid #ccc;
201259 }}
260+ .section-header {{
261+ border: none;
262+ padding: 0;
263+ margin-bottom: 16px;
264+ }}
202265 }}
203266 </style>
204267</head>
@@ -216,34 +279,28 @@ def generate_html_report(images_dir='dashboard_exports', output_file=None):
216279 <div class="nhs-container content">
217280"""
218281
219- # Add each widget image
220- for idx , image_file in enumerate (image_files , 1 ):
221- # Extract widget title from filename (remove number prefix and extension)
222- filename = image_file .stem
223- # Remove leading number and underscore (e.g., "01_")
224- title = filename .split ('_' , 1 )[1 ] if '_' in filename else filename
225- # Replace underscores with spaces
226- title = title .replace ('_' , ' ' )
227-
228- description = get_widget_description (title )
229-
230- # Read and encode image
231- with open (image_file , 'rb' ) as f :
232- image_data = base64 .b64encode (f .read ()).decode ('utf-8' )
282+ # ---------------------------------------------------------
283+ # Section 1: Production
284+ # ---------------------------------------------------------
285+ html_content += """
286+ <div class="section-header">
287+ <h2>Production Environment</h2>
288+ </div>
289+ """
290+ html_content += generate_section_html ("Prod" , base_path / "Prod" )
233291
234- html_content += f"""
235- <div class="widget-card">
236- <div class="widget-header">
237- <div class="widget-title">{ idx } . { title } </div>
238- <div class="widget-description">{ description } </div>
239- </div>
240- <div class="widget-image-container">
241- <img class="widget-image"
242- src="data:image/png;base64,{ image_data } "
243- alt="{ title } ">
244- </div>
292+ # ---------------------------------------------------------
293+ # Section 2: Preprod Environments
294+ # ---------------------------------------------------------
295+ html_content += """
296+ <div class="section-header" style="margin-top: 48px;">
297+ <h2>Preprod Environments</h2>
245298 </div>
246- """
299+ """
300+
301+ # Order: Preprod, Test, Dev
302+ for env in ["Preprod" , "Test" , "Dev" ]:
303+ html_content += generate_section_html (env , base_path / env )
247304
248305 # Close HTML
249306 html_content += """
0 commit comments