eshan6704 commited on
Commit
e1398c2
·
verified ·
1 Parent(s): c9073bf

Update indices_html.py

Browse files
Files changed (1) hide show
  1. indices_html.py +158 -119
indices_html.py CHANGED
@@ -2,188 +2,227 @@ import json
2
  import pandas as pd
3
  from nsepython import *
4
  import html
 
 
5
 
6
-
7
- def build_indices_html():
8
  """
9
- Generate a single, fully-rendered HTML string (no <script>) containing:
10
- - main indices table
11
- - dates table (if present)
12
- - one table per category/key
13
- - for each index record, a chart grid with 3 iframes (if paths exist) or placeholders
14
-
15
- Requires: indices() function available in scope which returns dict with keys:
16
- - "data": DataFrame of records (each row a dict with fields including at least 'key', 'index', 'indexSymbol')
17
- - "dates": DataFrame (optional)
18
  """
19
- p = indices() # must exist in your module
 
20
  data_df = p.get("data", pd.DataFrame())
21
  dates_df = p.get("dates", pd.DataFrame())
22
 
23
- # Convert records to list of dicts for iteration
24
  records = data_df.to_dict(orient="records") if not data_df.empty else []
25
 
26
- # Hidden columns we don't want to show in per-category tables
27
  hidden_cols = {
28
  "key","chartTodayPath","chart30dPath","chart30Path","chart365dPath",
29
  "date365dAgo","date30dAgo","previousDay","oneWeekAgo","oneMonthAgoVal",
30
  "oneWeekAgoVal","oneYearAgoVal","index","indicativeClose"
31
  }
32
 
 
33
  def build_table_from_records(recs, cols=None):
34
- """Return HTML <table> string for recs (list of dicts). If cols provided, use that order."""
35
  if not recs:
36
  return "<p>No data available.</p>"
37
 
38
- # Determine columns
39
  if cols is None:
40
- # union of keys preserving insertion order from first record
41
  cols = []
42
  for r in recs:
43
  for k in r.keys():
44
  if k not in cols:
45
  cols.append(k)
46
 
47
- # Build header
48
- header_cells = "".join(f"<th>{html.escape(str(c))}</th>" for c in cols)
49
- rows_html = []
50
  for r in recs:
51
- row_cells = []
52
  for c in cols:
53
  v = r.get(c, "")
54
- # Convert lists/dicts to string
55
  if isinstance(v, (list, dict)):
56
- cell = html.escape(str(v))
57
- else:
58
- cell = html.escape("" if v is None else str(v))
59
- row_cells.append(f"<td>{cell}</td>")
60
- rows_html.append("<tr>" + "".join(row_cells) + "</tr>")
61
-
62
- table_html = "<table>\n<thead>\n<tr>" + header_cells + "</tr>\n</thead>\n<tbody>\n" + "\n".join(rows_html) + "\n</tbody>\n</table>"
63
- return table_html
 
 
64
 
 
65
  def build_chart_grid_for_record(r):
66
  """
67
- Build a 3-panel grid for charts for a single record r.
68
- Uses r.get('chartTodayPath'), r.get('chart30dPath' or 'chart30Path'), r.get('chart365dPath').
69
- If a path is missing, show a placeholder box with text.
70
  """
71
- def iframe_or_placeholder(src, label):
 
72
  if src and isinstance(src, str) and src.strip():
73
- # escape src only in attribute context
74
- return f'<div class="chart-cell"><iframe src="{html.escape(src)}" frameborder="0" loading="lazy" title="{html.escape(label)}" style="width:100%;height:100%;"></iframe></div>'
75
- else:
76
- return f'<div class="chart-cell placeholder"><div class="ph-inner">{html.escape(label)}<br/>(no chart)</div></div>'
77
-
78
- today_src = r.get("chartTodayPath") or r.get("chartToday") or ""
79
- month30_src = r.get("chart30dPath") or r.get("chart30Path") or r.get("chart30") or ""
80
- year365_src = r.get("chart365dPath") or r.get("chart365Path") or r.get("chart365") or ""
81
-
82
- idx_name = r.get("index") or r.get("indexSymbol") or r.get("symbol") or ""
83
-
84
- grid = (
85
- '<div class="chart-grid-record">\n'
86
- f' <div class="chart-header"><strong>{html.escape(str(idx_name))}</strong></div>\n'
87
- ' <div class="chart-row">\n'
88
- f' {iframe_or_placeholder(today_src, "Today Chart")}\n'
89
- f' {iframe_or_placeholder(month30_src, "30d Chart")}\n'
90
- ' </div>\n'
91
- ' <div class="chart-row">\n'
92
- f' {iframe_or_placeholder(year365_src, "365d Chart")}\n'
93
- ' </div>\n'
94
- '</div>\n'
95
  )
96
- return grid
97
 
98
- # Build main full table (all columns present in records)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  main_table_html = build_table_from_records(records)
100
 
101
- # Build dates table if dates_df present
102
  dates_table_html = ""
103
  if not dates_df.empty:
104
  dates_records = dates_df.to_dict(orient="records")
105
  dates_table_html = build_table_from_records(dates_records)
106
 
107
- # Group records by 'key' (category)
108
  from collections import defaultdict
109
  groups = defaultdict(list)
110
  for r in records:
111
- k = r.get("key") or "UNCLASSIFIED"
112
- groups[k].append(r)
113
 
114
- # Build per-key tables and per-record chart grids
115
  per_key_sections = []
 
 
116
  for key_name, recs in groups.items():
117
- # Columns to show: all keys from first record except hidden_cols, preserving order
118
- first = recs[0] if recs else {}
 
119
  cols = [c for c in first.keys() if c not in hidden_cols]
120
- # But ensure some useful order: indexSymbol/index/name first if present
121
- preferred = ["indexSymbol","index","symbol","name"]
122
- cols_sorted = []
123
- for p in preferred:
124
- if p in cols:
125
- cols_sorted.append(p)
 
126
  for c in cols:
127
- if c not in cols_sorted:
128
- cols_sorted.append(c)
 
 
129
 
130
- table_html = build_table_from_records(recs, cols_sorted)
131
- # Build chart block for all recs in this key
132
- charts_html = "\n".join(build_chart_grid_for_record(r) for r in recs)
 
 
133
 
134
- section_html = f"""
135
  <section class="key-section">
136
- <h3>Category: {html.escape(str(key_name))} (Total: {len(recs)})</h3>
137
- <div class="key-table">{table_html}</div>
138
- <div class="key-charts">{charts_html}</div>
139
  </section>
140
- """
141
- per_key_sections.append(section_html)
142
 
143
- # CSS for layout (no JS)
144
  css = """
145
  <style>
146
- body { font-family: Arial, sans-serif; padding: 16px; color: #111; background: #fff; }
147
- h1,h2,h3 { color: #0b69a3; margin: 8px 0; }
148
- table { border-collapse: collapse; width: 100%; margin-bottom: 12px; font-size: 13px; }
149
- th, td { border: 1px solid #d0d0d0; padding: 6px 8px; text-align: left; vertical-align: top; }
150
- th { background: #007bff; color: #fff; position: sticky; top: 0; z-index: 2; }
151
- .scroll { max-height: 420px; overflow: auto; border: 1px solid #eee; padding: 8px; background: #fafafa; margin-bottom: 18px; }
152
- .key-section { margin-bottom: 28px; padding: 8px 6px; border: 1px solid #e6eef6; background: #fbfeff; border-radius: 6px; }
153
- .chart-grid-record { border: 1px solid #e0e0e0; padding: 6px; margin: 8px 0; border-radius: 6px; background: #fff; }
154
- .chart-header { margin-bottom: 6px; }
155
- .chart-row { display: flex; gap: 8px; margin-bottom: 8px; }
156
- .chart-cell { flex: 1 1 0; height: 200px; border: 1px solid #ddd; }
157
- .chart-cell.iframe-wrap iframe { width:100%; height:100%; border:0; }
158
- .placeholder { display:flex; align-items:center; justify-content:center; background:#f6f6f6; color:#666; font-size:13px; }
159
- .ph-inner { text-align:center; padding:8px; }
160
- .meta { font-size: 13px; color: #444; margin-bottom: 8px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  </style>
162
  """
163
 
164
- # HTML assembly
165
- html_parts = []
166
- html_parts.append("<!DOCTYPE html>")
167
- html_parts.append("<html><head><meta charset='utf-8'><title>NSE Indices (Static)</title>")
168
- html_parts.append(css)
169
- html_parts.append("</head><body>")
170
- html_parts.append("<h1>NSE Indices — Full Static Render</h1>")
171
- html_parts.append(f"<div class='meta'>Generated: {html.escape(pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S'))}</div>")
172
 
173
- html_parts.append("<h2>Main Indices Table</h2>")
174
- html_parts.append("<div class='scroll'>")
175
- html_parts.append(main_table_html)
176
- html_parts.append("</div>")
177
 
178
- if dates_table_html:
179
- html_parts.append("<h2>Dates / Meta</h2>")
180
- html_parts.append("<div class='scroll'>")
181
- html_parts.append(dates_table_html)
182
- html_parts.append("</div>")
183
 
184
- html_parts.append("<h2>Categories & Charts (All)</h2>")
185
- html_parts.extend(per_key_sections)
186
 
187
- html_parts.append("</body></html>")
 
188
 
189
- return "\n".join(html_parts)
 
2
  import pandas as pd
3
  from nsepython import *
4
  import html
5
+ import html
6
+ import pandas as pd
7
 
8
+ def build_indices_html_nojs():
 
9
  """
10
+ Generate HTML:
11
+ - main table
12
+ - dates table
13
+ - tables for all categories
14
+ - charts ONLY for key == "INDICES ELIGIBLE IN DERIVATIVES"
15
+ - flexible chart layout (no grid, auto-fit)
 
 
 
16
  """
17
+
18
+ p = indices() # your existing function
19
  data_df = p.get("data", pd.DataFrame())
20
  dates_df = p.get("dates", pd.DataFrame())
21
 
 
22
  records = data_df.to_dict(orient="records") if not data_df.empty else []
23
 
24
+ # Columns to hide in category tables
25
  hidden_cols = {
26
  "key","chartTodayPath","chart30dPath","chart30Path","chart365dPath",
27
  "date365dAgo","date30dAgo","previousDay","oneWeekAgo","oneMonthAgoVal",
28
  "oneWeekAgoVal","oneYearAgoVal","index","indicativeClose"
29
  }
30
 
31
+ # ----------- BASIC TABLE BUILDER -----------
32
  def build_table_from_records(recs, cols=None):
 
33
  if not recs:
34
  return "<p>No data available.</p>"
35
 
 
36
  if cols is None:
 
37
  cols = []
38
  for r in recs:
39
  for k in r.keys():
40
  if k not in cols:
41
  cols.append(k)
42
 
43
+ header = "".join(f"<th>{html.escape(str(c))}</th>" for c in cols)
44
+
45
+ body_rows = []
46
  for r in recs:
47
+ tds = []
48
  for c in cols:
49
  v = r.get(c, "")
 
50
  if isinstance(v, (list, dict)):
51
+ v = str(v)
52
+ tds.append(f"<td>{html.escape('' if v is None else str(v))}</td>")
53
+ body_rows.append("<tr>" + "".join(tds) + "</tr>")
54
+
55
+ return f"""
56
+ <table>
57
+ <thead><tr>{header}</tr></thead>
58
+ <tbody>{''.join(body_rows)}</tbody>
59
+ </table>
60
+ """
61
 
62
+ # ----------- FLEXIBLE CHART BLOCK -----------
63
  def build_chart_grid_for_record(r):
64
  """
65
+ Flexible chart layout: auto-fit, no fixed grid.
66
+ ONLY for INDICES ELIGIBLE IN DERIVATIVES category.
 
67
  """
68
+
69
+ def iframe_if_exists(src, label):
70
  if src and isinstance(src, str) and src.strip():
71
+ return f"""
72
+ <div class="chart-flex-item">
73
+ <iframe src="{html.escape(src)}" loading="lazy"
74
+ frameborder="0" title="{html.escape(label)}"></iframe>
75
+ </div>
76
+ """
77
+ return ""
78
+
79
+ today_src = r.get("chartTodayPath") or r.get("chartToday") or ""
80
+ month30_src = r.get("chart30dPath") or r.get("chart30Path") or ""
81
+ year365_src = r.get("chart365dPath") or r.get("chart365") or ""
82
+
83
+ block = (
84
+ iframe_if_exists(today_src, "Today Chart") +
85
+ iframe_if_exists(month30_src, "30d Chart") +
86
+ iframe_if_exists(year365_src, "365d Chart")
 
 
 
 
 
 
87
  )
 
88
 
89
+ if not block.strip():
90
+ return ""
91
+
92
+ title = r.get("index") or r.get("indexSymbol") or r.get("symbol") or ""
93
+
94
+ return f"""
95
+ <div class="chart-flex-block">
96
+ <div class="chart-title"><strong>{html.escape(str(title))}</strong></div>
97
+ <div class="chart-flex-container">
98
+ {block}
99
+ </div>
100
+ </div>
101
+ """
102
+
103
+ # ----------- MAIN TABLE -----------
104
  main_table_html = build_table_from_records(records)
105
 
106
+ # ----------- DATES TABLE -----------
107
  dates_table_html = ""
108
  if not dates_df.empty:
109
  dates_records = dates_df.to_dict(orient="records")
110
  dates_table_html = build_table_from_records(dates_records)
111
 
112
+ # ----------- GROUP BY KEY ----------
113
  from collections import defaultdict
114
  groups = defaultdict(list)
115
  for r in records:
116
+ groups[r.get("key") or "UNCLASSIFIED"].append(r)
 
117
 
 
118
  per_key_sections = []
119
+
120
+ # ----------- PER CATEGORY SECTIONS ----------
121
  for key_name, recs in groups.items():
122
+
123
+ # Determine visible columns
124
+ first = recs[0]
125
  cols = [c for c in first.keys() if c not in hidden_cols]
126
+
127
+ # Preferred order
128
+ preferred = ["indexSymbol", "index", "symbol", "name"]
129
+ ordered = []
130
+ for pkey in preferred:
131
+ if pkey in cols:
132
+ ordered.append(pkey)
133
  for c in cols:
134
+ if c not in ordered:
135
+ ordered.append(c)
136
+
137
+ table_html = build_table_from_records(recs, ordered)
138
 
139
+ # CHARTS ONLY FOR INDICES ELIGIBLE IN DERIVATIVES
140
+ if str(key_name).strip().upper() == "INDICES ELIGIBLE IN DERIVATIVES":
141
+ charts_html = "\n".join(build_chart_grid_for_record(r) for r in recs)
142
+ else:
143
+ charts_html = "" # no charts for other categories
144
 
145
+ per_key_sections.append(f"""
146
  <section class="key-section">
147
+ <h3>Category: {html.escape(str(key_name))} (Total: {len(recs)})</h3>
148
+ <div class="key-table">{table_html}</div>
149
+ {charts_html}
150
  </section>
151
+ """)
 
152
 
153
+ # ----------- CSS -----------
154
  css = """
155
  <style>
156
+ body { font-family: Arial; padding: 16px; background: #fff; color: #111; }
157
+ table { border-collapse: collapse; width: 100%; margin-bottom: 14px; }
158
+ th, td { border: 1px solid #ccc; padding: 6px 8px; font-size: 13px; }
159
+ th { background: #007bff; color: white; position: sticky; top: 0; }
160
+
161
+ .scroll { max-height: 420px; overflow: auto; padding: 6px; background: #fafafa;
162
+ margin-bottom: 16px; border: 1px solid #ddd; }
163
+
164
+ .key-section {
165
+ border: 1px solid #e6eef6;
166
+ background: #fbfeff;
167
+ border-radius: 6px;
168
+ padding: 10px;
169
+ margin-bottom: 30px;
170
+ }
171
+
172
+ /* FLEXIBLE CHART LAYOUT */
173
+ .chart-flex-block {
174
+ border: 1px solid #ddd;
175
+ background: #fff;
176
+ padding: 8px;
177
+ border-radius: 6px;
178
+ margin-bottom: 14px;
179
+ }
180
+
181
+ .chart-title { margin-bottom: 6px; font-size: 14px; }
182
+
183
+ .chart-flex-container {
184
+ display: flex;
185
+ flex-wrap: wrap;
186
+ gap: 10px;
187
+ }
188
+
189
+ .chart-flex-item {
190
+ flex: 1 1 300px;
191
+ min-height: 180px;
192
+ border: 1px solid #ccc;
193
+ border-radius: 6px;
194
+ overflow: hidden;
195
+ }
196
+
197
+ .chart-flex-item iframe {
198
+ width: 100%;
199
+ height: 100%;
200
+ border: 0;
201
+ }
202
  </style>
203
  """
204
 
205
+ # ----------- FINAL HTML ASSEMBLY -----------
206
+ html_parts = [
207
+ "<!DOCTYPE html>",
208
+ "<html><head><meta charset='utf-8'><title>NSE Indices</title>",
209
+ css,
210
+ "</head><body>",
211
+ "<h1>NSE Indices — Full Static Render</h1>",
212
+ f"<div class='meta'>Generated: {html.escape(pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S'))}</div>",
213
 
214
+ "<h2>Main Indices Table</h2>",
215
+ "<div class='scroll'>", main_table_html, "</div>",
 
 
216
 
217
+ "<h2>Dates / Meta</h2>" if dates_table_html else "",
218
+ "<div class='scroll'>" if dates_table_html else "",
219
+ dates_table_html,
220
+ "</div>" if dates_table_html else "",
 
221
 
222
+ "<h2>Categories</h2>",
223
+ *per_key_sections,
224
 
225
+ "</body></html>"
226
+ ]
227
 
228
+ return "\n".join(str(x) for x in html_parts)