diff --git a/apps/challenges/models.py b/apps/challenges/models.py index a07b475e9f..dfb105235e 100644 --- a/apps/challenges/models.py +++ b/apps/challenges/models.py @@ -36,7 +36,7 @@ def __init__(self, *args, **kwargs): self._original_evaluation_script = self.evaluation_script self._original_approved_by_admin = self.approved_by_admin - title = models.CharField(max_length=100, db_index=True) + title = models.CharField(max_length=100, db_index=True, unique=True) short_description = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True) terms_and_conditions = models.TextField(null=True, blank=True) @@ -100,7 +100,7 @@ def __init__(self, *args, **kwargs): default=8, verbose_name="EC2 storage (GB)" ) ephemeral_storage = models.PositiveIntegerField( - default=20, verbose_name="Ephemeral Storage (GB)" + default=21, verbose_name="Ephemeral Storage (GB)" ) featured = models.BooleanField( default=False, verbose_name="Featured", db_index=True diff --git a/apps/challenges/views.py b/apps/challenges/views.py index 808aa28c30..4f8c0215c8 100644 --- a/apps/challenges/views.py +++ b/apps/challenges/views.py @@ -4449,6 +4449,11 @@ def create_or_update_challenge(request, challenge_host_team_pk): challenge_pk = request.data.get("id") if not challenge_pk: + if Challenge.objects.filter(title=request.data.get("title")).exists(): + response_data = { + "error": "The challenge title already exists. Please choose a different title." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) data = request.data.copy() data["is_docker_based"] = True data["enable_forum"] = True @@ -4481,6 +4486,11 @@ def create_or_update_challenge(request, challenge_host_team_pk): } return Response(response_data, status=status.HTTP_404_NOT_FOUND) challenge.title = request.data.get("title") + if Challenge.objects.filter(title=challenge.title).exclude(id=challenge_pk).exists(): + response_data = { + "error": "The challenge title already exists. Please choose a different title." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) challenge.short_description = request.data.get("short_description") challenge.description = request.data.get("description") challenge.evaluation_details = request.data.get("evaluation_details") @@ -4489,7 +4499,11 @@ def create_or_update_challenge(request, challenge_host_team_pk): challenge.leaderboard_description = request.data.get("leaderboard_description") challenge.start_date = datetime.strptime(request.data.get("start_date"), "%Y-%m-%dT%H:%M:%S%z") challenge.end_date = datetime.strptime(request.data.get("end_date"), "%Y-%m-%dT%H:%M:%S%z") - challenge.image = simple_image_url(request.data.get("image")) + image = request.data.get("image") + if isinstance(image, str): + challenge.image = simple_image_url(image) + else: + challenge.image = image published = request.data.get("published") if published is not None: published = published.lower() == 'true' @@ -4533,6 +4547,12 @@ def create_or_update_challenge_phase(request, challenge_host_team_pk, challenge_ challenge_phase_pk = request.data.get("id") if not challenge_phase_pk: try: + codename = request.data["codename"] + if ChallengePhase.objects.filter(challenge=challenge, codename=codename).exists(): + response_data = { + "error": f"A ChallengePhase with the codename '{codename}' already exists for the given challenge." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) with transaction.atomic(): request.data["slug"] = "{}-{}-{}".format( challenge.title.split(" ")[0].lower(), @@ -4585,6 +4605,13 @@ def create_or_update_challenge_phase(request, challenge_host_team_pk, challenge_ except ChallengePhase.DoesNotExist: response_data = {"error": "Challenge Phase does not exist"} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + codename = request.data["codename"] + if ChallengePhase.objects.filter(challenge=challenge, codename=codename).exclude(id=challenge_phase_pk).exists(): + response_data = { + "error": f"A ChallengePhase with the codename '{codename}' already exists for the given challenge." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + challenge_phase.codename = codename challenge_phase.name = request.data.get("name") challenge_phase.description = request.data.get("description") challenge_phase.leaderboard_public = request.data.get("leaderboard_public") @@ -4593,7 +4620,6 @@ def create_or_update_challenge_phase(request, challenge_host_team_pk, challenge_ challenge_phase.start_date = datetime.strptime(request.data.get("start_date"), "%Y-%m-%dT%H:%M:%S%z") challenge_phase.end_date = datetime.strptime(request.data.get("start_date"), "%Y-%m-%dT%H:%M:%S%z") challenge_phase.test_annotation_file = request.data.get("test_annotation_file") - challenge_phase.codename = request.data.get("codename") challenge_phase.max_submissions_per_day = request.data.get("max_submissions_per_day") challenge_phase.max_submissions_per_month = request.data.get("max_submissions_per_month") challenge_phase.max_submissions = request.data.get("max_submissions") diff --git a/apps/jobs/sender.py b/apps/jobs/sender.py index 6e6c98bf6b..5561c391b0 100644 --- a/apps/jobs/sender.py +++ b/apps/jobs/sender.py @@ -52,7 +52,7 @@ def get_or_create_sqs_queue(queue_name, challenge=None): ) if queue_name == "": - queue_name = "evalai_submission_queue" + queue_name = "arena" # Check if the queue exists. If not, then create one. try: diff --git a/frontend/src/components/Editor.vue b/frontend/src/components/Editor.vue index e32a2eae3d..4b647acd55 100644 --- a/frontend/src/components/Editor.vue +++ b/frontend/src/components/Editor.vue @@ -29,6 +29,7 @@ const toolbarConfig = { }; const editorConfig = { placeholder: '', + maxLength: 5000, MENU_CONF: { uploadImage: { server: import.meta.env.VITE_APP_BASE_API + '/api/web/upload_image/', diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index ce36dd492b..eba3d81c66 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -207,9 +207,7 @@ export default { }, participate: { continue: 'Continue', - accept_text1: 'please accept the', - accept_text2: 'rules and terms', - accept_text3: 'in order to participate.', + accept_text: 'Please read and accept the rules and conditions.', accept_label: 'I accept the terms and conditions.', }, submission: { @@ -282,17 +280,17 @@ export default { editChall: 'Edit Challenge', title: 'Title', titlePH: 'Autonomous Driving Algorithms Challenge', - shortDesc: 'Short_description', + shortDesc: 'Short description', shortDescPH: 'Autonomous Driving Algorithm Challenge for each submission', desc: 'Description', - evaluation: 'Evaluation_details', - termsConditions: 'Terms_and_conditions', + evaluation: 'Evaluation details', + termsConditions: 'Terms and conditions', image: 'Image', imagePH: 'Please upload logo jpg format is supported', - SubmiGuide: 'Submission_guidelines', - lbDesc: 'Leaderboard_description', - startDate: 'Start_date', - endDate: 'End_date', + SubmiGuide: 'Submission guidelines', + lbDesc: 'Leaderboard description', + startDate: 'Start date', + endDate: 'End date', published: 'Published', createSuccess: 'Contest creation success', updateSuccess: 'Challenge updated successfully!', @@ -302,18 +300,18 @@ export default { editPhase: 'Edit Phase', name: 'Name', desc: 'Description', - lbPublic: 'Leaderboard_public', - isPublic: 'Is_public', - isSubmiPublic: 'Is_submission_public', - startDate: 'Start_date', - endDate: 'End_date', + lbPublic: 'Leaderboard public', + isPublic: 'Is public', + isSubmiPublic: 'Is submission public', + startDate: 'Start date', + endDate: 'End date', codename: 'Codename', - maxSubmiPerDay: 'Max_submissions_per_day', - maxSubmiPerMonth: 'Max_submissions_per_month', - maxSubmissions: 'Max_submissions', - isRestrictedToSelectOneSubmission: 'Is_restricted_to_select_one_submission', - isPartialSubmissionEvaluationEnabled: 'Is_partial_submission_evaluation_enabled', - allowedSubmissionFileTypes: 'Allowed_submission_file_types', + maxSubmiPerDay: 'Max submissions perday', + maxSubmiPerMonth: 'Max submissions per month', + maxSubmissions: 'Max submissions', + isRestrictedToSelectOneSubmission: 'Is restricted to select onesubmission', + isPartialSubmissionEvaluationEnabled: 'Is partial submission evaluation enabled', + allowedSubmissionFileTypes: 'Allowed submission file types', createSuccess: 'Phase creation successfully!', updateSuccess: 'Phase updated successfully!', }, diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 3bb76317b8..1079a4b6cb 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -205,9 +205,7 @@ export default { }, participate: { continue: '继续', - accept_text1: '请接受', - accept_text2: '规则和条款', - accept_text3: '才能参加比赛。', + accept_text: '请阅读并接受规则和条件。', accept_label: '我接受条款和条件', }, submission: { diff --git a/frontend/src/permission.js b/frontend/src/permission.js index 24a522c165..f4d4249d6c 100644 --- a/frontend/src/permission.js +++ b/frontend/src/permission.js @@ -23,9 +23,6 @@ router.beforeEach((to, from, next) => { .then((res) => { next({ path: '/' }); }) - .catch((err) => { - next({ path: '/' }); - }); }); } else if (to.path.startsWith('/host')) { if (store.state.isHost === 1) { diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 9d256e35c8..403792e4e8 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -93,7 +93,7 @@ export default createStore({ removeToken(); removeJwtToken(); commit('clearStore'); - reject(error); + resolve(); }); }); }, diff --git a/frontend/src/styles/global.scss b/frontend/src/styles/global.scss index 2d06fe1344..3ab94b99f9 100644 --- a/frontend/src/styles/global.scss +++ b/frontend/src/styles/global.scss @@ -393,6 +393,29 @@ body { } } +// 折叠面板 +.el-collapse.oa-collapse { + border: none; + margin-top: -16px; + // margin-bottom: 24px; + --el-collapse-border-color: rgba(67, 77, 96, 0.6); + .el-collapse-item__header { + font-size: 14px; + font-weight: 700; + } + .el-collapse-item__wrap { + border-bottom-color: rgba(67, 77, 96, 0.6); + } + .el-collapse-item:nth-last-child(1) { + .el-collapse-item__wrap { + border-bottom: none; + } + .el-collapse-item__header { + border-bottom-color: transparent; + } + } +} + // 已选择项tag框 .custom-selected-tag { &.el-tag { diff --git a/frontend/src/views/challenge/Detail.vue b/frontend/src/views/challenge/Detail.vue index 94e04675ad..eb0555216e 100644 --- a/frontend/src/views/challenge/Detail.vue +++ b/frontend/src/views/challenge/Detail.vue @@ -19,7 +19,10 @@ - + { }); }; -const openTerm = () => { - activeName.value = 'overview'; - setTimeout(() => { - let dom = document.querySelector('#term'); - dom && dom.scrollIntoView(); - }, 200); -}; const clearPartTeam = (tabId) => { teamDetail.value = undefined; activeName.value = tabId; diff --git a/frontend/src/views/challenge/Leaderboard.vue b/frontend/src/views/challenge/Leaderboard.vue index c6d173525d..5092cbf83b 100644 --- a/frontend/src/views/challenge/Leaderboard.vue +++ b/frontend/src/views/challenge/Leaderboard.vue @@ -1,14 +1,14 @@