gkdivya commited on
Commit
ccb7521
·
verified ·
1 Parent(s): 72d160b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -43
app.py CHANGED
@@ -2,129 +2,211 @@
2
  import os
3
  import pandas as pd
4
  import gradio as gr
 
5
 
6
- # Import search & admin modules (searchschool.py unchanged)
 
 
7
  from searchschool import (
8
- STATE_HF_FILES,
9
  DEFAULT_STATE_KEY,
10
- on_search_web,
11
  load_master_for_state,
12
  update_blocks,
13
  search_candidates,
14
  )
 
15
  from admin_patterns import (
16
  load_pattern_config,
17
  load_global_patterns_for_editor,
18
  load_state_patterns_for_editor,
19
  save_global_patterns_from_editor,
20
- save_state_patterns_from_editor,
21
- refresh_pattern_config,
22
- show_patterns_file_info,
23
  )
24
 
25
- # Admin password from environment (set as HF Space secret ADMIN_PASSWORD)
 
 
 
 
 
 
 
 
 
26
  ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", None)
27
  if not ADMIN_PASSWORD:
28
- print("⚠ ADMIN_PASSWORD environment variable not set. Set ADMIN_PASSWORD secret in HF Space settings.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
 
 
 
 
 
30
  with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
31
  gr.Markdown(
32
  """
33
  # State School Fuzzy Matcher (RapidFuzz)
34
 
35
  - Public: Search tab
36
- - Admin: Patterns editor (hidden until unlocked with admin password)
37
  """
38
  )
39
 
40
- # ----- SEARCH TAB -----
41
  with gr.Tab("Search"):
42
  with gr.Row():
43
  state_dd = gr.Dropdown(
44
  label="State",
45
- choices=list(STATE_HF_FILES.keys()),
46
- value=DEFAULT_STATE_KEY if DEFAULT_STATE_KEY in STATE_HF_FILES else None,
47
  interactive=True,
48
  )
 
49
  with gr.Row():
50
  district_dd = gr.Dropdown(label="District", choices=[], value=None, interactive=True)
51
  block_dd = gr.Dropdown(label="Block", choices=[], value=None, interactive=True)
52
 
53
- school_input = gr.Textbox(label="Input School Name", placeholder="Type school name from marksheet...")
 
 
 
 
54
  search_btn = gr.Button("Find Candidates")
55
 
56
  gr.Markdown("### Candidates (top matches)")
57
  candidates_table = gr.Dataframe(
58
  headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
59
  datatype=["str", "str", "str", "str", "str", "number"],
60
- interactive=False
61
  )
62
 
63
  gr.Markdown("### Best Candidate")
64
  best_table = gr.Dataframe(
65
  headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
66
  datatype=["str", "str", "str", "str", "str", "number"],
67
- interactive=False
68
  )
69
 
70
- # ----- ADMIN TAB (hidden until unlock) -----
71
  with gr.Tab("Admin"):
72
- gr.Markdown("### Admin — Patterns (enter password to unlock editor)")
73
 
74
- # Unlock area (visible by default)
75
- unlock_pwd = gr.Textbox(label="Admin Password", type="password", placeholder="Enter admin password and click Unlock")
 
 
 
76
  unlock_btn = gr.Button("Unlock Admin Panel")
77
  unlock_status = gr.Markdown("")
78
 
79
- # Admin editors wrapped inside a Column that starts hidden
80
  admin_panel = gr.Column(visible=False)
81
 
82
  with admin_panel:
83
- # Global patterns editor (loaded fresh)
84
  global_df = gr.Dataframe(
85
  value=load_global_patterns_for_editor(),
86
  headers=["pattern", "replacement"],
87
  datatype=["str", "str"],
88
  interactive=True,
89
- row_count=(len(load_pattern_config().get("global", [])) or 1),
90
  )
 
91
  save_global_btn = gr.Button("💾 Save Global Patterns")
92
  global_status = gr.Markdown("")
93
 
94
- # State specific editor
95
  existing_state_keys = sorted(load_pattern_config().get("states", {}).keys())
 
96
  with gr.Row():
97
- state_pattern_dd = gr.Dropdown(label="Existing state key", choices=existing_state_keys, value=existing_state_keys[0] if existing_state_keys else None, interactive=True)
98
- new_state_tb = gr.Textbox(label="Or type new state key", placeholder="e.g. KARNATAKA")
99
- state_df = gr.Dataframe(value=pd.DataFrame(columns=["pattern", "replacement"]), headers=["pattern", "replacement"], datatype=["str", "str"], interactive=True, row_count=3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  load_state_btn = gr.Button("Load patterns for selected / new state")
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- # -------- Wiring: Search --------
104
- state_dd.change(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
105
- demo.load(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
106
- district_dd.change(fn=update_blocks, inputs=district_dd, outputs=block_dd)
107
- search_btn.click(fn=search_candidates, inputs=[school_input, state_dd, district_dd, block_dd], outputs=[candidates_table, best_table])
108
 
109
- # -------- Wiring: Admin gating --------
110
  def try_unlock(pwd: str):
111
  if ADMIN_PASSWORD is None:
112
- return gr.update(visible=False), "❌ ADMIN_PASSWORD not configured in environment", None
113
  if pwd == ADMIN_PASSWORD:
114
  return gr.update(visible=True), "🔓 Admin panel unlocked.", True
115
- else:
116
- return gr.update(visible=False), "❌ Wrong password.", False
117
 
118
- unlock_btn.click(fn=try_unlock, inputs=unlock_pwd, outputs=[admin_panel, unlock_status, unlock_pwd])
 
 
 
 
119
 
120
- # -------- Wiring: Admin actions (inside admin_panel) --------
121
- # Save global (server still checks password inside save function)
122
- save_global_btn.click(fn=lambda df, pwd: save_global_patterns_from_editor(df, pwd, ADMIN_PASSWORD),
123
- inputs=[global_df, unlock_pwd],
124
- outputs=global_status)
125
 
126
- # Load state patterns into editor (view-only)
127
- load_state_btn.click(fn=load_state_patterns_for_editor, inputs=[state_pattern_dd, new_state_tb], outputs=state_df)
 
 
 
128
 
129
 
130
  if __name__ == "__main__":
 
2
  import os
3
  import pandas as pd
4
  import gradio as gr
5
+ from huggingface_hub import hf_hub_download
6
 
7
+ # ----------------------------------------------------
8
+ # Import search & admin modules
9
+ # ----------------------------------------------------
10
  from searchschool import (
 
11
  DEFAULT_STATE_KEY,
 
12
  load_master_for_state,
13
  update_blocks,
14
  search_candidates,
15
  )
16
+
17
  from admin_patterns import (
18
  load_pattern_config,
19
  load_global_patterns_for_editor,
20
  load_state_patterns_for_editor,
21
  save_global_patterns_from_editor,
 
 
 
22
  )
23
 
24
+ # ----------------------------------------------------
25
+ # CONFIG
26
+ # ----------------------------------------------------
27
+ HF_SCHOOLS_DATASET = "Apf-AI4Good/Schools"
28
+ MASTER_ALL_STATES_FILE = "master_all_states.csv"
29
+ MASTER_STATE_COL = "School_State__c"
30
+
31
+ # ----------------------------------------------------
32
+ # Load ADMIN password
33
+ # ----------------------------------------------------
34
  ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", None)
35
  if not ADMIN_PASSWORD:
36
+ print("⚠ ADMIN_PASSWORD environment variable not set.")
37
+
38
+ # ----------------------------------------------------
39
+ # 🔹 LOAD STATE LIST ONCE (APP STARTUP)
40
+ # ----------------------------------------------------
41
+ def load_state_choices_once():
42
+ path = hf_hub_download(
43
+ repo_id=HF_SCHOOLS_DATASET,
44
+ repo_type="dataset",
45
+ filename=MASTER_ALL_STATES_FILE,
46
+ )
47
+
48
+ df = pd.read_csv(path, dtype=str)
49
+
50
+ states = (
51
+ df[MASTER_STATE_COL]
52
+ .dropna()
53
+ .str.upper()
54
+ .unique()
55
+ .tolist()
56
+ )
57
+
58
+ return sorted(states)
59
+
60
 
61
+ STATE_CHOICES = load_state_choices_once()
62
+
63
+ # ----------------------------------------------------
64
+ # Gradio App
65
+ # ----------------------------------------------------
66
  with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
67
  gr.Markdown(
68
  """
69
  # State School Fuzzy Matcher (RapidFuzz)
70
 
71
  - Public: Search tab
72
+ - Admin: Patterns editor (password protected)
73
  """
74
  )
75
 
76
+ # ================= SEARCH TAB =================
77
  with gr.Tab("Search"):
78
  with gr.Row():
79
  state_dd = gr.Dropdown(
80
  label="State",
81
+ choices=STATE_CHOICES,
82
+ value=DEFAULT_STATE_KEY if DEFAULT_STATE_KEY in STATE_CHOICES else None,
83
  interactive=True,
84
  )
85
+
86
  with gr.Row():
87
  district_dd = gr.Dropdown(label="District", choices=[], value=None, interactive=True)
88
  block_dd = gr.Dropdown(label="Block", choices=[], value=None, interactive=True)
89
 
90
+ school_input = gr.Textbox(
91
+ label="Input School Name",
92
+ placeholder="Type school name from marksheet..."
93
+ )
94
+
95
  search_btn = gr.Button("Find Candidates")
96
 
97
  gr.Markdown("### Candidates (top matches)")
98
  candidates_table = gr.Dataframe(
99
  headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
100
  datatype=["str", "str", "str", "str", "str", "number"],
101
+ interactive=False,
102
  )
103
 
104
  gr.Markdown("### Best Candidate")
105
  best_table = gr.Dataframe(
106
  headers=["School_Name", "State", "District", "Block", "UDISE_Code", "Score"],
107
  datatype=["str", "str", "str", "str", "str", "number"],
108
+ interactive=False,
109
  )
110
 
111
+ # ================= ADMIN TAB =================
112
  with gr.Tab("Admin"):
113
+ gr.Markdown("### Admin — Patterns Editor")
114
 
115
+ unlock_pwd = gr.Textbox(
116
+ label="Admin Password",
117
+ type="password",
118
+ placeholder="Enter admin password and click Unlock",
119
+ )
120
  unlock_btn = gr.Button("Unlock Admin Panel")
121
  unlock_status = gr.Markdown("")
122
 
 
123
  admin_panel = gr.Column(visible=False)
124
 
125
  with admin_panel:
 
126
  global_df = gr.Dataframe(
127
  value=load_global_patterns_for_editor(),
128
  headers=["pattern", "replacement"],
129
  datatype=["str", "str"],
130
  interactive=True,
131
+ row_count=5,
132
  )
133
+
134
  save_global_btn = gr.Button("💾 Save Global Patterns")
135
  global_status = gr.Markdown("")
136
 
 
137
  existing_state_keys = sorted(load_pattern_config().get("states", {}).keys())
138
+
139
  with gr.Row():
140
+ state_pattern_dd = gr.Dropdown(
141
+ label="Existing state key",
142
+ choices=existing_state_keys,
143
+ value=existing_state_keys[0] if existing_state_keys else None,
144
+ )
145
+ new_state_tb = gr.Textbox(
146
+ label="Or type new state key",
147
+ placeholder="e.g. KARNATAKA",
148
+ )
149
+
150
+ state_df = gr.Dataframe(
151
+ value=pd.DataFrame(columns=["pattern", "replacement"]),
152
+ headers=["pattern", "replacement"],
153
+ datatype=["str", "str"],
154
+ interactive=True,
155
+ row_count=3,
156
+ )
157
+
158
  load_state_btn = gr.Button("Load patterns for selected / new state")
159
 
160
+ # ================= Wiring =================
161
+ state_dd.change(
162
+ fn=load_master_for_state,
163
+ inputs=state_dd,
164
+ outputs=[district_dd, block_dd],
165
+ )
166
+
167
+ demo.load(
168
+ fn=load_master_for_state,
169
+ inputs=state_dd,
170
+ outputs=[district_dd, block_dd],
171
+ )
172
+
173
+ district_dd.change(
174
+ fn=update_blocks,
175
+ inputs=district_dd,
176
+ outputs=block_dd,
177
+ )
178
 
179
+ search_btn.click(
180
+ fn=search_candidates,
181
+ inputs=[school_input, state_dd, district_dd, block_dd],
182
+ outputs=[candidates_table, best_table],
183
+ )
184
 
185
+ # ---------------- Admin gating ----------------
186
  def try_unlock(pwd: str):
187
  if ADMIN_PASSWORD is None:
188
+ return gr.update(visible=False), "❌ ADMIN_PASSWORD not configured", None
189
  if pwd == ADMIN_PASSWORD:
190
  return gr.update(visible=True), "🔓 Admin panel unlocked.", True
191
+ return gr.update(visible=False), "❌ Wrong password.", False
 
192
 
193
+ unlock_btn.click(
194
+ fn=try_unlock,
195
+ inputs=unlock_pwd,
196
+ outputs=[admin_panel, unlock_status, unlock_pwd],
197
+ )
198
 
199
+ save_global_btn.click(
200
+ fn=lambda df, pwd: save_global_patterns_from_editor(df, pwd, ADMIN_PASSWORD),
201
+ inputs=[global_df, unlock_pwd],
202
+ outputs=global_status,
203
+ )
204
 
205
+ load_state_btn.click(
206
+ fn=load_state_patterns_for_editor,
207
+ inputs=[state_pattern_dd, new_state_tb],
208
+ outputs=state_df,
209
+ )
210
 
211
 
212
  if __name__ == "__main__":