maringetxway commited on
Commit
4a79184
Β·
verified Β·
1 Parent(s): e2a5983

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -129
app.py CHANGED
@@ -5,50 +5,66 @@ import os
5
  import shutil
6
  import datetime
7
 
8
- # Path to the data file
9
- DATA_FILE = os.path.join("data", "teamup_data.json")
 
 
 
10
 
11
- # Load the ADMIN_CODE environment variable
12
- ADMIN_CODE = os.getenv("ADMIN_CODE", "")
13
-
14
- # Ensure data file exists
15
- os.makedirs("data", exist_ok=True)
16
  if not os.path.exists(DATA_FILE) or os.path.getsize(DATA_FILE) == 0:
17
  with open(DATA_FILE, "w") as f:
18
  json.dump([], f)
19
 
20
- # Function to create a backup of the data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  def backup_data():
22
- source_file = DATA_FILE
23
- backup_dir = './data/backup'
24
- os.makedirs(backup_dir, exist_ok=True)
25
-
26
  timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
27
- backup_file = os.path.join(backup_dir, f'teamup_data_backup_{timestamp}.json')
 
28
 
29
- shutil.copy(source_file, backup_file)
30
- print(f"βœ… Backup created at {backup_file}")
 
 
 
 
31
 
32
- # Function to submit or update a profile
33
  def submit_profile(name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea):
34
- print("🟒 Submit button clicked.")
35
- print(f"Incoming: {discord=}, {city=}, {country=}, {languages=}, {laptop=}, {robot=}")
36
-
37
  if not discord or not city or not country or not laptop or not robot:
38
  return "❌ Please fill in all required fields."
39
- if not languages or not isinstance(languages, list) or len(languages) == 0:
 
40
  return "❌ Please select at least one language."
41
 
42
- # Ensure country is stored as a string (in case form allows lists)
43
- if isinstance(country, list):
44
- country = country[0] if country else ""
 
45
 
46
  with open(DATA_FILE, "r") as f:
47
  data = json.load(f)
48
 
49
- for d in data:
50
- if d["Discord"].lower() == discord.lower():
51
- d.update({
52
  "Name": name,
53
  "City": city,
54
  "Country": country,
@@ -83,148 +99,101 @@ def submit_profile(name, discord, city, country, address, looking, onlinecheck,
83
  })
84
 
85
  try:
86
- with open(DATA_FILE, "w") as f:
87
- json.dump(data, f, indent=2)
88
- print(f"βœ… Successfully wrote {len(data)} profiles to {DATA_FILE}")
89
- backup_data() # Backup after every update
90
  except Exception as e:
91
- print(f"❌ Failed to write to {DATA_FILE}: {e}")
92
- return "❌ Error saving your profile. Please try again."
 
 
 
 
 
 
 
 
93
 
94
- return "βœ… Profile saved!"
 
95
 
96
- # Function to filter participants by fields
97
  def filter_by_fields(selected_country, selected_city, selected_language):
98
  with open(DATA_FILE, "r") as f:
99
  data = json.load(f)
100
- df = pd.DataFrame(data)
101
 
102
- # Convert list values to readable strings
103
- df["Languages"] = df["Languages"].apply(lambda langs: ", ".join(langs) if isinstance(langs, list) else langs)
 
104
 
105
- if df.empty or "Country" not in df.columns or "Languages" not in df.columns:
106
- return "<p>No participants found.</p>"
107
 
108
  if selected_country != "All":
109
- df = df[df["Country"] == selected_country]
110
-
111
  if selected_city != "All":
112
- df = df[df["City"] == selected_city]
113
-
114
  if selected_language != "All":
115
- df = df[df["Languages"].apply(lambda langs: selected_language in langs)]
116
 
117
- # Hide address
118
  if "Address" in df.columns:
119
- df = df.drop(columns=["Address"])
120
-
121
- # Rename column headers for display only
122
- display_names = {
123
- "Discord": "Discord",
124
- "Name": "Name",
125
- "City": "City",
126
- "Country": "Country",
127
- "Looking for Team": "Looking for Team",
128
- "Onlinecheck": "How?",
129
- "Languages": "Languages",
130
- "Laptop": "Laptop",
131
- "Robot": "Robot",
132
- "Skills": "Skills",
133
- "Describe3": "Describe",
134
- "Experience": "Experience",
135
- "Project Idea": "Project Idea"
136
- }
137
-
138
- html = '<h3 style="margin-top:20px;">πŸ” Find your matching Teammates & Register your team <a href="https://forms.gle/gJEMGD4CEA2emhD18" target="_blank">here</a>πŸ‘ˆπŸ‘ˆ</h3>'
139
- html += "<table style='width:100%; border-collapse: collapse;'>"
140
-
141
- # Header row
142
- html += "<tr>" + "".join(
143
- f"<th style='border: 1px solid #ccc; padding: 6px;'>{display_names.get(col, col)}</th>"
144
- for col in df.columns
145
- ) + "</tr>"
146
-
147
- # Data rows
148
- for _, row in df.iterrows():
149
- html += "<tr>"
150
- for col in df.columns:
151
- val = row[col]
152
- if col == "Discord":
153
- val = f"<a href='https://discord.com/users/{val}' target='_blank'>{val}</a>"
154
- html += f"<td style='border: 1px solid #eee; padding: 6px;'>{val}</td>"
155
- html += "</tr>"
156
 
 
 
 
 
 
 
 
157
  html += "</table>"
158
  return html
159
 
160
- # List of all countries in alphabetical order
161
- ALL_COUNTRIES = [
162
- "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria",
163
- "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan",
164
- "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi", "Cabo Verde", "Cambodia",
165
- "Cameroon", "Canada", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo (Congo-Brazzaville)",
166
- "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia (Czech Republic)", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica",
167
- "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Eswatini (fmr. 'Swaziland')", "Ethiopia",
168
- "Fiji", "Finland", "France", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Greece", "Grenada",
169
- "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia",
170
- "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya",
171
- "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia",
172
- "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta",
173
- "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco",
174
- "Mozambique", "Myanmar (formerly Burma)", "Namibia", "Nauru", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria",
175
- "North Macedonia", "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
176
- "Poland", "Portugal", "Qatar", "Romania", "Russia", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Vincent and the Grenadines", "Samoa",
177
- "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia",
178
- "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Sweden", "Switzerland",
179
- "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia",
180
- "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States of America", "Uruguay",
181
- "Uzbekistan", "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe"
182
- ]
183
-
184
- # Function to update the dropdown choices
185
- def update_dropdown_choices():
186
- return gr.update(choices=["All"] + ALL_COUNTRIES, value="All")
187
-
188
- # Setup Gradio interface
189
  with gr.Blocks(css=".gr-dropdown { max-height: 100px; overflow-y: auto; font-size: 12px; }") as demo:
190
- gr.Markdown("# 🌍 LeRobot Worldwide Hackathon - Team-Up Dashboard")
191
- gr.Markdown("1. Submit or update your profile to find matching teammates and contact them on Discord. (Required fields marked with *.) ")
192
 
193
- # Input fields and buttons setup
194
  with gr.Row():
195
  with gr.Column():
196
  name = gr.Text(label="Name")
197
  discord = gr.Text(label="πŸ‘€ Discord Username *")
198
  city = gr.Text(label="πŸ“ City *")
199
- country = gr.Dropdown(label="🌍 Country *", choices=ALL_COUNTRIES, value="All") # Dropdown for Country
200
  address = gr.Text(label="Address (optional)")
201
  looking = gr.Radio(["Yes", "No"], label="πŸ” Looking for a team?")
202
- onlinecheck = gr.Radio(["Participate Online", "Join a Local Hackathon"], label="πŸš€ I will...")
203
  languages = gr.CheckboxGroup(choices=["English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"], label="Languages Spoken *")
204
  laptop = gr.Text(label="πŸ’» Laptop Setup *")
205
- robot = gr.Text(label="Robot Setup *")
206
- skills = gr.Text(label="🧠 Your Skills (comma separated)")
207
- describe3 = gr.Text(label="πŸ€— 3 Words That Describe You")
208
  experience = gr.Dropdown(choices=["Beginner", "Intermediate", "Advanced"], label="Experience Level", value="Beginner")
209
  idea = gr.Textbox(label="Project Idea (optional)")
210
- submit_btn = gr.Button("Submit or Update Profile βœ…")
211
  status = gr.Textbox(label="", interactive=False)
212
 
213
  with gr.Column():
214
- gr.Markdown("🎯 2. Choose your preferences to find your teammates (country, city or language)")
215
- country_filter = gr.Dropdown(label="Filter by Country", choices=["All"], value="All", allow_custom_value=False)
216
- city_filter = gr.Dropdown(label="Filter by City", choices=["All"], value="All", allow_custom_value=False)
217
- language_filter = gr.Dropdown(label="Filter by Language", choices=["All"], value="All", allow_custom_value=False)
218
- table_html = gr.HTML(label="Matching Participants")
219
 
220
  submit_btn.click(
221
- submit_profile,
222
  inputs=[name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea],
223
  outputs=[status]
 
 
 
 
224
  )
225
 
226
- country_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html)
227
- city_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html)
228
- language_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html)
229
 
230
  demo.launch()
 
 
5
  import shutil
6
  import datetime
7
 
8
+ # Paths
9
+ DATA_DIR = "data"
10
+ DATA_FILE = os.path.join(DATA_DIR, "teamup_data.json")
11
+ BACKUP_DIR = os.path.join(DATA_DIR, "backup")
12
+ os.makedirs(DATA_DIR, exist_ok=True)
13
 
14
+ # Init data file
 
 
 
 
15
  if not os.path.exists(DATA_FILE) or os.path.getsize(DATA_FILE) == 0:
16
  with open(DATA_FILE, "w") as f:
17
  json.dump([], f)
18
 
19
+ # Country list
20
+ ALL_COUNTRIES = sorted(list(set([
21
+ "United States of America", "United Kingdom", "India", "France", "Germany", "Canada", "Australia", "Japan", "Brazil", "Mexico",
22
+ # Add or reduce to most relevant countries only for dropdown
23
+ ] + [ # Fallback: full list
24
+ "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina", "Armenia", "Austria", "Azerbaijan",
25
+ "Bangladesh", "Belgium", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bulgaria", "Cambodia",
26
+ "Chile", "China", "Colombia", "Croatia", "Cuba", "Czech Republic", "Denmark", "Dominican Republic", "Ecuador",
27
+ "Egypt", "Estonia", "Ethiopia", "Finland", "Greece", "Hungary", "Iceland", "Indonesia", "Iran", "Iraq", "Ireland",
28
+ "Israel", "Italy", "Jordan", "Kenya", "Kuwait", "Latvia", "Lithuania", "Luxembourg", "Malaysia", "Malta", "Morocco",
29
+ "Nepal", "Netherlands", "New Zealand", "Nigeria", "Norway", "Pakistan", "Peru", "Philippines", "Poland", "Portugal",
30
+ "Qatar", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "South Korea",
31
+ "Spain", "Sri Lanka", "Sweden", "Switzerland", "Thailand", "Tunisia", "Turkey", "Ukraine", "United Arab Emirates", "Vietnam",
32
+ "Zambia", "Zimbabwe"
33
+ ])))
34
+
35
+ # Backup
36
  def backup_data():
37
+ os.makedirs(BACKUP_DIR, exist_ok=True)
 
 
 
38
  timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
39
+ backup_file = os.path.join(BACKUP_DIR, f'teamup_data_backup_{timestamp}.json')
40
+ shutil.copy(DATA_FILE, backup_file)
41
 
42
+ # Safe save
43
+ def atomic_save(data, path):
44
+ tmp_path = path + ".tmp"
45
+ with open(tmp_path, "w") as f:
46
+ json.dump(data, f, indent=2)
47
+ os.replace(tmp_path, path)
48
 
49
+ # Profile submission
50
  def submit_profile(name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea):
 
 
 
51
  if not discord or not city or not country or not laptop or not robot:
52
  return "❌ Please fill in all required fields."
53
+
54
+ if not languages or not isinstance(languages, list):
55
  return "❌ Please select at least one language."
56
 
57
+ # Normalize input
58
+ city = city.strip().title()
59
+ country = country.strip().title()
60
+ discord = discord.strip()
61
 
62
  with open(DATA_FILE, "r") as f:
63
  data = json.load(f)
64
 
65
+ for entry in data:
66
+ if entry["Discord"].lower() == discord.lower():
67
+ entry.update({
68
  "Name": name,
69
  "City": city,
70
  "Country": country,
 
99
  })
100
 
101
  try:
102
+ atomic_save(data, DATA_FILE)
103
+ backup_data()
104
+ return "βœ… Profile saved!"
 
105
  except Exception as e:
106
+ return f"❌ Failed to save: {e}"
107
+
108
+ # City dropdown update
109
+ def update_city_filter(country):
110
+ with open(DATA_FILE, "r") as f:
111
+ data = json.load(f)
112
+ df = pd.DataFrame(data)
113
+
114
+ if country != "All":
115
+ df = df[df["Country"].str.title() == country.title()]
116
 
117
+ cities = sorted(set(df["City"].dropna().unique()))
118
+ return gr.update(choices=["All"] + cities, value="All")
119
 
120
+ # Filter participants
121
  def filter_by_fields(selected_country, selected_city, selected_language):
122
  with open(DATA_FILE, "r") as f:
123
  data = json.load(f)
 
124
 
125
+ df = pd.DataFrame(data)
126
+ if df.empty:
127
+ return "<p>No data available.</p>"
128
 
129
+ df["Languages"] = df["Languages"].apply(lambda x: ", ".join(x) if isinstance(x, list) else str(x))
 
130
 
131
  if selected_country != "All":
132
+ df = df[df["Country"].str.title() == selected_country.title()]
 
133
  if selected_city != "All":
134
+ df = df[df["City"].str.title() == selected_city.title()]
 
135
  if selected_language != "All":
136
+ df = df[df["Languages"].str.contains(selected_language)]
137
 
 
138
  if "Address" in df.columns:
139
+ df.drop(columns=["Address"], inplace=True)
140
+
141
+ if df.empty:
142
+ return "<p>No participants match your filters.</p>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
+ html = "<table style='width:100%; border-collapse: collapse;'>"
145
+ html += "<tr>" + "".join(f"<th style='border:1px solid #ccc;padding:6px'>{col}</th>" for col in df.columns) + "</tr>"
146
+ for _, row in df.iterrows():
147
+ html += "<tr>" + "".join(
148
+ f"<td style='border:1px solid #eee;padding:6px'>{row[col] if col != 'Discord' else f'<a href=\"https://discord.com/users/{row[col]}\" target=\"_blank\">{row[col]}</a>'}</td>"
149
+ for col in df.columns
150
+ ) + "</tr>"
151
  html += "</table>"
152
  return html
153
 
154
+ # Gradio Interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  with gr.Blocks(css=".gr-dropdown { max-height: 100px; overflow-y: auto; font-size: 12px; }") as demo:
156
+ gr.Markdown("# 🌍 LeRobot Hackathon: Global Team-Up Dashboard")
 
157
 
 
158
  with gr.Row():
159
  with gr.Column():
160
  name = gr.Text(label="Name")
161
  discord = gr.Text(label="πŸ‘€ Discord Username *")
162
  city = gr.Text(label="πŸ“ City *")
163
+ country = gr.Dropdown(label="🌍 Country *", choices=ALL_COUNTRIES)
164
  address = gr.Text(label="Address (optional)")
165
  looking = gr.Radio(["Yes", "No"], label="πŸ” Looking for a team?")
166
+ onlinecheck = gr.Radio(["Participate Online", "Join a Local Hackathon"], label="πŸš€ I will...")
167
  languages = gr.CheckboxGroup(choices=["English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"], label="Languages Spoken *")
168
  laptop = gr.Text(label="πŸ’» Laptop Setup *")
169
+ robot = gr.Text(label="πŸ€– Robot Setup *")
170
+ skills = gr.Text(label="🧠 Skills (comma separated)")
171
+ describe3 = gr.Text(label="3 Words That Describe You")
172
  experience = gr.Dropdown(choices=["Beginner", "Intermediate", "Advanced"], label="Experience Level", value="Beginner")
173
  idea = gr.Textbox(label="Project Idea (optional)")
174
+ submit_btn = gr.Button("Submit or Update βœ…")
175
  status = gr.Textbox(label="", interactive=False)
176
 
177
  with gr.Column():
178
+ gr.Markdown("🎯 Find teammates by country, city, or language.")
179
+ country_filter = gr.Dropdown(label="Filter by Country", choices=["All"] + ALL_COUNTRIES, value="All")
180
+ city_filter = gr.Dropdown(label="Filter by City", choices=["All"], value="All")
181
+ language_filter = gr.Dropdown(label="Filter by Language", choices=["All", "English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"], value="All")
182
+ table_html = gr.HTML()
183
 
184
  submit_btn.click(
185
+ fn=submit_profile,
186
  inputs=[name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea],
187
  outputs=[status]
188
+ ).then(
189
+ fn=filter_by_fields,
190
+ inputs=[country_filter, city_filter, language_filter],
191
+ outputs=[table_html]
192
  )
193
 
194
+ country_filter.change(fn=update_city_filter, inputs=[country_filter], outputs=[city_filter])
195
+ for dropdown in [country_filter, city_filter, language_filter]:
196
+ dropdown.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=[table_html])
197
 
198
  demo.launch()
199
+