akaburia commited on
Commit
7141c9e
·
verified ·
1 Parent(s): 3619e86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -8
app.py CHANGED
@@ -34,9 +34,32 @@ try:
34
  except ImportError:
35
  import pytz # Fallback if zoneinfo is missing
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  # --- CACHING HELPERS ---
38
  DRAFT_FILE = "user_drafts.json"
39
 
 
40
  def load_drafts():
41
  if os.path.exists(DRAFT_FILE):
42
  try:
@@ -70,6 +93,7 @@ def update_cache_row(user, session_id, dom_a, pol_a, dom_b, pol_b, tar_col, ctx_
70
  drafts[user]["rows"][cache_key][b_text] = {
71
  "rel": rel, "inter": inter, "just": just, "session_id": session_id
72
  }
 
73
 
74
  with open(DRAFT_FILE, 'w') as f:
75
  json.dump(drafts, f)
@@ -775,26 +799,41 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
775
 
776
  # ADD link_val and follow_val to inputs
777
  def authenticate(email, link_val, follow_val):
 
 
 
 
 
 
 
 
 
 
 
778
  user_tag, msg = get_or_create_user(email)
779
 
780
  if not user_tag:
 
781
  return (gr.update(value=f"<font color='red'>{msg}</font>"),
782
- gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), # Added sector_box visibility
783
  None, None,
784
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), link_val, follow_val)
785
 
 
786
  hf_df = load_hf_dataset()
787
  drafts = load_drafts()
788
  user_data = drafts.get(user_tag, {})
789
  ws = user_data.get("workspace", {})
790
 
 
791
  if ws.get("pol_a") and ws.get("pol_b"):
792
- msg += f" Restored your previous session workspace."
 
793
  return (
794
  gr.update(value=f"{msg} Loaded {len(hf_df)} annotations."),
795
- gr.update(visible=False), # login_box
796
- gr.update(visible=False), # sector_box (SKIP)
797
- gr.update(visible=True), # app_box
798
  user_tag,
799
  hf_df,
800
  gr.update(value=ws["dom_a"]),
@@ -807,11 +846,12 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
807
  follow_val
808
  )
809
  else:
 
810
  return (
811
  gr.update(value=f"{msg} Loaded {len(hf_df)} annotations."),
812
- gr.update(visible=False), # login_box
813
- gr.update(visible=True), # sector_box (SHOW)
814
- gr.update(visible=False), # app_box (HIDE)
815
  user_tag,
816
  hf_df,
817
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
@@ -838,6 +878,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
838
  default_domain = allowed_list[0] if allowed_list else None
839
  available_policies = get_policy_list(default_domain) if default_domain else []
840
 
 
841
  return (
842
  gr.update(visible=False), # Hide sector box
843
  gr.update(visible=True), # Show main app
@@ -1064,6 +1105,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
1064
 
1065
  status_msg = t_text(f"Data loaded. {total_missing_pairs} unannotated pairs remain across {len(target_a_list)} Target A groups.", lang)
1066
 
 
1067
  return [
1068
  target_a_list, pending_tasks, 0,
1069
  ctx_a_chunk_eng, ctx_b_chunk_eng, b_eng_list,
@@ -1151,6 +1193,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
1151
  hf_df.to_csv(csv_buffer, index=False)
1152
  csv_bytes = csv_buffer.getvalue().encode('utf-8')
1153
 
 
1154
  api = HfApi()
1155
  api.upload_file(
1156
  path_or_fileobj=io.BytesIO(csv_bytes), path_in_repo=HF_CSV_FILE,
@@ -1176,6 +1219,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
1176
  return gr.update(value=log_msg), idx + 1, hf_df
1177
 
1178
  def skip_action(idx, lang):
 
1179
  return gr.update(value=t_text(f"Skipped group {idx + 1}.", lang)), idx + 1
1180
 
1181
  # --- TRIGGER FIRST PASS ---
 
34
  except ImportError:
35
  import pytz # Fallback if zoneinfo is missing
36
 
37
+ # --- COMPREHENSIVE LOGGING ---
38
+ LOG_FILE = "logs.txt"
39
+
40
+ def write_log(action_type, details):
41
+ """Appends a timestamped log entry to logs.txt"""
42
+ try:
43
+ try:
44
+ tz = ZoneInfo("Africa/Nairobi")
45
+ except:
46
+ import pytz
47
+ tz = pytz.timezone("Africa/Nairobi")
48
+
49
+ timestamp = datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')
50
+ log_entry = f"[{timestamp}] [{action_type}] {details}\n"
51
+
52
+ with open(LOG_FILE, "a", encoding="utf-8") as f:
53
+ f.write(log_entry)
54
+
55
+ print(log_entry.strip()) # Also print to console for debugging
56
+ except Exception as e:
57
+ print(f"Logging failed: {e}")
58
+
59
  # --- CACHING HELPERS ---
60
  DRAFT_FILE = "user_drafts.json"
61
 
62
+
63
  def load_drafts():
64
  if os.path.exists(DRAFT_FILE):
65
  try:
 
93
  drafts[user]["rows"][cache_key][b_text] = {
94
  "rel": rel, "inter": inter, "just": just, "session_id": session_id
95
  }
96
+ write_log("CACHE_UPDATE", f"User {user} auto-saved draft for row index {idx}.")
97
 
98
  with open(DRAFT_FILE, 'w') as f:
99
  json.dump(drafts, f)
 
799
 
800
  # ADD link_val and follow_val to inputs
801
  def authenticate(email, link_val, follow_val):
802
+ email = email.strip().lower()
803
+
804
+ # 1. Validate Email Format
805
+ email_pattern = r"^[^@\s]+@[^@\s]+\.[^@\s]+$"
806
+ if not re.match(email_pattern, email):
807
+ write_log("LOGIN_FAILED", f"Invalid email format attempted: '{email}'")
808
+ return (gr.update(value=f"<font color='red'>Please enter a valid email address.</font>"),
809
+ gr.update(visible=True), gr.update(visible=False), gr.update(visible=False),
810
+ None, None,
811
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), link_val, follow_val)
812
+
813
  user_tag, msg = get_or_create_user(email)
814
 
815
  if not user_tag:
816
+ write_log("LOGIN_FAILED", f"System error creating user for '{email}'")
817
  return (gr.update(value=f"<font color='red'>{msg}</font>"),
818
+ gr.update(visible=True), gr.update(visible=False), gr.update(visible=False),
819
  None, None,
820
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), link_val, follow_val)
821
 
822
+ write_log("LOGIN_SUCCESS", f"User {user_tag} ({email}) logged in. Consents - Link: {link_val}, Follow: {follow_val}")
823
  hf_df = load_hf_dataset()
824
  drafts = load_drafts()
825
  user_data = drafts.get(user_tag, {})
826
  ws = user_data.get("workspace", {})
827
 
828
+ # 2. Check for pending session and redirect straight to workspace
829
  if ws.get("pol_a") and ws.get("pol_b"):
830
+ write_log("SESSION_RESTORED", f"User {user_tag} skipped sectors and restored previous session {ws.get('session_id')}.")
831
+ msg += f" Restored your pending session. Click 'Fetch Data' to resume your draft."
832
  return (
833
  gr.update(value=f"{msg} Loaded {len(hf_df)} annotations."),
834
+ gr.update(visible=False), # Hide login_box
835
+ gr.update(visible=False), # Hide sector_box (Bypass directly to app)
836
+ gr.update(visible=True), # Show app_box
837
  user_tag,
838
  hf_df,
839
  gr.update(value=ws["dom_a"]),
 
846
  follow_val
847
  )
848
  else:
849
+ write_log("NEW_SESSION", f"User {user_tag} starting fresh. Routing to Sector Selection.")
850
  return (
851
  gr.update(value=f"{msg} Loaded {len(hf_df)} annotations."),
852
+ gr.update(visible=False), # Hide login_box
853
+ gr.update(visible=True), # Show sector_box
854
+ gr.update(visible=False), # Hide app_box
855
  user_tag,
856
  hf_df,
857
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
 
878
  default_domain = allowed_list[0] if allowed_list else None
879
  available_policies = get_policy_list(default_domain) if default_domain else []
880
 
881
+ write_log("SECTOR_SELECTED", f"Mapped sectors {selected_sectors} to domains {allowed_list}")
882
  return (
883
  gr.update(visible=False), # Hide sector box
884
  gr.update(visible=True), # Show main app
 
1105
 
1106
  status_msg = t_text(f"Data loaded. {total_missing_pairs} unannotated pairs remain across {len(target_a_list)} Target A groups.", lang)
1107
 
1108
+ write_log("WORKSPACE_LOADED", f"User {user_tag} fetched {pol_a} vs {pol_b}.")
1109
  return [
1110
  target_a_list, pending_tasks, 0,
1111
  ctx_a_chunk_eng, ctx_b_chunk_eng, b_eng_list,
 
1193
  hf_df.to_csv(csv_buffer, index=False)
1194
  csv_bytes = csv_buffer.getvalue().encode('utf-8')
1195
 
1196
+ write_log("DATA_SAVED", f"User {user_tag} successfully saved {len(new_rows)} completed rows to Hugging Face.")
1197
  api = HfApi()
1198
  api.upload_file(
1199
  path_or_fileobj=io.BytesIO(csv_bytes), path_in_repo=HF_CSV_FILE,
 
1219
  return gr.update(value=log_msg), idx + 1, hf_df
1220
 
1221
  def skip_action(idx, lang):
1222
+ write_log("TARGET_SKIPPED", f"User skipped group {idx + 1}")
1223
  return gr.update(value=t_text(f"Skipped group {idx + 1}.", lang)), idx + 1
1224
 
1225
  # --- TRIGGER FIRST PASS ---