Spaces:
Sleeping
Sleeping
| import json | |
| import pandas as pd | |
| from nsepython import * | |
| import html | |
| import html | |
| import pandas as pd | |
| def build_indices_html(): | |
| """ | |
| Generate HTML: | |
| - main table | |
| - dates table | |
| - tables for all categories | |
| - charts ONLY for key == "INDICES ELIGIBLE IN DERIVATIVES" | |
| - flexible chart layout (no grid, auto-fit) | |
| """ | |
| p = indices() # your existing function | |
| data_df = p.get("data", pd.DataFrame()) | |
| dates_df = p.get("dates", pd.DataFrame()) | |
| records = data_df.to_dict(orient="records") if not data_df.empty else [] | |
| # Columns to hide in category tables | |
| hidden_cols = { | |
| "key","chartTodayPath","chart30dPath","chart30Path","chart365dPath", | |
| "date365dAgo","date30dAgo","previousDay","oneWeekAgo","oneMonthAgoVal", | |
| "oneWeekAgoVal","oneYearAgoVal","index","indicativeClose" | |
| } | |
| # ----------- BASIC TABLE BUILDER ----------- | |
| def build_table_from_records(recs, cols=None): | |
| if not recs: | |
| return "<p>No data available.</p>" | |
| if cols is None: | |
| cols = [] | |
| for r in recs: | |
| for k in r.keys(): | |
| if k not in cols: | |
| cols.append(k) | |
| header = "".join(f"<th>{html.escape(str(c))}</th>" for c in cols) | |
| body_rows = [] | |
| for r in recs: | |
| tds = [] | |
| for c in cols: | |
| v = r.get(c, "") | |
| if isinstance(v, (list, dict)): | |
| v = str(v) | |
| tds.append(f"<td>{html.escape('' if v is None else str(v))}</td>") | |
| body_rows.append("<tr>" + "".join(tds) + "</tr>") | |
| return f""" | |
| <table> | |
| <thead><tr>{header}</tr></thead> | |
| <tbody>{''.join(body_rows)}</tbody> | |
| </table> | |
| """ | |
| # ----------- FLEXIBLE CHART BLOCK ----------- | |
| def build_chart_grid_for_record(r): | |
| """ | |
| Flexible chart layout: auto-fit, no fixed grid. | |
| ONLY for INDICES ELIGIBLE IN DERIVATIVES category. | |
| """ | |
| def iframe_if_exists(src, label): | |
| if src and isinstance(src, str) and src.strip(): | |
| return f""" | |
| <div class="chart-flex-item"> | |
| <iframe src="{html.escape(src)}" loading="lazy" | |
| frameborder="0" title="{html.escape(label)}"></iframe> | |
| </div> | |
| """ | |
| return "" | |
| today_src = r.get("chartTodayPath") or r.get("chartToday") or "" | |
| month30_src = r.get("chart30dPath") or r.get("chart30Path") or "" | |
| year365_src = r.get("chart365dPath") or r.get("chart365") or "" | |
| block = ( | |
| iframe_if_exists(today_src, "Today Chart") + | |
| iframe_if_exists(month30_src, "30d Chart") + | |
| iframe_if_exists(year365_src, "365d Chart") | |
| ) | |
| if not block.strip(): | |
| return "" | |
| title = r.get("index") or r.get("indexSymbol") or r.get("symbol") or "" | |
| return f""" | |
| <div class="chart-flex-block"> | |
| <div class="chart-title"><strong>{html.escape(str(title))}</strong></div> | |
| <div class="chart-flex-container"> | |
| {block} | |
| </div> | |
| </div> | |
| """ | |
| # ----------- MAIN TABLE ----------- | |
| main_table_html = build_table_from_records(records) | |
| # ----------- DATES TABLE ----------- | |
| dates_table_html = "" | |
| if not dates_df.empty: | |
| dates_records = dates_df.to_dict(orient="records") | |
| dates_table_html = build_table_from_records(dates_records) | |
| # ----------- GROUP BY KEY ---------- | |
| from collections import defaultdict | |
| groups = defaultdict(list) | |
| for r in records: | |
| groups[r.get("key") or "UNCLASSIFIED"].append(r) | |
| per_key_sections = [] | |
| # ----------- PER CATEGORY SECTIONS ---------- | |
| for key_name, recs in groups.items(): | |
| # Determine visible columns | |
| first = recs[0] | |
| cols = [c for c in first.keys() if c not in hidden_cols] | |
| # Preferred order | |
| preferred = ["indexSymbol", "index", "symbol", "name"] | |
| ordered = [] | |
| for pkey in preferred: | |
| if pkey in cols: | |
| ordered.append(pkey) | |
| for c in cols: | |
| if c not in ordered: | |
| ordered.append(c) | |
| table_html = build_table_from_records(recs, ordered) | |
| # CHARTS ONLY FOR INDICES ELIGIBLE IN DERIVATIVES | |
| if str(key_name).strip().upper() == "INDICES ELIGIBLE IN DERIVATIVES": | |
| charts_html = "\n".join(build_chart_grid_for_record(r) for r in recs) | |
| else: | |
| charts_html = "" # no charts for other categories | |
| per_key_sections.append(f""" | |
| <section class="key-section"> | |
| <h3>Category: {html.escape(str(key_name))} (Total: {len(recs)})</h3> | |
| <div class="key-table">{table_html}</div> | |
| {charts_html} | |
| </section> | |
| """) | |
| # ----------- CSS ----------- | |
| css = """ | |
| <style> | |
| body { font-family: Arial; padding: 16px; background: #fff; color: #111; } | |
| table { border-collapse: collapse; width: 100%; margin-bottom: 14px; } | |
| th, td { border: 1px solid #ccc; padding: 6px 8px; font-size: 13px; } | |
| th { background: #007bff; color: white; position: sticky; top: 0; } | |
| .scroll { max-height: 420px; overflow: auto; padding: 6px; background: #fafafa; | |
| margin-bottom: 16px; border: 1px solid #ddd; } | |
| .key-section { | |
| border: 1px solid #e6eef6; | |
| background: #fbfeff; | |
| border-radius: 6px; | |
| padding: 10px; | |
| margin-bottom: 30px; | |
| } | |
| /* FLEXIBLE CHART LAYOUT */ | |
| .chart-flex-block { | |
| border: 1px solid #ddd; | |
| background: #fff; | |
| padding: 8px; | |
| border-radius: 6px; | |
| margin-bottom: 14px; | |
| } | |
| .chart-title { margin-bottom: 6px; font-size: 14px; } | |
| .chart-flex-container { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| } | |
| .chart-flex-item { | |
| flex: 1 1 300px; | |
| min-height: 180px; | |
| border: 1px solid #ccc; | |
| border-radius: 6px; | |
| overflow: hidden; | |
| } | |
| .chart-flex-item iframe { | |
| width: 100%; | |
| height: 100%; | |
| border: 0; | |
| } | |
| </style> | |
| """ | |
| # ----------- FINAL HTML ASSEMBLY ----------- | |
| html_parts = [ | |
| "<!DOCTYPE html>", | |
| "<html><head><meta charset='utf-8'><title>NSE Indices</title>", | |
| css, | |
| "</head><body>", | |
| "<h1>NSE Indices — Full Static Render</h1>", | |
| f"<div class='meta'>Generated: {html.escape(pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S'))}</div>", | |
| "<h2>Main Indices Table</h2>", | |
| "<div class='scroll'>", main_table_html, "</div>", | |
| "<h2>Dates / Meta</h2>" if dates_table_html else "", | |
| "<div class='scroll'>" if dates_table_html else "", | |
| dates_table_html, | |
| "</div>" if dates_table_html else "", | |
| "<h2>Categories</h2>", | |
| *per_key_sections, | |
| "</body></html>" | |
| ] | |
| return "\n".join(str(x) for x in html_parts) | |