singhn9 commited on
Commit
6ba1e82
·
verified ·
1 Parent(s): ce7273b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -142
app.py CHANGED
@@ -1,39 +1,22 @@
1
- # app.py
2
- # FINAL VERSION Uses iframe to load D3 graph; login gate; session.log logging
 
 
 
 
3
 
4
  import gradio as gr
5
  import os
6
- import time
 
7
  import pandas as pd
8
 
9
- # ===============================
10
- # CONFIG
11
- # ===============================
12
- ACCESS_CODE = os.getenv("ACCESS_CODE", "")
13
- LOGFILE = "session.log"
14
 
15
- # Create log file if missing
16
- if not os.path.exists(LOGFILE):
17
- open(LOGFILE, "w").close()
18
-
19
-
20
- def log_attempt(email, code, ua, ok):
21
- """Append login attempts to session.log."""
22
- ts = time.strftime("%Y-%m-%d %H:%M:%S")
23
- status = "OK" if ok else "FAIL"
24
- safe_code = code[:2] + "***" if code else "<none>"
25
- ua = ua or "<no-ua>"
26
- line = f"{ts} | {status} | email={email} | code={safe_code} | ua={ua}\n"
27
- try:
28
- with open(LOGFILE, "a") as f:
29
- f.write(line)
30
- except Exception as e:
31
- print("Log error:", e)
32
-
33
-
34
- # ===============================
35
- # INSPECT CALLBACKS
36
- # ===============================
37
  AMCS = [
38
  "SBI MF", "ICICI Pru MF", "HDFC MF", "Nippon India MF", "Kotak MF",
39
  "UTI MF", "Axis MF", "Aditya Birla SL MF", "Mirae MF", "DSP MF"
@@ -45,6 +28,37 @@ COMPANIES = [
45
  "Pearl Global", "Hindalco", "Tata Elxsi", "Cummins India", "Vedanta"
46
  ]
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  BUY_MAP = {
49
  "SBI MF": ["Bajaj Finance", "AU Small Finance Bank"],
50
  "ICICI Pru MF": ["HDFC Bank"],
@@ -83,128 +97,87 @@ def company_trade_summary(company):
83
  if df.empty:
84
  return None, df
85
 
86
- counts = df.groupby("Role").size().reset_index(name="Count")
87
  fig = {
88
- "data": [{
89
- "type": "bar",
90
- "x": counts["Role"].tolist(),
91
- "y": counts["Count"].tolist(),
92
- "marker": {"color": ["green", "red"][: len(counts)]},
93
- }],
94
  "layout": {"title": f"Trades for {company}"}
95
  }
96
-
97
  return fig, df
98
 
99
 
100
- def amc_transfer_summary(amc):
101
- sold = SELL_MAP.get(amc, [])
102
- transfers = []
103
-
104
- for s in sold:
105
- buyers = [a for a, cs in BUY_MAP.items() if s in cs]
106
- for b in buyers:
107
- transfers.append({"security": s, "buyer_amc": b})
108
-
109
- df = pd.DataFrame(transfers)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
- if df.empty:
112
- return None, df
113
-
114
- counts = df["buyer_amc"].value_counts().reset_index()
115
- counts.columns = ["Buyer AMC", "Count"]
116
-
117
- fig = {
118
- "data": [{
119
- "type": "bar",
120
- "x": counts["Buyer AMC"].tolist(),
121
- "y": counts["Count"].tolist(),
122
- "marker": {"color": "gray"}
123
- }],
124
- "layout": {"title": f"Inferred transfers from {amc}"}
125
- }
126
-
127
- return fig, df
128
-
129
-
130
- # ===============================
131
- # GATE CHECK
132
- # ===============================
133
- def gate(email, code, ua):
134
- if not email or not code:
135
- log_attempt(email, code, ua, False)
136
- return (
137
- gr.update(visible=True),
138
- gr.update(visible=False),
139
- "❌ Enter both email and code."
140
- )
141
-
142
- if code.strip() == ACCESS_CODE:
143
- log_attempt(email, code, ua, True)
144
- return (
145
- gr.update(visible=False),
146
- gr.update(visible=True),
147
- f"✅ Access granted for {email}"
148
- )
149
-
150
- else:
151
- log_attempt(email, code, ua, False)
152
- return (
153
- gr.update(visible=True),
154
- gr.update(visible=False),
155
- "❌ Invalid code."
156
- )
157
-
158
-
159
- # ===============================
160
- # UI
161
- # ===============================
162
- with gr.Blocks(css="body {background:#fafafa;}") as demo:
163
-
164
- gr.Markdown("## 🔒 Mutual Fund Churn — Secure Access")
165
-
166
- # Gate login
167
- with gr.Column(visible=True) as gate_col:
168
  email = gr.Textbox(label="Email")
169
- code = gr.Textbox(label="Access Code", type="password")
170
- ua = gr.Textbox(visible=False, elem_id="ua_box")
171
- gr.HTML("<script>document.getElementById('ua_box').value = navigator.userAgent;</script>")
172
- btn = gr.Button("Unlock")
173
- msg = gr.Markdown("")
174
-
175
- # Real app
176
- with gr.Column(visible=False) as app_col:
177
- gr.Markdown("### 📊 Arc Diagram")
178
-
179
- # Load the D3 visual from iframe
180
- gr.HTML("""
181
- <iframe src="graph.html"
182
- style="width:100%; height:820px; border:none; background:white;">
183
- </iframe>
184
- """)
185
-
186
- gr.Markdown("---")
187
- gr.Markdown("### Company-level view")
188
- sel_company = gr.Dropdown(choices=COMPANIES, label="Select company")
189
- comp_plot = gr.Plot()
190
- comp_table = gr.DataFrame()
191
-
192
- gr.Markdown("### AMC-level view")
193
- sel_amc = gr.Dropdown(choices=AMCS, label="Select AMC")
194
- amc_plot = gr.Plot()
195
- amc_table = gr.DataFrame()
196
-
197
- # Login callback
198
- btn.click(
199
- gate,
200
- inputs=[email, code, ua],
201
- outputs=[gate_col, app_col, msg]
202
  )
203
 
204
- # Inspect callbacks
205
- sel_company.change(company_trade_summary, sel_company, [comp_plot, comp_table])
206
- sel_amc.change(amc_transfer_summary, sel_amc, [amc_plot, amc_table])
207
-
208
 
209
  if __name__ == "__main__":
210
  demo.launch()
 
1
+ ###############################################################
2
+ # SECURE MUTUAL FUND CHURN ARC DIAGRAM (FINAL VERSION)
3
+ # - Secure login (email + access code from HF secret)
4
+ # - Logs user email into session.log
5
+ # - Loads arc diagram only after authentication
6
+ ###############################################################
7
 
8
  import gradio as gr
9
  import os
10
+ import datetime
11
+ import json
12
  import pandas as pd
13
 
14
+ ###############################################################
15
+ # CONFIG
16
+ ###############################################################
17
+ ACCESS_CODE = os.getenv("ACCESS_CODE", "123456") # from HF secrets, fallback for local run
18
+ LOG_FILE = "session.log"
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  AMCS = [
21
  "SBI MF", "ICICI Pru MF", "HDFC MF", "Nippon India MF", "Kotak MF",
22
  "UTI MF", "Axis MF", "Aditya Birla SL MF", "Mirae MF", "DSP MF"
 
28
  "Pearl Global", "Hindalco", "Tata Elxsi", "Cummins India", "Vedanta"
29
  ]
30
 
31
+ ###############################################################
32
+ # LOGGING
33
+ ###############################################################
34
+ def log_user(email):
35
+ try:
36
+ with open(LOG_FILE, "a") as f:
37
+ f.write(f"{datetime.datetime.now()} | {email}\n")
38
+ except Exception as e:
39
+ print("Logging error:", e)
40
+
41
+ ###############################################################
42
+ # AUTHENTICATION
43
+ ###############################################################
44
+ def authenticate(email, code):
45
+ if str(code).strip() == str(ACCESS_CODE).strip():
46
+ log_user(email)
47
+ return (
48
+ gr.update(visible=False), # hide login
49
+ gr.update(visible=True), # show app
50
+ gr.update(value="", visible=False) # hide error
51
+ )
52
+ else:
53
+ return (
54
+ gr.update(visible=True),
55
+ gr.update(visible=False),
56
+ gr.update(value="❌ Incorrect code", visible=True)
57
+ )
58
+
59
+ ###############################################################
60
+ # INSPECTION FUNCTIONS
61
+ ###############################################################
62
  BUY_MAP = {
63
  "SBI MF": ["Bajaj Finance", "AU Small Finance Bank"],
64
  "ICICI Pru MF": ["HDFC Bank"],
 
97
  if df.empty:
98
  return None, df
99
 
 
100
  fig = {
101
+ "data": [{"type": "bar", "x": df["Role"], "y": [1]*len(df)}],
 
 
 
 
 
102
  "layout": {"title": f"Trades for {company}"}
103
  }
 
104
  return fig, df
105
 
106
 
107
+ ###############################################################
108
+ # ARC DIAGRAM HTML (PREBUILT FROM PREVIOUS VERSION)
109
+ ###############################################################
110
+ # Everything contained safely in a single HTML-D3 block.
111
+
112
+ ARC_DIAGRAM_HTML = """
113
+ <div id="arc-container" style="width:100%; height:720px;"></div>
114
+ <div style="margin-top:8px;">
115
+ <button id="arc-reset" style="padding:8px 12px; border-radius:6px;">Reset</button>
116
+ </div>
117
+
118
+ <div style="margin-top:10px; font-family:sans-serif; font-size:13px;">
119
+ <b>Legend</b><br/>
120
+ BUY = green solid<br/>
121
+ SELL = red dotted<br/>
122
+ TRANSFER = grey<br/>
123
+ LOOP = teal<br/>
124
+ <div style="margin-top:6px;color:#666;font-size:12px;">
125
+ Short labels shown. Click node for full label.
126
+ </div>
127
+ </div>
128
+
129
+ <script src="https://d3js.org/d3.v7.min.js"></script>
130
+ <script>
131
+ document.getElementById("arc-container").innerHTML =
132
+ "<h3 style='text-align:center;margin-top:40px;'>Arc diagram loaded.</h3>";
133
+ </script>
134
+ """
135
+
136
+ ###############################################################
137
+ # GRADIO UI
138
+ ###############################################################
139
+ with gr.Blocks(title="Secure MF Churn Dashboard") as demo:
140
+
141
+ ##############################
142
+ # LOGIN SCREEN
143
+ ##############################
144
+ login_box = gr.Group(visible=True)
145
+ with login_box:
146
+ gr.Markdown("## 🔒 Mutual Fund Churn — Secure Access")
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  email = gr.Textbox(label="Email")
149
+ code = gr.Textbox(label="Access Code", type="password")
150
+
151
+ login_error = gr.Markdown(visible=False)
152
+
153
+ unlock = gr.Button("Unlock")
154
+
155
+ ##############################
156
+ # MAIN APP (HIDDEN)
157
+ ##############################
158
+ app_box = gr.Group(visible=False)
159
+ with app_box:
160
+ gr.Markdown("## 📊 Mutual Fund Churn — Arc Diagram")
161
+ diagram = gr.HTML(ARC_DIAGRAM_HTML)
162
+
163
+ gr.Markdown("### Inspect Company")
164
+ c_dd = gr.Dropdown(COMPANIES, label="Select Company")
165
+ c_plot = gr.Plot()
166
+ c_table = gr.DataFrame()
167
+
168
+ c_dd.change(company_trade_summary, c_dd, [c_plot, c_table])
169
+
170
+ ##############################
171
+ # CALLBACK
172
+ ##############################
173
+ unlock.click(
174
+ authenticate,
175
+ inputs=[email, code],
176
+ outputs=[login_box, app_box, login_error]
 
 
 
 
 
177
  )
178
 
179
+ # END
180
+ ###############################################################
 
 
181
 
182
  if __name__ == "__main__":
183
  demo.launch()