Tesneem commited on
Commit
82469d9
·
verified ·
1 Parent(s): 3a38a75

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -27
app.py CHANGED
@@ -10,6 +10,7 @@ import plotly.graph_objects as go
10
  import streamlit as st
11
  from pymongo import MongoClient
12
  from urllib.parse import quote_plus
 
13
  st.set_page_config(page_title="Student Skill Radar", layout="wide")
14
 
15
  # ------------------- Constants -------------------
@@ -123,31 +124,44 @@ def plot_radar(df: pd.DataFrame, grouped: bool, title: str):
123
  return fig
124
 
125
 
126
- # ------------------- Mongo Access -------------------
127
- @st.cache_data(show_spinner=False)
128
- def _client(uri: str):
129
- return MongoClient(uri, serverSelectionTimeoutMS=10000)
130
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- def get_mongo_uri(db_name: str | None = None) -> str | None:
133
- user = os.getenv("MONGO_USER")
134
- pw = os.getenv("MONGO_PASS")
135
- cluster = os.getenv("MONGO_CLUSTER")
136
- if user and pw and cluster:
137
- user_q = quote_plus(user)
138
- pw_q = quote_plus(pw)
139
- db_path = f"/{db_name}" if db_name else ""
140
- # TLS flags help on Spaces; SRV requires dnspython
141
- return (
142
- f"mongodb+srv://{user_q}:{pw_q}@{cluster}{db_path}"
143
- f"?retryWrites=true&w=majority&tls=true&tlsAllowInvalidCertificates=true"
144
- )
145
- return None
146
 
 
 
 
 
147
 
148
 
149
  @st.cache_data(show_spinner=False)
150
  def mongo_distinct(uri: str, db: str, coll: str, field: str) -> List[str]:
 
 
151
  try:
152
  c = _client(uri)
153
  vals = c[db][coll].distinct(field)
@@ -157,7 +171,17 @@ def mongo_distinct(uri: str, db: str, coll: str, field: str) -> List[str]:
157
 
158
 
159
  @st.cache_data(show_spinner=False)
160
- def mongo_records(uri: str, db: str, coll: str, student: str | None, source: str | None, start: str | None, end: str | None) -> List[dict]:
 
 
 
 
 
 
 
 
 
 
161
  q = {}
162
  if student and student != "(All)":
163
  q["student"] = student
@@ -183,19 +207,24 @@ def mongo_records(uri: str, db: str, coll: str, student: str | None, source: str
183
 
184
 
185
  # ------------------- UI -------------------
186
- st.title("📊 Student Skill Radar — MongoDB only")
187
 
188
  with st.sidebar:
189
  st.subheader("MongoDB Settings")
190
  db_name = st.text_input("Database name", value="student_skills")
191
  coll_name = st.text_input("Collection name", value="responses_IFE_2025")
192
 
193
- # URI handling
194
- detected_uri = get_mongo_uri(db_name)
195
- uri_override = st.text_input("Override MONGO_URI (optional)", type="password")
196
- mongo_uri = uri_override.strip() or (detected_uri or "")
197
  if not mongo_uri:
198
- st.warning("No Mongo URI found. Set MONGO_URI (or MONGO_USER/PASS/CLUSTER) in Space secrets, or paste an override.")
 
 
 
 
 
 
199
 
200
  # Filters
201
  students = ["(All)"] + (mongo_distinct(mongo_uri, db_name, coll_name, "student") if mongo_uri else [])
@@ -218,7 +247,6 @@ end_str = end_dt.strftime("%Y-%m-%d") if isinstance(end_dt, date) else None
218
 
219
  # Fetch + aggregate
220
  records = mongo_records(mongo_uri, db_name, coll_name, student_choice, source_choice, start_str, end_str) if mongo_uri else []
221
-
222
  df = summarize(records, level=agg_level) if records else pd.DataFrame()
223
 
224
  # ------------------- Output -------------------
@@ -237,6 +265,7 @@ with right:
237
  csv = df.to_csv(index=False).encode("utf-8")
238
  st.download_button("Download CSV", data=csv, file_name="skill_scores.csv", mime="text/csv")
239
 
 
240
  # # app.py
241
  # import os
242
  # import json
 
10
  import streamlit as st
11
  from pymongo import MongoClient
12
  from urllib.parse import quote_plus
13
+
14
  st.set_page_config(page_title="Student Skill Radar", layout="wide")
15
 
16
  # ------------------- Constants -------------------
 
124
  return fig
125
 
126
 
127
+ # ------------------- Mongo Access (secrets-only) -------------------
128
+ def _get_secret(name: str) -> str | None:
129
+ # Prefer Streamlit secrets, fallback to env vars
130
+ try:
131
+ val = st.secrets.get(name)
132
+ if val is not None:
133
+ return str(val)
134
+ except Exception:
135
+ pass
136
+ return os.getenv(name)
137
+
138
+
139
+ def _build_uri(db_name: str | None) -> str | None:
140
+ user = _get_secret("MONGO_USER")
141
+ pw = _get_secret("MONGO_PASS")
142
+ cluster = _get_secret("MONGO_CLUSTER")
143
+ if not (user and pw and cluster):
144
+ return None
145
+ user_q = quote_plus(user)
146
+ pw_q = quote_plus(pw)
147
+ db_path = f"/{db_name}" if db_name else ""
148
+ # TLS flags help on some hosts; SRV requires dnspython (present on Streamlit Cloud)
149
+ return (
150
+ f"mongodb+srv://{user_q}:{pw_q}@{cluster}{db_path}"
151
+ f"?retryWrites=true&w=majority&tls=true&tlsAllowInvalidCertificates=true"
152
+ )
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ @st.cache_resource(show_spinner=False)
156
+ def _client(uri: str):
157
+ # Use a cached client resource (not cache_data) for connections
158
+ return MongoClient(uri, serverSelectionTimeoutMS=10000)
159
 
160
 
161
  @st.cache_data(show_spinner=False)
162
  def mongo_distinct(uri: str, db: str, coll: str, field: str) -> List[str]:
163
+ if not uri:
164
+ return []
165
  try:
166
  c = _client(uri)
167
  vals = c[db][coll].distinct(field)
 
171
 
172
 
173
  @st.cache_data(show_spinner=False)
174
+ def mongo_records(
175
+ uri: str,
176
+ db: str,
177
+ coll: str,
178
+ student: str | None,
179
+ source: str | None,
180
+ start: str | None,
181
+ end: str | None,
182
+ ) -> List[dict]:
183
+ if not uri:
184
+ return []
185
  q = {}
186
  if student and student != "(All)":
187
  q["student"] = student
 
207
 
208
 
209
  # ------------------- UI -------------------
210
+ st.title("📊 Student Skill Radar — MongoDB (secrets-based)")
211
 
212
  with st.sidebar:
213
  st.subheader("MongoDB Settings")
214
  db_name = st.text_input("Database name", value="student_skills")
215
  coll_name = st.text_input("Collection name", value="responses_IFE_2025")
216
 
217
+ # Build from MONGO_USER / MONGO_PASS / MONGO_CLUSTER only
218
+ mongo_uri = _build_uri(db_name)
219
+
 
220
  if not mongo_uri:
221
+ st.warning("Missing MONGO_USER, MONGO_PASS, or MONGO_CLUSTER in secrets/env.")
222
+ else:
223
+ try:
224
+ _client(mongo_uri).admin.command("ping")
225
+ st.success("Connected via secrets ✅")
226
+ except Exception as e:
227
+ st.error(f"Mongo connection failed: {e}")
228
 
229
  # Filters
230
  students = ["(All)"] + (mongo_distinct(mongo_uri, db_name, coll_name, "student") if mongo_uri else [])
 
247
 
248
  # Fetch + aggregate
249
  records = mongo_records(mongo_uri, db_name, coll_name, student_choice, source_choice, start_str, end_str) if mongo_uri else []
 
250
  df = summarize(records, level=agg_level) if records else pd.DataFrame()
251
 
252
  # ------------------- Output -------------------
 
265
  csv = df.to_csv(index=False).encode("utf-8")
266
  st.download_button("Download CSV", data=csv, file_name="skill_scores.csv", mime="text/csv")
267
 
268
+
269
  # # app.py
270
  # import os
271
  # import json