bgamazay commited on
Commit
76550bf
·
verified ·
1 Parent(s): da92ff4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +4 -41
app.py CHANGED
@@ -6,8 +6,6 @@ import random
6
  import os
7
 
8
  # --- CONFIGURATION ---
9
- # We will use your username and a standard name for the storage dataset
10
- # The app will find your username automatically from the token
11
  DATASET_NAME = "my-french-flashcards-data"
12
  CSV_FILE = "cards.csv"
13
 
@@ -21,7 +19,6 @@ def get_api():
21
  return HfApi(token=token), token
22
 
23
  def get_user_repo_id(api, token):
24
- # Determine the current user's username to build the repo_id
25
  user_info = api.whoami(token=token)
26
  return f"{user_info['name']}/{DATASET_NAME}"
27
 
@@ -30,7 +27,6 @@ def load_data():
30
  repo_id = get_user_repo_id(api, token)
31
 
32
  try:
33
- # Try to download the CSV
34
  local_path = hf_hub_download(
35
  repo_id=repo_id,
36
  filename=CSV_FILE,
@@ -39,26 +35,22 @@ def load_data():
39
  )
40
  return pd.read_csv(local_path)
41
  except Exception:
42
- # If download fails, the dataset or file might not exist yet.
43
- # Check if repo exists, if not create it.
44
  try:
45
  api.create_repo(repo_id=repo_id, repo_type="dataset", private=True, exist_ok=True)
46
  except Exception as e:
47
  st.error(f"Could not create storage repository: {e}")
48
 
49
- # Return an empty dataframe structure
50
  return pd.DataFrame(columns=["french", "context", "english", "active"])
51
 
52
  def save_data(df):
53
  api, token = get_api()
54
  repo_id = get_user_repo_id(api, token)
55
 
56
- # Save dataframe to buffer
57
  csv_buffer = StringIO()
58
  df.to_csv(csv_buffer, index=False)
59
  csv_buffer.seek(0)
60
 
61
- # Upload to Hub
62
  try:
63
  api.upload_file(
64
  path_or_fileobj=csv_buffer.read().encode(),
@@ -74,26 +66,23 @@ def save_data(df):
74
 
75
  # --- UI LOGIC ---
76
 
77
- # Initialize Session State
78
  if 'page' not in st.session_state:
79
  st.session_state['page'] = 'home'
80
  if 'df' not in st.session_state:
81
  st.session_state['df'] = load_data()
82
  if 'deck' not in st.session_state:
83
- st.session_state['deck'] = [] # List of indices from df
84
  if 'current_card_idx' not in st.session_state:
85
  st.session_state['current_card_idx'] = 0
86
  if 'side_cycle_count' not in st.session_state:
87
- st.session_state['side_cycle_count'] = 0 # 0=Fr, 1=Ctx, 2=Eng, 3=Ctx -> Loop
88
 
89
  def set_page(page_name):
 
90
  st.session_state['page'] = page_name
91
- st.rerun()
92
 
93
  def start_session():
94
- # Filter only active cards
95
  df = st.session_state['df']
96
- # Ensure 'active' column exists and is boolean (handle legacy data)
97
  if 'active' not in df.columns:
98
  df['active'] = True
99
 
@@ -110,32 +99,20 @@ def start_session():
110
  set_page('play')
111
 
112
  def next_card():
113
- # Move to next card in the deck
114
  st.session_state['current_card_idx'] += 1
115
- # Reset side to 0 (French)
116
  st.session_state['side_cycle_count'] = 0
117
 
118
- # If we reached end of deck, go home
119
  if st.session_state['current_card_idx'] >= len(st.session_state['deck']):
120
  st.balloons()
121
  st.success("Session Complete!")
122
  set_page('home')
123
- else:
124
- st.rerun()
125
 
126
  def archive_current_card():
127
- # Get actual index in the dataframe
128
  current_deck_idx = st.session_state['current_card_idx']
129
  if current_deck_idx < len(st.session_state['deck']):
130
  df_idx = st.session_state['deck'][current_deck_idx]
131
-
132
- # Update DataFrame
133
  st.session_state['df'].at[df_idx, 'active'] = False
134
-
135
- # Save to Cloud
136
  save_data(st.session_state['df'])
137
-
138
- # Move to next card
139
  next_card()
140
 
141
  def add_card(french, context, english):
@@ -152,13 +129,11 @@ def add_card(french, context, english):
152
  def unarchive(df_idx):
153
  st.session_state['df'].at[df_idx, 'active'] = True
154
  save_data(st.session_state['df'])
155
- st.rerun()
156
 
157
  # --- PAGE RENDERING ---
158
 
159
  st.set_page_config(page_title="French Flashcards", page_icon="🇫🇷", layout="centered")
160
 
161
- # Custom CSS for "Beautiful & Minimal" look
162
  st.markdown("""
163
  <style>
164
  .stButton>button {
@@ -213,13 +188,9 @@ elif st.session_state['page'] == 'archive':
213
  st.title("Archive")
214
  st.button("Back", on_click=lambda: set_page('home'))
215
 
216
- # Show active/inactive status clearly
217
  df = st.session_state['df']
218
  if not df.empty:
219
- # Display as a table with checkboxes?
220
- # Streamlit data editor is easiest
221
  st.write("Below are your inactive cards. Click 'Unarchive' to restore.")
222
-
223
  archived = df[df['active'] == False]
224
  if archived.empty:
225
  st.info("Archive is empty.")
@@ -234,16 +205,12 @@ elif st.session_state['page'] == 'archive':
234
  st.write("No cards yet.")
235
 
236
  elif st.session_state['page'] == 'play':
237
- # Get current card data
238
  deck_idx = st.session_state['current_card_idx']
239
 
240
  if deck_idx < len(st.session_state['deck']):
241
  df_idx = st.session_state['deck'][deck_idx]
242
  card = st.session_state['df'].iloc[df_idx]
243
 
244
- # Determine which side to show based on cycle
245
- # Cycle logic: 0->1->2->3(which is 2 again)->0...
246
- # Map: 0:Fr, 1:Ctx, 2:En, 3:Ctx
247
  cycle_map = {0: 'French', 1: 'Context', 2: 'English', 3: 'Context'}
248
  current_side_idx = st.session_state['side_cycle_count'] % 4
249
  side_name = cycle_map[current_side_idx]
@@ -253,12 +220,10 @@ elif st.session_state['page'] == 'play':
253
  elif side_name == 'Context': content = card['context']
254
  elif side_name == 'English': content = card['english']
255
 
256
- # Progress Bar
257
  progress = (deck_idx + 1) / len(st.session_state['deck'])
258
  st.progress(progress)
259
  st.caption(f"Card {deck_idx + 1} of {len(st.session_state['deck'])}")
260
 
261
- # Card Display
262
  st.markdown(f"""
263
  <div class="card-container">
264
  <div class="card-label">{side_name}</div>
@@ -266,7 +231,6 @@ elif st.session_state['page'] == 'play':
266
  </div>
267
  """, unsafe_allow_html=True)
268
 
269
- # Buttons
270
  col1, col2 = st.columns([2, 1])
271
  with col1:
272
  def cycle_side():
@@ -281,5 +245,4 @@ elif st.session_state['page'] == 'play':
281
  st.button("Quit Session", on_click=lambda: set_page('home'))
282
 
283
  else:
284
- # Fallback if index error
285
  set_page('home')
 
6
  import os
7
 
8
  # --- CONFIGURATION ---
 
 
9
  DATASET_NAME = "my-french-flashcards-data"
10
  CSV_FILE = "cards.csv"
11
 
 
19
  return HfApi(token=token), token
20
 
21
  def get_user_repo_id(api, token):
 
22
  user_info = api.whoami(token=token)
23
  return f"{user_info['name']}/{DATASET_NAME}"
24
 
 
27
  repo_id = get_user_repo_id(api, token)
28
 
29
  try:
 
30
  local_path = hf_hub_download(
31
  repo_id=repo_id,
32
  filename=CSV_FILE,
 
35
  )
36
  return pd.read_csv(local_path)
37
  except Exception:
38
+ # If repo or file doesn't exist, create repo
 
39
  try:
40
  api.create_repo(repo_id=repo_id, repo_type="dataset", private=True, exist_ok=True)
41
  except Exception as e:
42
  st.error(f"Could not create storage repository: {e}")
43
 
 
44
  return pd.DataFrame(columns=["french", "context", "english", "active"])
45
 
46
  def save_data(df):
47
  api, token = get_api()
48
  repo_id = get_user_repo_id(api, token)
49
 
 
50
  csv_buffer = StringIO()
51
  df.to_csv(csv_buffer, index=False)
52
  csv_buffer.seek(0)
53
 
 
54
  try:
55
  api.upload_file(
56
  path_or_fileobj=csv_buffer.read().encode(),
 
66
 
67
  # --- UI LOGIC ---
68
 
 
69
  if 'page' not in st.session_state:
70
  st.session_state['page'] = 'home'
71
  if 'df' not in st.session_state:
72
  st.session_state['df'] = load_data()
73
  if 'deck' not in st.session_state:
74
+ st.session_state['deck'] = []
75
  if 'current_card_idx' not in st.session_state:
76
  st.session_state['current_card_idx'] = 0
77
  if 'side_cycle_count' not in st.session_state:
78
+ st.session_state['side_cycle_count'] = 0
79
 
80
  def set_page(page_name):
81
+ # UPDATED: Just set state, let Streamlit handle the rerun automatically
82
  st.session_state['page'] = page_name
 
83
 
84
  def start_session():
 
85
  df = st.session_state['df']
 
86
  if 'active' not in df.columns:
87
  df['active'] = True
88
 
 
99
  set_page('play')
100
 
101
  def next_card():
 
102
  st.session_state['current_card_idx'] += 1
 
103
  st.session_state['side_cycle_count'] = 0
104
 
 
105
  if st.session_state['current_card_idx'] >= len(st.session_state['deck']):
106
  st.balloons()
107
  st.success("Session Complete!")
108
  set_page('home')
 
 
109
 
110
  def archive_current_card():
 
111
  current_deck_idx = st.session_state['current_card_idx']
112
  if current_deck_idx < len(st.session_state['deck']):
113
  df_idx = st.session_state['deck'][current_deck_idx]
 
 
114
  st.session_state['df'].at[df_idx, 'active'] = False
 
 
115
  save_data(st.session_state['df'])
 
 
116
  next_card()
117
 
118
  def add_card(french, context, english):
 
129
  def unarchive(df_idx):
130
  st.session_state['df'].at[df_idx, 'active'] = True
131
  save_data(st.session_state['df'])
 
132
 
133
  # --- PAGE RENDERING ---
134
 
135
  st.set_page_config(page_title="French Flashcards", page_icon="🇫🇷", layout="centered")
136
 
 
137
  st.markdown("""
138
  <style>
139
  .stButton>button {
 
188
  st.title("Archive")
189
  st.button("Back", on_click=lambda: set_page('home'))
190
 
 
191
  df = st.session_state['df']
192
  if not df.empty:
 
 
193
  st.write("Below are your inactive cards. Click 'Unarchive' to restore.")
 
194
  archived = df[df['active'] == False]
195
  if archived.empty:
196
  st.info("Archive is empty.")
 
205
  st.write("No cards yet.")
206
 
207
  elif st.session_state['page'] == 'play':
 
208
  deck_idx = st.session_state['current_card_idx']
209
 
210
  if deck_idx < len(st.session_state['deck']):
211
  df_idx = st.session_state['deck'][deck_idx]
212
  card = st.session_state['df'].iloc[df_idx]
213
 
 
 
 
214
  cycle_map = {0: 'French', 1: 'Context', 2: 'English', 3: 'Context'}
215
  current_side_idx = st.session_state['side_cycle_count'] % 4
216
  side_name = cycle_map[current_side_idx]
 
220
  elif side_name == 'Context': content = card['context']
221
  elif side_name == 'English': content = card['english']
222
 
 
223
  progress = (deck_idx + 1) / len(st.session_state['deck'])
224
  st.progress(progress)
225
  st.caption(f"Card {deck_idx + 1} of {len(st.session_state['deck'])}")
226
 
 
227
  st.markdown(f"""
228
  <div class="card-container">
229
  <div class="card-label">{side_name}</div>
 
231
  </div>
232
  """, unsafe_allow_html=True)
233
 
 
234
  col1, col2 = st.columns([2, 1])
235
  with col1:
236
  def cycle_side():
 
245
  st.button("Quit Session", on_click=lambda: set_page('home'))
246
 
247
  else:
 
248
  set_page('home')