Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,14 +3,13 @@ import os
|
|
| 3 |
import pandas as pd
|
| 4 |
import gradio as gr
|
| 5 |
|
| 6 |
-
# Import
|
| 7 |
from searchschool import (
|
| 8 |
STATE_HF_FILES,
|
| 9 |
DEFAULT_STATE_KEY,
|
| 10 |
load_master_for_state,
|
| 11 |
update_blocks,
|
| 12 |
search_candidates,
|
| 13 |
-
MASTER_SCHOOL_COL,
|
| 14 |
)
|
| 15 |
from admin_patterns import (
|
| 16 |
load_pattern_config,
|
|
@@ -27,11 +26,13 @@ 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 |
-
|
| 31 |
-
with gr.Blocks(title="State School Fuzzy Matcher (modular)") as demo:
|
| 32 |
gr.Markdown(
|
| 33 |
"""
|
| 34 |
# State School Fuzzy Matcher (RapidFuzz)
|
|
|
|
|
|
|
|
|
|
| 35 |
"""
|
| 36 |
)
|
| 37 |
|
|
@@ -65,51 +66,90 @@ with gr.Blocks(title="State School Fuzzy Matcher (modular)") as demo:
|
|
| 65 |
interactive=False
|
| 66 |
)
|
| 67 |
|
| 68 |
-
# ----- ADMIN TAB -----
|
| 69 |
with gr.Tab("Admin"):
|
| 70 |
-
gr.Markdown("### Admin β Patterns (password
|
| 71 |
-
admin_pwd = gr.Textbox(label="Admin Password", type="password", placeholder="Enter admin password to save changes")
|
| 72 |
-
|
| 73 |
-
# Global patterns editor (load fresh)
|
| 74 |
-
global_df = gr.Dataframe(
|
| 75 |
-
value=load_global_patterns_for_editor(),
|
| 76 |
-
headers=["pattern", "replacement"],
|
| 77 |
-
datatype=["str", "str"],
|
| 78 |
-
interactive=True,
|
| 79 |
-
row_count=(len(load_pattern_config().get("global", [])) or 1),
|
| 80 |
-
)
|
| 81 |
-
save_global_btn = gr.Button("πΎ Save Global Patterns")
|
| 82 |
-
global_status = gr.Markdown("")
|
| 83 |
|
| 84 |
-
#
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
state_dd.change(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
|
| 102 |
demo.load(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
|
| 103 |
district_dd.change(fn=update_blocks, inputs=district_dd, outputs=block_dd)
|
| 104 |
search_btn.click(fn=search_candidates, inputs=[school_input, state_dd, district_dd, block_dd], outputs=[candidates_table, best_table])
|
| 105 |
|
| 106 |
-
#
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
load_state_btn.click(fn=load_state_patterns_for_editor, inputs=[state_pattern_dd, new_state_tb], outputs=state_df)
|
| 109 |
-
save_state_btn.click(fn=lambda state_sel, new_state, df, pwd: save_state_patterns_from_editor(state_sel, new_state, df, pwd, ADMIN_PASSWORD), inputs=[state_pattern_dd, new_state_tb, state_df, admin_pwd], outputs=state_status)
|
| 110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
refresh_btn.click(fn=refresh_pattern_config, inputs=None, outputs=refresh_status)
|
| 112 |
show_file_btn.click(fn=show_patterns_file_info, inputs=None, outputs=debug_info_md)
|
| 113 |
|
|
|
|
| 114 |
if __name__ == "__main__":
|
| 115 |
demo.launch()
|
|
|
|
| 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 |
load_master_for_state,
|
| 11 |
update_blocks,
|
| 12 |
search_candidates,
|
|
|
|
| 13 |
)
|
| 14 |
from admin_patterns import (
|
| 15 |
load_pattern_config,
|
|
|
|
| 26 |
if not ADMIN_PASSWORD:
|
| 27 |
print("β ADMIN_PASSWORD environment variable not set. Set ADMIN_PASSWORD secret in HF Space settings.")
|
| 28 |
|
| 29 |
+
with gr.Blocks(title="State School Fuzzy Matcher (with gated Admin)") as demo:
|
|
|
|
| 30 |
gr.Markdown(
|
| 31 |
"""
|
| 32 |
# State School Fuzzy Matcher (RapidFuzz)
|
| 33 |
+
|
| 34 |
+
- Public: Search tab
|
| 35 |
+
- Admin: Patterns editor (hidden until unlocked with admin password)
|
| 36 |
"""
|
| 37 |
)
|
| 38 |
|
|
|
|
| 66 |
interactive=False
|
| 67 |
)
|
| 68 |
|
| 69 |
+
# ----- ADMIN TAB (hidden until unlock) -----
|
| 70 |
with gr.Tab("Admin"):
|
| 71 |
+
gr.Markdown("### Admin β Patterns (enter password to unlock editor)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
+
# Unlock area (visible by default)
|
| 74 |
+
unlock_pwd = gr.Textbox(label="Admin Password", type="password", placeholder="Enter admin password and click Unlock")
|
| 75 |
+
unlock_btn = gr.Button("Unlock Admin Panel")
|
| 76 |
+
unlock_status = gr.Markdown("")
|
| 77 |
+
|
| 78 |
+
# Admin editors wrapped inside a Column that starts hidden
|
| 79 |
+
admin_panel = gr.Column(visible=False)
|
| 80 |
+
|
| 81 |
+
with admin_panel:
|
| 82 |
+
# Global patterns editor (loaded fresh)
|
| 83 |
+
global_df = gr.Dataframe(
|
| 84 |
+
value=load_global_patterns_for_editor(),
|
| 85 |
+
headers=["pattern", "replacement"],
|
| 86 |
+
datatype=["str", "str"],
|
| 87 |
+
interactive=True,
|
| 88 |
+
row_count=(len(load_pattern_config().get("global", [])) or 1),
|
| 89 |
+
)
|
| 90 |
+
save_global_btn = gr.Button("πΎ Save Global Patterns")
|
| 91 |
+
global_status = gr.Markdown("")
|
| 92 |
+
|
| 93 |
+
# State specific editor
|
| 94 |
+
existing_state_keys = sorted(load_pattern_config().get("states", {}).keys())
|
| 95 |
+
with gr.Row():
|
| 96 |
+
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)
|
| 97 |
+
new_state_tb = gr.Textbox(label="Or type new state key", placeholder="e.g. KARNATAKA")
|
| 98 |
+
state_df = gr.Dataframe(value=pd.DataFrame(columns=["pattern", "replacement"]), headers=["pattern", "replacement"], datatype=["str", "str"], interactive=True, row_count=3)
|
| 99 |
+
load_state_btn = gr.Button("Load patterns for selected / new state")
|
| 100 |
+
save_state_btn = gr.Button("πΎ Save State Patterns")
|
| 101 |
+
state_status = gr.Markdown("")
|
| 102 |
+
|
| 103 |
+
# Debug + Refresh
|
| 104 |
+
refresh_btn = gr.Button("π Refresh patterns.json from disk")
|
| 105 |
+
refresh_status = gr.Markdown("")
|
| 106 |
+
show_file_btn = gr.Button("π Show patterns.json file info (path + preview)")
|
| 107 |
+
debug_info_md = gr.Markdown("")
|
| 108 |
+
|
| 109 |
+
# Lock button to hide again (optional)
|
| 110 |
+
lock_btn = gr.Button("Lock Admin Panel")
|
| 111 |
+
lock_status = gr.Markdown("")
|
| 112 |
+
|
| 113 |
+
# -------- Wiring: Search --------
|
| 114 |
state_dd.change(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
|
| 115 |
demo.load(fn=load_master_for_state, inputs=state_dd, outputs=[district_dd, block_dd])
|
| 116 |
district_dd.change(fn=update_blocks, inputs=district_dd, outputs=block_dd)
|
| 117 |
search_btn.click(fn=search_candidates, inputs=[school_input, state_dd, district_dd, block_dd], outputs=[candidates_table, best_table])
|
| 118 |
|
| 119 |
+
# -------- Wiring: Admin gating --------
|
| 120 |
+
def try_unlock(pwd: str):
|
| 121 |
+
if ADMIN_PASSWORD is None:
|
| 122 |
+
return gr.update(visible=False), "β ADMIN_PASSWORD not configured in environment", None
|
| 123 |
+
if pwd == ADMIN_PASSWORD:
|
| 124 |
+
return gr.update(visible=True), "π Admin panel unlocked.", True
|
| 125 |
+
else:
|
| 126 |
+
return gr.update(visible=False), "β Wrong password.", False
|
| 127 |
+
|
| 128 |
+
unlock_btn.click(fn=try_unlock, inputs=unlock_pwd, outputs=[admin_panel, unlock_status, unlock_pwd])
|
| 129 |
+
|
| 130 |
+
def do_lock():
|
| 131 |
+
return gr.update(visible=False), "π Admin panel locked."
|
| 132 |
+
|
| 133 |
+
lock_btn.click(fn=do_lock, inputs=None, outputs=[admin_panel, lock_status])
|
| 134 |
+
|
| 135 |
+
# -------- Wiring: Admin actions (inside admin_panel) --------
|
| 136 |
+
# Save global (server still checks password inside save function)
|
| 137 |
+
save_global_btn.click(fn=lambda df, pwd: save_global_patterns_from_editor(df, pwd, ADMIN_PASSWORD),
|
| 138 |
+
inputs=[global_df, unlock_pwd],
|
| 139 |
+
outputs=global_status)
|
| 140 |
+
|
| 141 |
+
# Load state patterns into editor (view-only)
|
| 142 |
load_state_btn.click(fn=load_state_patterns_for_editor, inputs=[state_pattern_dd, new_state_tb], outputs=state_df)
|
|
|
|
| 143 |
|
| 144 |
+
# Save state patterns
|
| 145 |
+
save_state_btn.click(fn=lambda state_sel, new_state, df, pwd: save_state_patterns_from_editor(state_sel, new_state, df, pwd, ADMIN_PASSWORD),
|
| 146 |
+
inputs=[state_pattern_dd, new_state_tb, state_df, unlock_pwd],
|
| 147 |
+
outputs=state_status)
|
| 148 |
+
|
| 149 |
+
# Refresh & show file info
|
| 150 |
refresh_btn.click(fn=refresh_pattern_config, inputs=None, outputs=refresh_status)
|
| 151 |
show_file_btn.click(fn=show_patterns_file_info, inputs=None, outputs=debug_info_md)
|
| 152 |
|
| 153 |
+
|
| 154 |
if __name__ == "__main__":
|
| 155 |
demo.launch()
|