Abhishek Thakur commited on
Commit
bf3d263
·
1 Parent(s): 7b9d0c2

option to change team name

Browse files
competitions/app.py CHANGED
@@ -51,6 +51,11 @@ if REQUIREMENTS_FNAME:
51
  utils.install_requirements(REQUIREMENTS_FNAME)
52
 
53
 
 
 
 
 
 
54
  class User(BaseModel):
55
  user_token: str
56
 
@@ -193,6 +198,7 @@ async def my_submissions(request: Request, user: User):
193
  "submissions": "",
194
  "submission_text": SUBMISSION_TEXT.format(COMP_INFO.submission_limit),
195
  "error": "**Invalid token**",
 
196
  }
197
  }
198
  subs = subs.to_dict(orient="records")
@@ -204,11 +210,14 @@ async def my_submissions(request: Request, user: User):
204
  submission_text = SUBMISSION_TEXT.format(COMP_INFO.submission_limit)
205
  submission_selection_text = SUBMISSION_SELECTION_TEXT.format(COMP_INFO.selection_limit)
206
 
 
 
207
  resp = {
208
  "response": {
209
  "submissions": subs,
210
  "submission_text": submission_text + submission_selection_text,
211
  "error": error,
 
212
  }
213
  }
214
  return resp
@@ -282,3 +291,18 @@ def update_selected_submissions(request: Request, user_sub: UserSubmissionUpdate
282
  }
283
  sub.update_selected_submissions(user_token=user_sub.user_token, selected_submission_ids=submission_ids)
284
  return {"success": True, "error": ""}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  utils.install_requirements(REQUIREMENTS_FNAME)
52
 
53
 
54
+ class UserTeamNameUpdate(BaseModel):
55
+ user_token: str
56
+ new_team_name: str
57
+
58
+
59
  class User(BaseModel):
60
  user_token: str
61
 
 
198
  "submissions": "",
199
  "submission_text": SUBMISSION_TEXT.format(COMP_INFO.submission_limit),
200
  "error": "**Invalid token**",
201
+ "team_name": "",
202
  }
203
  }
204
  subs = subs.to_dict(orient="records")
 
210
  submission_text = SUBMISSION_TEXT.format(COMP_INFO.submission_limit)
211
  submission_selection_text = SUBMISSION_SELECTION_TEXT.format(COMP_INFO.selection_limit)
212
 
213
+ team_name = utils.get_team_name(user.user_token, COMPETITION_ID, HF_TOKEN)
214
+
215
  resp = {
216
  "response": {
217
  "submissions": subs,
218
  "submission_text": submission_text + submission_selection_text,
219
  "error": error,
220
+ "team_name": team_name,
221
  }
222
  }
223
  return resp
 
291
  }
292
  sub.update_selected_submissions(user_token=user_sub.user_token, selected_submission_ids=submission_ids)
293
  return {"success": True, "error": ""}
294
+
295
+
296
+ @app.post("/update_team_name", response_class=JSONResponse)
297
+ def update_team_name(request: Request, user_team: UserTeamNameUpdate):
298
+ if USE_OAUTH == 1:
299
+ if request.session.get("oauth_info") is not None:
300
+ user_token = request.session.get("oauth_info")["access_token"]
301
+
302
+ user_token = user_team.user_token
303
+
304
+ try:
305
+ utils.update_team_name(user_token, user_team.new_team_name, COMPETITION_ID, HF_TOKEN)
306
+ return {"success": True, "error": ""}
307
+ except Exception as e:
308
+ return {"success": False, "error": str(e)}
competitions/templates/index.html CHANGED
@@ -137,7 +137,12 @@
137
  // contentDiv.innerHTML = marked.parse(data.response.submission_text) + data.response.submissions;
138
  if (data.response.submissions && data.response.submissions.length > 0 && data.response.error.length == 0) {
139
  // Start building the table HTML
140
- let tableHTML = '<table border="1"><tr><th>Datetime</th><th>Submission ID</th><th>Public Score</th><th>Submission Comment</th><th>Selected</th><th>Status</th></tr>';
 
 
 
 
 
141
 
142
  // Iterate over each submission and add it to the table
143
  data.response.submissions.forEach(submission => {
@@ -154,10 +159,14 @@
154
  // Close the table HTML and set it as the content
155
  tableHTML += '</table>';
156
  tableHTML += '<button id="updateSelectedSubmissionsButton" type="button" class="confirm text-white bg-green-600 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center me-2">Update Selected Submissions</button>';
 
157
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + tableHTML;
158
  document.getElementById('updateSelectedSubmissionsButton').addEventListener('click', function () {
159
  updateSelectedSubmissions(userToken);
160
  });
 
 
 
161
  } else {
162
  // Display message if there are no submissions
163
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + marked.parse(data.response.error);
@@ -192,6 +201,45 @@
192
  });
193
  }
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  // Find the 'Home' link in the sidebar
196
  const homeLink = document.getElementById('home');
197
  const datasetLink = document.getElementById('dataset');
@@ -200,6 +248,7 @@
200
  const newSubmission = document.getElementById('new_submission');
201
  const mySubmissions = document.getElementById('my_submissions');
202
  const submissionInfo = document.getElementById('submission_info');
 
203
 
204
  // Add a click event listener to the 'Home' link
205
  homeLink.addEventListener('click', function (event) {
@@ -234,6 +283,10 @@
234
  event.preventDefault(); // Prevent the default link behavior
235
  fetchAndDisplaySubmissionInfo(); // Fetch and display info on click
236
  });
 
 
 
 
237
 
238
  // Fetch and display info when the page loads
239
  fetchAndDisplayCompetitionInfo();
@@ -307,6 +360,17 @@
307
  <span class="flex-1 ms-3 whitespace-nowrap">Dataset</span>
308
  </a>
309
  </li>
 
 
 
 
 
 
 
 
 
 
 
310
  <li>
311
  <button type="button"
312
  class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100"
@@ -373,18 +437,6 @@
373
  </li>
374
  </ul>
375
  </li>
376
- <!-- <li>
377
- <a href="#"
378
- class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-gray-100">
379
- <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
380
- aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
381
- viewBox="0 0 20 18">
382
- <path
383
- d="M14 2a3.963 3.963 0 0 0-1.4.267 6.439 6.439 0 0 1-1.331 6.638A4 4 0 1 0 14 2Zm1 9h-1.264A6.957 6.957 0 0 1 15 15v2a2.97 2.97 0 0 1-.184 1H19a1 1 0 0 0 1-1v-1a5.006 5.006 0 0 0-5-5ZM6.5 9a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM8 10H5a5.006 5.006 0 0 0-5 5v2a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-2a5.006 5.006 0 0 0-5-5Z" />
384
- </svg>
385
- <span class="flex-1 ms-3 whitespace-nowrap">Team</span>
386
- </a>
387
- </li> -->
388
  <li id="userToken">
389
  <label for="user_token" class="text-xs font-medium">Hugging Face <a
390
  href="https://huggingface.co/settings/tokens" target="_blank">Token</a> (read-only)
@@ -581,4 +633,49 @@
581
  }
582
  </script>
583
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
584
  </html>
 
137
  // contentDiv.innerHTML = marked.parse(data.response.submission_text) + data.response.submissions;
138
  if (data.response.submissions && data.response.submissions.length > 0 && data.response.error.length == 0) {
139
  // Start building the table HTML
140
+ let tableHTML = `
141
+ <div class="flex items-center">
142
+ <input type="text" name="team_name" id="team_name" class="mt-1 mb-1 block me-2" value="${data.response.team_name}">
143
+ <button id="updateTeamNameButton" type="button" class="confirm text-white bg-green-600 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center me-2">Update Team Name</button>
144
+ </div>`;
145
+ tableHTML += '<table border="1"><tr><th>Datetime</th><th>Submission ID</th><th>Public Score</th><th>Submission Comment</th><th>Selected</th><th>Status</th></tr>';
146
 
147
  // Iterate over each submission and add it to the table
148
  data.response.submissions.forEach(submission => {
 
159
  // Close the table HTML and set it as the content
160
  tableHTML += '</table>';
161
  tableHTML += '<button id="updateSelectedSubmissionsButton" type="button" class="confirm text-white bg-green-600 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center me-2">Update Selected Submissions</button>';
162
+ // add a text field which displays team name and a button to update team name
163
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + tableHTML;
164
  document.getElementById('updateSelectedSubmissionsButton').addEventListener('click', function () {
165
  updateSelectedSubmissions(userToken);
166
  });
167
+ document.getElementById('updateTeamNameButton').addEventListener('click', function () {
168
+ updateTeamName(userToken);
169
+ });
170
  } else {
171
  // Display message if there are no submissions
172
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + marked.parse(data.response.error);
 
201
  });
202
  }
203
 
204
+ function fetchAndDisplayTeamInfo() {
205
+ const apiEndpoint = '/team_info';
206
+ const userToken = document.getElementById('user_token').value;
207
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
208
+ articleLoadingSpinner.classList.remove('hidden');
209
+
210
+ const requestOptions = {
211
+ method: 'POST',
212
+ headers: {
213
+ 'Content-Type': 'application/json',
214
+ },
215
+ body: JSON.stringify({ "user_token": userToken })
216
+ };
217
+ fetch(apiEndpoint, requestOptions)
218
+ .then(response => {
219
+ if (!response.ok) {
220
+ throw new Error('Network response was not ok');
221
+ }
222
+ return response.json(); // Parse the JSON response
223
+ })
224
+ .then(data => {
225
+ // Populate the 'content' div with the HTML from the response
226
+ const contentDiv = document.getElementById('content');
227
+ if (data.team_exists) {
228
+ contentHTML = "<h2>Team</h2>";
229
+ contentHTML += "<p>" + data.team_name + "</p>";
230
+ contentDiv.innerHTML = marked.parse(contentHTML);
231
+ } else {
232
+ contentDiv.innerHTML = marked.parse(data.response);
233
+ }
234
+ contentDiv.innerHTML = marked.parse(data.response);
235
+ articleLoadingSpinner.classList.add('hidden');
236
+ })
237
+ .catch(error => {
238
+ console.error('There has been a problem with your fetch operation:', error);
239
+ articleLoadingSpinner.classList.add('hidden');
240
+ });
241
+ }
242
+
243
  // Find the 'Home' link in the sidebar
244
  const homeLink = document.getElementById('home');
245
  const datasetLink = document.getElementById('dataset');
 
248
  const newSubmission = document.getElementById('new_submission');
249
  const mySubmissions = document.getElementById('my_submissions');
250
  const submissionInfo = document.getElementById('submission_info');
251
+ const teamLink = document.getElementById('team');
252
 
253
  // Add a click event listener to the 'Home' link
254
  homeLink.addEventListener('click', function (event) {
 
283
  event.preventDefault(); // Prevent the default link behavior
284
  fetchAndDisplaySubmissionInfo(); // Fetch and display info on click
285
  });
286
+ teamLink.addEventListener('click', function (event) {
287
+ event.preventDefault(); // Prevent the default link behavior
288
+ fetchAndDisplayTeamInfo(); // Fetch and display info on click
289
+ });
290
 
291
  // Fetch and display info when the page loads
292
  fetchAndDisplayCompetitionInfo();
 
360
  <span class="flex-1 ms-3 whitespace-nowrap">Dataset</span>
361
  </a>
362
  </li>
363
+ <li>
364
+ <a href="#" id="team" class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-gray-100">
365
+ <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
366
+ aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
367
+ viewBox="0 0 20 18">
368
+ <path
369
+ d="M14 2a3.963 3.963 0 0 0-1.4.267 6.439 6.439 0 0 1-1.331 6.638A4 4 0 1 0 14 2Zm1 9h-1.264A6.957 6.957 0 0 1 15 15v2a2.97 2.97 0 0 1-.184 1H19a1 1 0 0 0 1-1v-1a5.006 5.006 0 0 0-5-5ZM6.5 9a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM8 10H5a5.006 5.006 0 0 0-5 5v2a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-2a5.006 5.006 0 0 0-5-5Z" />
370
+ </svg>
371
+ <span class="flex-1 ms-3 whitespace-nowrap">Team</span>
372
+ </a>
373
+ </li>
374
  <li>
375
  <button type="button"
376
  class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100"
 
437
  </li>
438
  </ul>
439
  </li>
 
 
 
 
 
 
 
 
 
 
 
 
440
  <li id="userToken">
441
  <label for="user_token" class="text-xs font-medium">Hugging Face <a
442
  href="https://huggingface.co/settings/tokens" target="_blank">Token</a> (read-only)
 
633
  }
634
  </script>
635
 
636
+ <script>
637
+ function updateTeamName(userToken) {
638
+ const teamName = document.getElementById('team_name').value;
639
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
640
+ articleLoadingSpinner.classList.remove('hidden');
641
+
642
+ const updateEndpoint = '/update_team_name';
643
+ const requestOptions = {
644
+ method: 'POST',
645
+ headers: {
646
+ 'Content-Type': 'application/json',
647
+ },
648
+ body: JSON.stringify({
649
+ "user_token": userToken,
650
+ "new_team_name": teamName
651
+ })
652
+ };
653
+
654
+ fetch(updateEndpoint, requestOptions)
655
+ .then(response => {
656
+ if (!response.ok) {
657
+ throw new Error('Network response was not ok');
658
+ }
659
+ return response.json();
660
+ })
661
+ .then(data => {
662
+ if (data.success) {
663
+ // Optionally, display a success message or handle accordingly
664
+ console.log('Update successful');
665
+ articleLoadingSpinner.classList.add('hidden');
666
+ } else {
667
+ // Handle failure case
668
+ console.log('Update failed');
669
+ articleLoadingSpinner.classList.add('hidden');
670
+ alert(data.error);
671
+ }
672
+ // Refresh submissions display
673
+ fetchAndDisplaySubmissions();
674
+ })
675
+ .catch(error => {
676
+ console.error('There was a problem with the fetch operation for updating:', error);
677
+ });
678
+ }
679
+ </script>
680
+
681
  </html>
competitions/utils.py CHANGED
@@ -230,3 +230,73 @@ def can_user_submit_before_start(user_token, competition_organization):
230
  if org["name"] == competition_organization:
231
  return True
232
  return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  if org["name"] == competition_organization:
231
  return True
232
  return False
233
+
234
+
235
+ def get_team_name(user_token, competition_id, hf_token):
236
+ user_info = user_authentication(token=user_token)
237
+ user_id = user_info["id"]
238
+ user_team = hf_hub_download(
239
+ repo_id=competition_id,
240
+ filename="user_team.json",
241
+ token=hf_token,
242
+ repo_type="dataset",
243
+ )
244
+ with open(user_team, "r", encoding="utf-8") as f:
245
+ user_team = json.load(f)
246
+
247
+ if user_id not in user_team:
248
+ return None
249
+
250
+ team_id = user_team[user_id]
251
+
252
+ team_metadata = hf_hub_download(
253
+ repo_id=competition_id,
254
+ filename="teams.json",
255
+ token=hf_token,
256
+ repo_type="dataset",
257
+ )
258
+ with open(team_metadata, "r", encoding="utf-8") as f:
259
+ team_metadata = json.load(f)
260
+
261
+ team_name = team_metadata[team_id]["name"]
262
+ return team_name
263
+
264
+
265
+ def update_team_name(user_token, new_team_name, competition_id, hf_token):
266
+ user_info = user_authentication(token=user_token)
267
+ user_id = user_info["id"]
268
+ user_team = hf_hub_download(
269
+ repo_id=competition_id,
270
+ filename="user_team.json",
271
+ token=hf_token,
272
+ repo_type="dataset",
273
+ )
274
+ with open(user_team, "r", encoding="utf-8") as f:
275
+ user_team = json.load(f)
276
+
277
+ if user_id not in user_team:
278
+ raise Exception("User is not part of a team")
279
+
280
+ team_id = user_team[user_id]
281
+
282
+ team_metadata = hf_hub_download(
283
+ repo_id=competition_id,
284
+ filename="teams.json",
285
+ token=hf_token,
286
+ repo_type="dataset",
287
+ )
288
+ with open(team_metadata, "r", encoding="utf-8") as f:
289
+ team_metadata = json.load(f)
290
+
291
+ team_metadata[team_id]["name"] = new_team_name
292
+ team_metadata_json = json.dumps(team_metadata, indent=4)
293
+ team_metadata_json_bytes = team_metadata_json.encode("utf-8")
294
+ team_metadata_json_buffer = io.BytesIO(team_metadata_json_bytes)
295
+ api = HfApi(token=hf_token)
296
+ api.upload_file(
297
+ path_or_fileobj=team_metadata_json_buffer,
298
+ path_in_repo="teams.json",
299
+ repo_id=competition_id,
300
+ repo_type="dataset",
301
+ )
302
+ return new_team_name