maringetxway commited on
Commit
11dc894
Β·
verified Β·
1 Parent(s): db1ce28

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -152
app.py CHANGED
@@ -7,61 +7,12 @@ import datetime
7
  DATA_DIR = "data"
8
  os.makedirs(DATA_DIR, exist_ok=True)
9
 
10
- # Paths
11
  DB_PATH = os.path.join(DATA_DIR, "teamup.db")
12
-
13
- # Initialize SQLite DB
14
- def init_db():
15
- with sqlite3.connect(DB_PATH) as conn:
16
- conn.execute("""
17
- CREATE TABLE IF NOT EXISTS teamup (
18
- id INTEGER PRIMARY KEY AUTOINCREMENT,
19
- Name TEXT,
20
- Discord TEXT UNIQUE,
21
- City TEXT,
22
- Country TEXT,
23
- Address TEXT,
24
- Looking TEXT,
25
- Onlinecheck TEXT,
26
- Languages TEXT,
27
- Laptop TEXT,
28
- Robot TEXT,
29
- Skills TEXT,
30
- Describe3 TEXT,
31
- Experience TEXT,
32
- Idea TEXT
33
- );
34
- """)
35
- print("βœ… SQLite database initialized.")
36
- init_db()
37
-
38
- # Initialize database
39
- conn = sqlite3.connect(DB_PATH)
40
- c = conn.cursor()
41
- c.execute('''
42
- CREATE TABLE IF NOT EXISTS teamup (
43
- discord TEXT PRIMARY KEY,
44
- name TEXT,
45
- city TEXT,
46
- country TEXT,
47
- address TEXT,
48
- looking TEXT,
49
- onlinecheck TEXT,
50
- languages TEXT,
51
- laptop TEXT,
52
- robot TEXT,
53
- skills TEXT,
54
- describe3 TEXT,
55
- experience TEXT,
56
- idea TEXT
57
- )
58
- ''')
59
- conn.commit()
60
- conn.close()
61
-
62
  ADMIN_CODE = os.getenv("ADMIN_CODE", "")
 
63
 
64
- ALL_COUNTRIES = sorted(list(set([
 
65
  "United States of America", "United Kingdom", "India", "France", "Germany", "Canada", "Australia", "Japan", "Brazil", "Mexico",
66
  "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina", "Armenia", "Austria", "Azerbaijan",
67
  "Bangladesh", "Belgium", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bulgaria", "Cambodia",
@@ -72,63 +23,89 @@ ALL_COUNTRIES = sorted(list(set([
72
  "Qatar", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "South Korea",
73
  "Spain", "Sri Lanka", "Sweden", "Switzerland", "Thailand", "Tunisia", "Turkey", "Ukraine", "United Arab Emirates", "Vietnam",
74
  "Zambia", "Zimbabwe"
75
- ])))
76
 
77
- LANGUAGES = ["English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
- # Insert or update profile
80
  def submit_profile(name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea):
81
  if not discord or not city or not country or not laptop or not robot:
82
  return "❌ Please fill in all required fields."
83
 
84
  lang_str = ", ".join(languages) if isinstance(languages, list) else languages
85
 
86
- conn = sqlite3.connect(DB_PATH)
87
- c = conn.cursor()
88
- c.execute("""
89
- INSERT INTO teamup (discord, name, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea)
90
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
91
- ON CONFLICT(discord) DO UPDATE SET
92
- name=excluded.name,
93
- city=excluded.city,
94
- country=excluded.country,
95
- address=excluded.address,
96
- looking=excluded.looking,
97
- onlinecheck=excluded.onlinecheck,
98
- languages=excluded.languages,
99
- laptop=excluded.laptop,
100
- robot=excluded.robot,
101
- skills=excluded.skills,
102
- describe3=excluded.describe3,
103
- experience=excluded.experience,
104
- idea=excluded.idea
105
- """, (discord, name, city.title(), country.title(), address, looking, onlinecheck, lang_str.lower(), laptop, robot, skills, describe3, experience, idea))
106
- conn.commit()
107
- conn.close()
108
- return "βœ… Profile saved!"
109
 
110
- # Filter and return HTML table
111
- def filter_by_fields(selected_country, selected_city, selected_language):
112
- conn = sqlite3.connect(DB_PATH)
113
- df = pd.read_sql_query("SELECT * FROM teamup", conn)
114
- conn.close()
115
 
116
- if df.empty:
117
- return "<p>No data available.</p>"
118
 
119
- df["City"] = df["city"].str.title()
120
- df["Country"] = df["country"].str.title()
121
- df["Languages"] = df["languages"]
122
 
123
  if selected_country != "All":
124
- df = df[df["Country"] == selected_country.title()]
 
125
  if selected_city != "All":
126
- df = df[df["City"] == selected_city.title()]
 
127
  if selected_language != "All":
128
- df = df[df["Languages"].str.contains(selected_language.lower(), na=False)]
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  if df.empty:
131
- return "<p>No participants match your filters.</p>"
132
 
133
  html = "<table style='width:100%; border-collapse: collapse;'><tr>"
134
  headers = ["Discord", "Name", "City", "Country", "Looking", "Onlinecheck", "Languages", "Laptop", "Robot", "Skills", "Describe3", "Experience", "Idea"]
@@ -138,7 +115,7 @@ def filter_by_fields(selected_country, selected_city, selected_language):
138
 
139
  for _, row in df.iterrows():
140
  html += "<tr>"
141
- for col in ["discord", "name", "City", "Country", "looking", "onlinecheck", "Languages", "laptop", "robot", "skills", "describe3", "experience", "idea"]:
142
  val = row[col]
143
  if col == "discord":
144
  val = f"<a href='https://discord.com/users/{val}' target='_blank'>{val}</a>"
@@ -146,72 +123,94 @@ def filter_by_fields(selected_country, selected_city, selected_language):
146
  html += "</tr>"
147
 
148
  html += "</table>"
149
- return html
150
 
151
- # Update city dropdown
152
  def update_city_filter(country):
153
- conn = sqlite3.connect(DB_PATH)
154
- c = conn.cursor()
155
- if country == "All":
156
- c.execute("SELECT DISTINCT city FROM teamup")
157
- else:
158
- c.execute("SELECT DISTINCT city FROM teamup WHERE country = ?", (country.title(),))
159
- cities = [r[0].title() for r in c.fetchall() if r[0]]
160
- conn.close()
161
  return gr.update(choices=["All"] + sorted(cities), value="All")
162
 
163
- # Delete
164
  def delete_by_discord(discord, code):
165
  if code != ADMIN_CODE:
166
  return "❌ Invalid admin code."
167
- conn = sqlite3.connect(DB_PATH)
168
- c = conn.cursor()
169
- c.execute("DELETE FROM teamup WHERE lower(discord) = ?", (discord.lower(),))
170
- conn.commit()
171
- conn.close()
172
  return f"πŸ—‘οΈ Deleted user with Discord: {discord}"
173
 
174
- with gr.Blocks(css=".gr-dropdown { max-height: 100px; overflow-y: auto; font-size: 12px; }") as demo:
175
- gr.Markdown("# 🌍 LeRobot Worldwide Hackathon - Team-Up Dashboard")
176
-
177
- with gr.Row():
178
- with gr.Column():
179
- name = gr.Text(label="Name")
180
- discord = gr.Text(label="πŸ‘€ Discord Username *")
181
- city = gr.Text(label="πŸ“ City *")
182
- country = gr.Dropdown(label="🌍 Country *", choices=ALL_COUNTRIES, value="France")
183
- address = gr.Text(label="Address (optional)")
184
- looking = gr.Radio(["Yes", "No"], label="πŸ” Looking for a team?")
185
- onlinecheck = gr.Radio(["Participate Online", "Join a Local Hackathon"], label="πŸš€ I will...")
186
- languages = gr.CheckboxGroup(choices=LANGUAGES, label="Languages Spoken *")
187
- laptop = gr.Text(label="πŸ’» Laptop Setup *")
188
- robot = gr.Text(label="πŸ€– Robot Setup *")
189
- skills = gr.Text(label="🧠 Skills (comma separated)")
190
- describe3 = gr.Text(label="3 Words That Describe You")
191
- experience = gr.Dropdown(choices=["Beginner", "Intermediate", "Advanced"], label="Experience Level", value="Beginner")
192
- idea = gr.Textbox(label="Project Idea (optional)")
193
- submit_btn = gr.Button("Submit or Update βœ…")
194
- status = gr.Textbox(label="", interactive=False)
195
-
196
- with gr.Column():
197
- country_filter = gr.Dropdown(label="Filter by Country", choices=["All"] + ALL_COUNTRIES, value="All")
198
- city_filter = gr.Dropdown(label="Filter by City", choices=["All"], value="All")
199
- language_filter = gr.Dropdown(label="Filter by Language", choices=["All"] + LANGUAGES, value="All")
200
- table_html = gr.HTML(label="Matching Participants")
201
-
202
- country_filter.change(fn=update_city_filter, inputs=[country_filter], outputs=[city_filter])
203
- for dropdown in [country_filter, city_filter, language_filter]:
204
- dropdown.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=[table_html])
205
-
206
- submit_btn.click(fn=submit_profile, inputs=[name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea], outputs=[status])
207
- submit_btn.click(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=[table_html])
208
-
209
- gr.Markdown("---\n### πŸ›‘οΈ Admin Panel")
210
- admin_discord = gr.Text(label="Discord Username")
211
- admin_code = gr.Text(label="Admin Code", type="password")
212
- del_btn = gr.Button("Delete Profile")
213
- del_status = gr.Textbox(label="Status", interactive=False)
214
- del_btn.click(delete_by_discord, inputs=[admin_discord, admin_code], outputs=[del_status])
215
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  demo.launch()
217
-
 
7
  DATA_DIR = "data"
8
  os.makedirs(DATA_DIR, exist_ok=True)
9
 
 
10
  DB_PATH = os.path.join(DATA_DIR, "teamup.db")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  ADMIN_CODE = os.getenv("ADMIN_CODE", "")
12
+ PAGE_SIZE = 20
13
 
14
+ LANGUAGES = ["English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"]
15
+ ALL_COUNTRIES = sorted(set([
16
  "United States of America", "United Kingdom", "India", "France", "Germany", "Canada", "Australia", "Japan", "Brazil", "Mexico",
17
  "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina", "Armenia", "Austria", "Azerbaijan",
18
  "Bangladesh", "Belgium", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bulgaria", "Cambodia",
 
23
  "Qatar", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "South Korea",
24
  "Spain", "Sri Lanka", "Sweden", "Switzerland", "Thailand", "Tunisia", "Turkey", "Ukraine", "United Arab Emirates", "Vietnam",
25
  "Zambia", "Zimbabwe"
26
+ ]))
27
 
28
+ def init_db():
29
+ with sqlite3.connect(DB_PATH) as conn:
30
+ conn.execute("""
31
+ CREATE TABLE IF NOT EXISTS teamup (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ name TEXT,
34
+ discord TEXT UNIQUE,
35
+ city TEXT,
36
+ country TEXT,
37
+ address TEXT,
38
+ looking TEXT,
39
+ onlinecheck TEXT,
40
+ languages TEXT,
41
+ laptop TEXT,
42
+ robot TEXT,
43
+ skills TEXT,
44
+ describe3 TEXT,
45
+ experience TEXT,
46
+ idea TEXT,
47
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
48
+ );
49
+ """)
50
+ init_db()
51
 
 
52
  def submit_profile(name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea):
53
  if not discord or not city or not country or not laptop or not robot:
54
  return "❌ Please fill in all required fields."
55
 
56
  lang_str = ", ".join(languages) if isinstance(languages, list) else languages
57
 
58
+ with sqlite3.connect(DB_PATH) as conn:
59
+ conn.execute("""
60
+ INSERT INTO teamup (discord, name, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea)
61
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
62
+ ON CONFLICT(discord) DO UPDATE SET
63
+ name=excluded.name,
64
+ city=excluded.city,
65
+ country=excluded.country,
66
+ address=excluded.address,
67
+ looking=excluded.looking,
68
+ onlinecheck=excluded.onlinecheck,
69
+ languages=excluded.languages,
70
+ laptop=excluded.laptop,
71
+ robot=excluded.robot,
72
+ skills=excluded.skills,
73
+ describe3=excluded.describe3,
74
+ experience=excluded.experience,
75
+ idea=excluded.idea
76
+ """, (discord, name, city.title(), country.title(), address, looking, onlinecheck, lang_str.lower(), laptop, robot, skills, describe3, experience, idea))
 
 
 
 
77
 
78
+ return "βœ… Profile saved!"
 
 
 
 
79
 
80
+ def filter_by_fields(selected_country, selected_city, selected_language, page):
81
+ offset = (page - 1) * PAGE_SIZE
82
 
83
+ query = "SELECT * FROM teamup"
84
+ filters = []
85
+ params = []
86
 
87
  if selected_country != "All":
88
+ filters.append("country = ?")
89
+ params.append(selected_country.title())
90
  if selected_city != "All":
91
+ filters.append("city = ?")
92
+ params.append(selected_city.title())
93
  if selected_language != "All":
94
+ filters.append("languages LIKE ?")
95
+ params.append(f"%{selected_language.lower()}%")
96
+
97
+ if filters:
98
+ query += " WHERE " + " AND ".join(filters)
99
+ query += " ORDER BY created_at DESC LIMIT ? OFFSET ?"
100
+ params.extend([PAGE_SIZE, offset])
101
+
102
+ with sqlite3.connect(DB_PATH) as conn:
103
+ df = pd.read_sql_query(query, conn, params=params)
104
+ total_query = "SELECT COUNT(*) FROM teamup" + (" WHERE " + " AND ".join(filters) if filters else "")
105
+ total_count = pd.read_sql_query(total_query, conn, params=params[:-2] if filters else []).iloc[0, 0]
106
 
107
  if df.empty:
108
+ return "<p>No participants match your filters.</p>", page, total_count
109
 
110
  html = "<table style='width:100%; border-collapse: collapse;'><tr>"
111
  headers = ["Discord", "Name", "City", "Country", "Looking", "Onlinecheck", "Languages", "Laptop", "Robot", "Skills", "Describe3", "Experience", "Idea"]
 
115
 
116
  for _, row in df.iterrows():
117
  html += "<tr>"
118
+ for col in ["discord", "name", "city", "country", "looking", "onlinecheck", "languages", "laptop", "robot", "skills", "describe3", "experience", "idea"]:
119
  val = row[col]
120
  if col == "discord":
121
  val = f"<a href='https://discord.com/users/{val}' target='_blank'>{val}</a>"
 
123
  html += "</tr>"
124
 
125
  html += "</table>"
126
+ return html, page, total_count
127
 
 
128
  def update_city_filter(country):
129
+ with sqlite3.connect(DB_PATH) as conn:
130
+ if country == "All":
131
+ result = conn.execute("SELECT DISTINCT city FROM teamup").fetchall()
132
+ else:
133
+ result = conn.execute("SELECT DISTINCT city FROM teamup WHERE country = ?", (country.title(),)).fetchall()
134
+ cities = [r[0].title() for r in result if r[0]]
 
 
135
  return gr.update(choices=["All"] + sorted(cities), value="All")
136
 
 
137
  def delete_by_discord(discord, code):
138
  if code != ADMIN_CODE:
139
  return "❌ Invalid admin code."
140
+ with sqlite3.connect(DB_PATH) as conn:
141
+ conn.execute("DELETE FROM teamup WHERE lower(discord) = ?", (discord.lower(),))
 
 
 
142
  return f"πŸ—‘οΈ Deleted user with Discord: {discord}"
143
 
144
+ def download_csv(code):
145
+ if code != ADMIN_CODE:
146
+ raise gr.Error("❌ Invalid admin code.")
147
+ with sqlite3.connect(DB_PATH) as conn:
148
+ df = pd.read_sql_query("SELECT * FROM teamup", conn)
149
+ csv_path = os.path.join(DATA_DIR, "teamup_export.csv")
150
+ df.to_csv(csv_path, index=False)
151
+ return csv_path
152
+
153
+ def interface():
154
+ with gr.Blocks(css=".gr-dropdown { max-height: 100px; overflow-y: auto; font-size: 12px; }") as demo:
155
+ gr.Markdown("# 🌍 LeRobot Worldwide Hackathon - Team-Up Dashboard")
156
+
157
+ with gr.Row():
158
+ with gr.Column():
159
+ name = gr.Text(label="Name")
160
+ discord = gr.Text(label="πŸ‘€ Discord Username *")
161
+ city = gr.Text(label="πŸ“ City *")
162
+ country = gr.Dropdown(label="🌍 Country *", choices=ALL_COUNTRIES, value="France")
163
+ address = gr.Text(label="Address (optional)")
164
+ looking = gr.Radio(["Yes", "No"], label="πŸ” Looking for a team?")
165
+ onlinecheck = gr.Radio(["Participate Online", "Join a Local Hackathon"], label="πŸš€ I will...")
166
+ languages = gr.CheckboxGroup(choices=LANGUAGES, label="Languages Spoken *")
167
+ laptop = gr.Text(label="πŸ’» Laptop Setup *")
168
+ robot = gr.Text(label="πŸ€– Robot Setup *")
169
+ skills = gr.Text(label="🧠 Skills (comma separated)")
170
+ describe3 = gr.Text(label="3 Words That Describe You")
171
+ experience = gr.Dropdown(choices=["Beginner", "Intermediate", "Advanced"], label="Experience Level", value="Beginner")
172
+ idea = gr.Textbox(label="Project Idea (optional)")
173
+ submit_btn = gr.Button("Submit or Update βœ…")
174
+ status = gr.Textbox(label="", interactive=False)
175
+
176
+ with gr.Column():
177
+ country_filter = gr.Dropdown(label="Filter by Country", choices=["All"] + ALL_COUNTRIES, value="All")
178
+ city_filter = gr.Dropdown(label="Filter by City", choices=["All"], value="All")
179
+ language_filter = gr.Dropdown(label="Filter by Language", choices=["All"] + LANGUAGES, value="All")
180
+ page_state = gr.Number(value=1, visible=False)
181
+ table_html = gr.HTML(label="Matching Participants")
182
+ prev_btn = gr.Button("⬅️ Previous Page")
183
+ next_btn = gr.Button("➑️ Next Page")
184
+
185
+ submit_btn.click(submit_profile, inputs=[name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea], outputs=[status])
186
+ submit_btn.click(filter_by_fields, inputs=[country_filter, city_filter, language_filter, page_state], outputs=[table_html, page_state, gr.Number(visible=False)])
187
+
188
+ country_filter.change(update_city_filter, inputs=[country_filter], outputs=[city_filter])
189
+
190
+ for dropdown in [country_filter, city_filter, language_filter]:
191
+ dropdown.change(lambda c, ci, l: (1,), inputs=[country_filter, city_filter, language_filter], outputs=[page_state])
192
+ dropdown.change(filter_by_fields, inputs=[country_filter, city_filter, language_filter, page_state], outputs=[table_html, page_state, gr.Number(visible=False)])
193
+
194
+ prev_btn.click(lambda p: max(p - 1, 1), inputs=[page_state], outputs=[page_state])
195
+ prev_btn.click(filter_by_fields, inputs=[country_filter, city_filter, language_filter, page_state], outputs=[table_html, page_state, gr.Number(visible=False)])
196
+
197
+ next_btn.click(lambda p: p + 1, inputs=[page_state], outputs=[page_state])
198
+ next_btn.click(filter_by_fields, inputs=[country_filter, city_filter, language_filter, page_state], outputs=[table_html, page_state, gr.Number(visible=False)])
199
+
200
+ gr.Markdown("---\n### πŸ›‘οΈ Admin Panel")
201
+ admin_discord = gr.Text(label="Discord Username")
202
+ admin_code = gr.Text(label="Admin Code", type="password")
203
+ del_btn = gr.Button("Delete Profile")
204
+ del_status = gr.Textbox(label="Status", interactive=False)
205
+ del_btn.click(delete_by_discord, inputs=[admin_discord, admin_code], outputs=[del_status])
206
+
207
+ gr.Markdown("---\n### πŸ“₯ Admin Export CSV")
208
+ export_code = gr.Text(label="Admin Code", type="password")
209
+ download_btn = gr.Button("Generate and Download CSV")
210
+ download_file = gr.File(label="CSV Export", interactive=False)
211
+ download_btn.click(download_csv, inputs=[export_code], outputs=[download_file])
212
+
213
+ return demo
214
+
215
+ demo = interface()
216
  demo.launch()