').html(texExpression).contents();
- var compiledTemplate = $compile(template)(scope);
- element.empty().append(compiledTemplate);
- $timeout(function() {
- /* eslint-disable no-undef */
- MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
- }, 0);
- });
- }
- };
- }]);
- }());
diff --git a/frontend/src/js/directives/validation.directives.js b/frontend/src/js/directives/validation.directives.js
deleted file mode 100644
index 6b9bd78a50..0000000000
--- a/frontend/src/js/directives/validation.directives.js
+++ /dev/null
@@ -1,41 +0,0 @@
-var compareTo = function() {
- return {
- require: "ngModel",
- scope: {
- otherModelValue: "=compareTo"
- },
- link: function(scope, element, attributes, ngModel) {
-
- ngModel.$validators.compareTo = function(modelValue) {
- return modelValue == scope.otherModelValue;
- };
-
- scope.$watch("otherModelValue", function() {
- ngModel.$validate();
- });
- }
- };
-};
-var match = function() {
- return {
- require: "ngModel",
- scope: {
- otherModelValue: "=match"
- },
- link: function(scope, element, attributes, ngModel) {
-
- ngModel.$validators.match = function(modelValue) {
- return modelValue != scope.otherModelValue;
- };
-
- scope.$watch("otherModelValue", function() {
- ngModel.$validate();
- });
- }
- };
-};
-
-angular
- .module('evalai')
- .directive("compareTo", compareTo)
- .directive("match", match);
diff --git a/frontend/src/js/filters/filters.js b/frontend/src/js/filters/filters.js
deleted file mode 100644
index 031356eaeb..0000000000
--- a/frontend/src/js/filters/filters.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// define filters here
-
-// filter to get ceiling value
-(function() {
-
- 'use strict';
-
- angular
- .module('evalai')
- .filter('ceil', ceil);
-
- function ceil() {
- return function(input) {
- return Math.ceil(input);
- };
- }
-
- angular.module('evalai')
- .filter('format_execution_time', format_execution_time);
-
- function format_execution_time() {
- return function (execution_time) {
- var executiontime = new Date(execution_time * 1000);
- var days = (executiontime.getUTCDate() - 1);
- var hours = executiontime.getUTCHours();
- var minutes = executiontime.getUTCMinutes();
- var seconds = executiontime.getSeconds();
- var timeString = (execution_time != 0) ? (
- (days !=0 ? days.toString().padStart(2, '0') + ' day ' : '') +
- (hours !=0 ? hours.toString().padStart(2, '0') + ' hr ' : '') +
- (minutes != 0 ? minutes.toString().padStart(2, '0') + ' min ' : '') +
- (seconds !=0 ? seconds.toString().padStart(2, '0') + ' sec' : '')
- ) : (seconds.toString().padStart(2, '0') + ' sec');
- return timeString;
- };
- }
-
-})();
diff --git a/frontend/src/js/route-config/route-config.js b/frontend/src/js/route-config/route-config.js
deleted file mode 100644
index cc678f2c82..0000000000
--- a/frontend/src/js/route-config/route-config.js
+++ /dev/null
@@ -1,805 +0,0 @@
-/**
- * Config for the router
- */
-
-(function () {
- 'use strict';
- angular
- .module('evalai')
- .config(configure);
-
- var baseUrl = "dist/views";
-
- configure.$inject = ['$stateProvider', '$urlRouterProvider', '$locationProvider', '$urlMatcherFactoryProvider'];
-
- function configure($stateProvider, $urlRouterProvider, $locationProvider, $urlMatcherFactoryProvider) {
-
- //in order to prevent 404 for trailing '/' in urls
- $urlMatcherFactoryProvider.strictMode(false);
-
- // formating hashed url
- $locationProvider.html5Mode({
- enabled: true,
- requireBase: true
- });
-
- // Index url definition
- var home = {
- name: "home",
- url: "/",
- templateUrl: baseUrl + "/web/landing.html",
- controller: 'MainCtrl',
- controllerAs: 'main',
- title: "Welcome"
- };
-
- // Auth related urls
- var auth = {
- name: "auth",
- url: "/auth",
- templateUrl: baseUrl + "/web/auth/auth.html",
- controller: 'AuthCtrl',
- controllerAs: 'auth',
- abstract: true,
- title: 'Auth'
- };
-
- var login = {
- name: "auth.login",
- parent: "auth",
- url: "/login",
- templateUrl: baseUrl + "/web/auth/login.html",
- title: 'Login',
- authpage: true
- };
-
- var signup = {
- name: "auth.signup",
- parent: "auth",
- url: "/signup",
- templateUrl: baseUrl + "/web/auth/signup.html",
- title: 'SignUp',
- authpage: true
- };
-
- var verify_email = {
- name: "auth.verify-email",
- parent: "auth",
- url: "/api/auth/registration/account-confirm-email/:email_conf_key",
- templateUrl: baseUrl + "/web/auth/verify-email.html",
- title: "Email Verify",
- authpage: true
- };
-
- var reset_password = {
- name: "auth.reset-password",
- parent: "auth",
- url: "/reset-password",
- templateUrl: baseUrl + "/web/auth/reset-password.html",
- title: "Reset Password",
- authpage: true
- };
-
- var reset_password_confirm = {
- name: "auth.reset-password-confirm",
- parent: "auth",
- url: "/api/password/reset/confirm/:user_id/:reset_token",
- templateUrl: baseUrl + "/web/auth/reset-password-confirm.html",
- title: "Reset Password Confirm",
- authpage: true
- };
-
- var logout = {
- name: "auth.logout",
- parent: "auth",
- url: "/logout",
- authenticate: true,
- title: 'Logout'
- };
-
- // main app 'web'
- var web = {
- name: "web",
- url: "/web",
- templateUrl: baseUrl + "/web/web.html",
- controller: 'WebCtrl',
- controllerAs: 'web',
- abstract: true
- };
-
- var dashboard = {
- name: "web.dashboard",
- parent: "web",
- url: "/dashboard",
- templateUrl: baseUrl + "/web/dashboard.html",
- controller: 'DashCtrl',
- controllerAs: 'dash',
- title: 'Dashboard',
- authenticate: true
- };
-
- var teams = {
- name: "web.teams",
- parent: "web",
- url: "/teams",
- templateUrl: baseUrl + "/web/teams.html",
- controller: 'TeamsCtrl',
- controllerAs: 'teams',
- title: 'Participating Teams',
- authenticate: true
- };
-
- var hosted_challenges = {
- name: "web.hosted-challenge",
- parent: "web",
- url: "/hosted-challenges",
- templateUrl: baseUrl + "/web/hosted-challenges.html",
- controller: 'HostedChallengesCtrl',
- controllerAs: 'hostedChallenges',
- title: 'Hosted Challenges',
- authenticate: true
- };
-
- var host_analytics = {
- name: "web.host-analytics",
- parent: "web",
- url: "/host-analytics",
- templateUrl: baseUrl + "/web/analytics/host-analytics.html",
- controller: 'AnalyticsCtrl',
- controllerAs: 'analytics',
- title: 'Host Challenge Analytics',
- authenticate: true
- };
-
- var challenge_host_teams = {
- name: "web.challenge-host-teams",
- parent: "web",
- url: "/challenge-host-teams",
- templateUrl: baseUrl + "/web/challenge-host-teams.html",
- controller: 'ChallengeHostTeamsCtrl',
- controllerAs: 'challengeHostTeams',
- title: 'Host Teams',
- authenticate: true
- };
-
- var challenge_create = {
- name: "web.challenge-create",
- parent: "web",
- url: "/challenge-create",
- templateUrl: baseUrl + "/web/challenge-create.html",
- title: 'Create Challenge',
- controller: 'ChallengeCreateCtrl',
- controllerAs: 'challengeCreate',
- authenticate: true
- };
-
- var challenge_main = {
- name: "web.challenge-main",
- parent: "web",
- url: "/challenges",
- templateUrl: baseUrl + "/web/challenge-main.html",
- redirectTo: "web.challenge-main.challenge-list",
- };
-
- var challenge_list = {
- name: "web.challenge-main.challenge-list",
- parent: "web.challenge-main",
- url: "/list",
- templateUrl: baseUrl + "/web/challenge-list.html",
- controller: 'ChallengeListCtrl',
- controllerAs: 'challengeList',
- title: 'Challenges',
- };
-
- var challenge_page = {
- name: "web.challenge-main.challenge-page",
- parent: "web.challenge-main",
- url: "/challenge-page/:challengeId",
- templateUrl: baseUrl + "/web/challenge/challenge-page.html",
- controller: 'ChallengeCtrl',
- controllerAs: 'challenge',
- redirectTo: "web.challenge-main.challenge-page.overview",
- };
-
- var overview = {
- name: "web.challenge-main.challenge-page.overview",
- parent: "web.challenge-main.challenge-page",
- url: "/overview",
- templateUrl: baseUrl + "/web/challenge/overview.html",
- title: 'Overview',
- };
-
- var evaluation = {
- name: "web.challenge-main.challenge-page.evaluation",
- parent: "web.challenge-main.challenge-page",
- url: "/evaluation",
- templateUrl: baseUrl + "/web/challenge/evaluation.html",
- title: 'Evaluation',
- };
-
- var phases = {
- name: "web.challenge-main.challenge-page.phases",
- parent: "web.challenge-main.challenge-page",
- url: "/phases",
- templateUrl: baseUrl + "/web/challenge/phases.html",
- title: 'Phases',
- };
-
- var participate = {
- name: "web.challenge-main.challenge-page.participate",
- parent: "web.challenge-main.challenge-page",
- url: "/participate",
- templateUrl: baseUrl + "/web/challenge/participate.html",
- title: 'Participate',
- };
-
- var submission = {
- name: "web.challenge-main.challenge-page.submission",
- parent: "web.challenge-main.challenge-page",
- url: "/submission",
- templateUrl: baseUrl + "/web/challenge/submission.html",
- title: 'Submit',
- authenticate: true,
- resolve: {
- challenge: function(utilities, $state, $stateParams) {
- return new Promise(function(resolve) {
- var parameters = {};
- parameters.token = utilities.getData('userKey');
- parameters.url = 'challenges/' + $stateParams.challengeId + '/participant_team/team_detail';
- parameters.method = 'GET';
- parameters.data = {};
- parameters.callback = {
- onSuccess: function(response) {
- var details = response.data;
- resolve(details);
- },
- onError: function() {
- $state.go('error-404');
- }
- };
- utilities.sendRequest(parameters);
- });
- }
- },
- };
-
- var my_submission = {
- name: "web.challenge-main.challenge-page.my-submission",
- parent: "web.challenge-main.challenge-page",
- url: "/my-submission",
- templateUrl: baseUrl + "/web/challenge/my-submission.html",
- title: 'My Submissions',
- authenticate: true
- };
-
- var my_challenge_all_submission = {
- name: "web.challenge-main.challenge-page.my-challenge-all-submission",
- parent: "web.challenge-main.challenge-page",
- url: "/my-challenge-all-submission",
- templateUrl: baseUrl + "/web/challenge/my-challenge-all-submission.html",
- title: 'My Challenge All Submissions',
- authenticate: true,
- resolve: {
- challenge: function(utilities, $state, $stateParams) {
- return new Promise(function(resolve, reject) {
- var parameters = {};
- parameters.token = utilities.getData('userKey');
- parameters.url = 'participants/participant_teams/challenges/' + $stateParams.challengeId + '/user';
- parameters.method = 'GET';
- parameters.data = {};
- parameters.callback = {
- onSuccess: function(response) {
- var details = response.data;
- if (details.is_challenge_host) {
- resolve(details);
- } else {
- $state.go('error-404');
- reject();
- }
- },
- onError: function() {
- reject();
- }
- };
- utilities.sendRequest(parameters);
- });
- }
- },
- };
-
- var approval_team = {
- name: "web.challenge-main.challenge-page.approval_team",
- parent: "web.challenge-main.challenge-page",
- url: "/approval_team",
- templateUrl: baseUrl + "/web/challenge/approval-team.html",
- title: 'My Challenge Approved Teams',
- authenticate: true,
-
- };
-
- var leaderboard = {
- name: "web.challenge-main.challenge-page.leaderboard",
- parent: "web.challenge-main.challenge-page",
- url: "/leaderboard",
- templateUrl: baseUrl + "/web/challenge/leaderboard.html",
- title: 'Leaderboard',
- };
-
- var prizes = {
- name: "web.challenge-main.challenge-page.prizes",
- parent: "web.challenge-main.challenge-page",
- url: "/prizes",
- templateUrl: baseUrl + "/web/challenge/prizes.html",
- title: 'Prizes',
- };
-
- var sponsors = {
- name: "web.challenge-main.challenge-page.sponsors",
- parent: "web.challenge-main.challenge-page",
- url: "/sponsors",
- templateUrl: baseUrl + "/web/challenge/sponsors.html",
- title: 'Sponsors',
- };
-
- var manage = {
- name: "web.challenge-main.challenge-page.manage",
- parent: "web.challenge-main.challenge-page",
- url: "/manage",
- templateUrl: baseUrl + "/web/challenge/manage.html",
- controller: 'ChallengeCtrl',
- controllerAs: 'challenge',
- authenticate: true,
- resolve: {
- challenge: function(utilities, $state, $stateParams) {
- return new Promise(function(resolve, reject) {
- var parameters = {};
- parameters.token = utilities.getData('userKey');
- parameters.url = 'participants/participant_teams/challenges/' + $stateParams.challengeId + '/user';
- parameters.method = 'GET';
- parameters.data = {};
- parameters.callback = {
- onSuccess: function(response) {
- var details = response.data;
- if (details.is_challenge_host) {
- resolve(details);
- } else {
- $state.go('error-404');
- reject();
- }
- },
- onError: function() {
- reject();
- }
- };
- utilities.sendRequest(parameters);
- });
- }
- },
- };
-
- var challenge_phase_leaderboard = {
- name: "web.challenge-main.challenge-page.phase-leaderboard",
- url: "/leaderboard/:phaseSplitId",
- controller: 'ChallengeCtrl',
- controllerAs: 'challenge',
- templateUrl: baseUrl + "/web/challenge/leaderboard.html",
- title: 'Leaderboard'
- };
-
- var challenge_phase_metric_leaderboard = {
- name: "web.challenge-main.challenge-page.phase-metric-leaderboard",
- url: "/leaderboard/:phaseSplitId/:metric",
- controller: 'ChallengeCtrl',
- controllerAs: 'challenge',
- templateUrl: baseUrl + "/web/challenge/leaderboard.html",
- title: 'Leaderboard'
- };
-
- var profile = {
- name: "web.profile",
- parent: "web",
- url: "/profile",
- templateUrl: baseUrl + "/web/profile/profile.html",
- title: "Profile",
- controller: 'profileCtrl',
- controllerAs: 'profile',
- redirectTo: "web.profile.Updateprofile",
- authenticate: true
- };
-
- var auth_token = {
- name: "web.profile.AuthToken",
- parent: "web.profile",
- url: "/auth-token",
- templateUrl: baseUrl + "/web/auth/get-token.html",
- title: 'Auth Token',
- authenticate: true
- };
-
- var update_profile = {
- name: "web.profile.Updateprofile",
- parent: "web.profile",
- url: "/update-profile",
- templateUrl: baseUrl + "/web/profile/edit-profile/update-profile.html",
- title: 'Update profile',
- authenticate: true
- };
-
- var edit_profile = {
- name: "web.profile.Editprofile",
- parent: "web.profile",
- url: "/edit-profile",
- templateUrl: baseUrl + "/web/profile/edit-profile/edit-profile.html",
- title: 'Edit profile',
- authenticate: true
- };
-
- var deactivate_account = {
- name: "web.profile.deactivate-account",
- parent: "web.profile",
- url: "/deactivate-account",
- templateUrl: baseUrl + "/web/profile/edit-profile/deactivate-account.html",
- title: 'Deactivate Account',
- authenticate: true
- };
-
- var host_challenge = {
- name: "web.host-challenge",
- parent: "web",
- url: "/host-challenge",
- templateUrl: baseUrl + "/web/host-challenge.html",
- title: 'Host Competition',
- // controller: 'HostCtrl',
- // controllerAs: 'host',
- authenticate: true
- };
-
- var permission_denied = {
- name: "web.permission-denied",
- parent: "web",
- url: "/permission-denied",
- templateUrl: baseUrl + "/web/permission-denied.html",
- title: "Permission Denied",
- controller: 'PermCtrl',
- controllerAs: 'perm',
- authenticate: true
- };
-
- var change_password = {
- name: "web.profile.change-password",
- parent: "web.profile",
- url: "/change-password",
- templateUrl: baseUrl + "/web/change-password.html",
- title: "Change Password",
- controller: 'ChangePwdCtrl',
- controllerAs: 'changepwd',
- authenticate: true
- };
-
- var error_404 = {
- name: "error-404",
- templateUrl: baseUrl + "/web/error-pages/error-404.html",
- title: "Error 404",
- };
-
- var error_500 = {
- name: "error-500",
- templateUrl: baseUrl + "/web/error-pages/error-500.html",
- title: "Error 500",
- };
-
- var privacy_policy = {
- name: "privacy_policy",
- url: "/privacy-policy",
- templateUrl: baseUrl + "/web/privacy-policy.html",
- title: "Privacy Policy"
- };
-
- var about_us = {
- name: 'about-us',
- url: "/about",
- templateUrl: baseUrl + "/web/about-us.html",
- title: "About Us"
- };
-
- var our_team = {
- name: 'our-team',
- url: "/team",
- templateUrl: baseUrl + "/web/our-team.html",
- controller: 'ourTeamCtrl',
- controllerAs: 'ourTeam',
- title: "Team"
- };
-
- var get_involved = {
- name: 'get-involved',
- url: "/get-involved",
- templateUrl: baseUrl + "/web/get-involved.html",
- title: "Get Involved"
- };
-
- var contact_us = {
- name: "contact-us",
- url: "/contact",
- templateUrl: baseUrl + "/web/contact-us.html",
- title: "Contact Us",
- controller: 'contactUsCtrl',
- controllerAs: 'contactUs'
- };
-
- var featured_challenge_page = {
- name: "featured-challenge-page",
- url: "/featured-challenges/:challengeId",
- templateUrl: baseUrl + "/web/featured-challenge/challenge-page.html",
- controller: 'FeaturedChallengeCtrl',
- controllerAs: 'featured_challenge',
- redirectTo: "featured-challenge-page.overview"
- };
-
- var featured_challenge_overview = {
- name: "featured-challenge-page.overview",
- parent: "featured-challenge-page",
- url: "/overview",
- templateUrl: baseUrl + "/web/featured-challenge/overview.html",
- title: 'Overview'
- };
-
- var featured_challenge_evaluation = {
- name: "featured-challenge-page.evaluation",
- url: "/evaluation",
- templateUrl: baseUrl + "/web/featured-challenge/evaluation.html",
- title: 'Evaluation'
- };
-
- var featured_challenge_phases = {
- name: "featured-challenge-page.phases",
- url: "/phases",
- templateUrl: baseUrl + "/web/featured-challenge/phases.html",
- title: 'Phases'
- };
-
- var featured_challenge_participate = {
- name: "featured-challenge-page.participate",
- url: "/participate",
- templateUrl: baseUrl + "/web/featured-challenge/participate.html",
- title: 'Participate'
- };
-
- var featured_challenge_leaderboard = {
- name: "featured-challenge-page.leaderboard",
- url: "/leaderboard",
- templateUrl: baseUrl + "/web/featured-challenge/leaderboard.html",
- title: 'Leaderboard'
- };
-
- var featured_challenge_phase_leaderboard = {
- name: "featured-challenge-page.phase-leaderboard",
- url: "/leaderboard/:phaseSplitId",
- controller: 'FeaturedChallengeCtrl',
- controllerAs: 'featured_challenge',
- templateUrl: baseUrl + "/web/featured-challenge/leaderboard.html",
- title: 'Leaderboard'
- };
-
- var challengeInvitation = {
- name: "challenge-invitation",
- url: "/accept-invitation/:invitationKey",
- controller: "ChallengeInviteCtrl",
- controllerAs: "challenge_invitation",
- templateUrl: baseUrl + "/web/challenge-invite.html",
- title: "Accept challenge invitation"
- };
-
- var get_submission_related_files = {
- name: "get-submission-related-files",
- url: "/web/submission-files?bucket&key",
- controller: "SubmissionFilesCtrl",
- controllerAs: "submission_files",
- };
-
- // call all states here
- $stateProvider.state(home);
- $stateProvider.state(privacy_policy);
-
- // auth configs
- $stateProvider.state(auth);
- $stateProvider.state(login);
- $stateProvider.state(signup);
- $stateProvider.state(verify_email);
- $stateProvider.state(reset_password);
- $stateProvider.state(reset_password_confirm);
- $stateProvider.state(logout);
-
- // web main configs.
- $stateProvider.state(web);
- $stateProvider.state(dashboard);
- $stateProvider.state(host_analytics);
- $stateProvider.state(teams);
- $stateProvider.state(hosted_challenges);
-
- // challenge host teams
- $stateProvider.state(challenge_host_teams);
-
- // challenges list page
- $stateProvider.state(challenge_main);
- $stateProvider.state(challenge_list);
-
- // challenge create page
- $stateProvider.state(challenge_create);
-
- // challenge details
- $stateProvider.state(challenge_page);
- $stateProvider.state(overview);
- $stateProvider.state(evaluation);
- $stateProvider.state(phases);
- $stateProvider.state(participate);
- $stateProvider.state(submission);
- $stateProvider.state(my_submission);
- $stateProvider.state(my_challenge_all_submission);
- $stateProvider.state(approval_team);
- $stateProvider.state(leaderboard);
- $stateProvider.state(prizes);
- $stateProvider.state(sponsors);
- $stateProvider.state(challenge_phase_leaderboard);
- $stateProvider.state(challenge_phase_metric_leaderboard);
-
- // featured challenge details
- $stateProvider.state(featured_challenge_page);
- $stateProvider.state(featured_challenge_overview);
- $stateProvider.state(featured_challenge_evaluation);
- $stateProvider.state(featured_challenge_phases);
- $stateProvider.state(featured_challenge_participate);
- $stateProvider.state(featured_challenge_leaderboard);
- $stateProvider.state(featured_challenge_phase_leaderboard);
-
- $stateProvider.state(host_challenge);
-
- $stateProvider.state(profile);
- $stateProvider.state(auth_token);
- $stateProvider.state(update_profile);
- $stateProvider.state(permission_denied);
- $stateProvider.state(change_password);
- $stateProvider.state(error_404);
- $stateProvider.state(error_500);
- $stateProvider.state(about_us);
- $stateProvider.state(our_team);
- $stateProvider.state(get_involved);
- $stateProvider.state(edit_profile);
- $stateProvider.state(deactivate_account);
- $stateProvider.state(contact_us);
- $stateProvider.state(challengeInvitation);
- $stateProvider.state(get_submission_related_files);
-
- $stateProvider.state(manage);
-
- $urlRouterProvider.otherwise(function($injector, $location) {
- var state = $injector.get('$state');
- state.go('error-404');
- return $location.path();
- });
- }
-
-})();
-
-// define run block here
-(function () {
-
- 'use strict';
-
- angular
- .module('evalai')
- .run(runFunc);
-
- runFunc.$inject = ['$rootScope', '$state', 'utilities', '$window', '$location', 'toaster'];
-
- function runFunc($rootScope, $state, utilities, $window, $location, toaster) {
- // setting timout for token (7days)
- // var getTokenTime = utilities.getData('tokenTime');
- // var timeNow = (new Date()).getTime();
- // .getTime() returns milliseconds, so for 7 days 1000 * 60 * 60 * 24 * 7 = 7 days
- // var tokenExpTime = 1000 * 60 * 60 * 24 * 7;
- // if ((timeNow - getTokenTime) > tokenExpTime) {
- // utilities.resetStorage();
- // }
-
- $rootScope.isAuth = false;
- // check for valid user
- $rootScope.$on("$stateChangeStart", function(event, to, toParams) {
- if (utilities.isAuthenticated()) {
- $rootScope.isAuth = true;
- if (to.authpage) {
- event.preventDefault();
- $state.go("home");
- }
- } else {
- $rootScope.isAuth = false;
- if (to.authenticate) {
- event.preventDefault();
- $rootScope.previousState = to;
- $rootScope.previousStateParams = toParams;
- $state.go("auth.login");
- }
- }
-
- });
-
- $rootScope.$on('$stateChangeStart', function(event, to, params) {
- if (to.redirectTo) {
- event.preventDefault();
- $state.go(to.redirectTo, params, { location: $location.path() });
- }
- });
-
- $rootScope.$on('$stateChangeSuccess', function() {
- // Save the route title
- $rootScope.pageTitle = $state.current.title;
- // Scroll to top
- $window.scrollTo(0, 0);
- // Google Analytics Scripts
- if ($window.ga) {
- $window.ga('create', 'UA-45466017-2', 'auto');
- $window.ga('send', 'pageview', $location.path());
- }
- });
-
- $rootScope.notify = function(type, message, timeout) {
- // function to pic timeout
- function pick(arg, def) {
- return (typeof arg === undefined ? def : arg);
- }
-
- timeout = pick(timeout, 5000);
- toaster.pop({
- type: type,
- body: message,
- timeout: timeout,
- });
- };
-
- $rootScope.logout = function() {
- var userKey = utilities.getData('userKey');
- var parameters = {};
- parameters.url = 'auth/logout/';
- parameters.method = 'POST';
- parameters.token = userKey;
- parameters.callback = {
- onSuccess: function() {
- utilities.resetStorage();
- $rootScope.isLoader = false;
- $state.go("home");
- $rootScope.isAuth = false;
- $rootScope.notify("info", "Successfully logged out!");
- },
- onError: function() {}
- };
-
- utilities.sendRequest(parameters);
- };
-
- $rootScope.checkToken = function() {
- var userKey = utilities.getData('userKey');
- var parameters = {};
- parameters.url = 'auth/user/';
- parameters.method = 'GET';
- parameters.token = userKey;
- parameters.callback = {
- onSuccess: function() {},
- onError: function(response) {
- var status = response.status;
- if (status == 401) {
- alert("Timeout, Please login again to continue!");
- utilities.resetStorage();
- $state.go("auth.login");
- $rootScope.isAuth = false;
- }
- }
- };
-
- utilities.sendRequest(parameters);
- };
-
- if (!$rootScope.isAuth) {
- // checkToken();
- }
- }
-})();
diff --git a/frontend/src/js/services/loaderService.js b/frontend/src/js/services/loaderService.js
deleted file mode 100644
index 76b2f78715..0000000000
--- a/frontend/src/js/services/loaderService.js
+++ /dev/null
@@ -1,25 +0,0 @@
-
- angular
- .module('evalai')
- .service('loaderService', loaderService);
-
- function loaderService() {
-
- //start loader
- this.startLoader = function(msg) {
- this.isExistLoader = true;
- this.loaderTitle = msg;
- this.loaderContainer.addClass('low-screen');
- };
-
- // stop loader
- this.stopLoader = function() {
- this.isExistLoader = false;
- this.loaderTitle = '';
- this.loaderContainer.removeClass('low-screen');
- };
-
- return this;
-
- }
-
diff --git a/frontend/src/js/services/services.js b/frontend/src/js/services/services.js
deleted file mode 100644
index db264f97fe..0000000000
--- a/frontend/src/js/services/services.js
+++ /dev/null
@@ -1,165 +0,0 @@
-// define services here
-
-// Basic utilities
-(function() {
-
- 'use strict';
-
- angular
- .module('evalai')
- .service('utilities', utilities);
-
- utilities.$inject = ['$http', 'EnvironmentConfig'];
-
- function utilities($http, EnvironmentConfig) {
-
- // factory for API calls
- this.sendRequest = function(parameters, header, type) {
- var url = EnvironmentConfig.API + parameters.url;
- var data = parameters.data;
- var token = parameters.token;
- var method = parameters.method;
- var successCallback = parameters.callback.onSuccess;
- var errorCallback = parameters.callback.onError;
-
- // check for authenticated calls
- if (parameters.token != null) {
- var headers = {
- 'Authorization': "Token " + token
- };
- }
-
- // function to check for applying header
- function pick(arg, def) {
- return (typeof arg == 'undefined' ? def : arg);
- }
-
- header = pick(header, 'header');
- var req = {
- method: method,
- url: url,
- };
- if (header == 'header') {
- req.headers = headers;
- }
- if (method == "POST" || method == "PUT" || method == "PATCH") {
- req.data = data;
- }
-
- // for file upload
- if (method == "POST" || method == "PATCH" || method == "PUT") {
- if (type == "upload") {
- // alert("")
- headers = {
- 'Content-Type': undefined,
- 'Authorization': "Token " + token
- };
- req.transformRequest = function(data) {
- return data;
- };
-
- req.headers = headers;
- }
- }
-
- $http(req)
- .then(successCallback, errorCallback);
- };
-
- this.storeData = function(key, value) {
- localStorage.setItem(key, JSON.stringify(value));
- };
-
- this.getData = function(key) {
- if (localStorage.getItem(key) === null) {
- return false;
- } else {
- return JSON.parse(localStorage.getItem(key));
- }
- };
-
- this.deleteData = function(key) {
- localStorage.removeItem(key);
- };
-
- // user verification auth service
- this.isAuthenticated = function() {
- if (this.getData('userKey')) {
- return true;
- } else {
- return false;
- }
- };
-
- this.resetStorage = function() {
- localStorage.clear();
- };
-
- this.showLoader = function() {
- angular.element("#sim-loader").show();
- angular.element(".web-container").addClass('low-screen');
- };
-
- this.hideLoader = function() {
- angular.element("#sim-loader").fadeOut();
- angular.element(".web-container").removeClass('low-screen');
- };
-
- this.showButton = function() {
- angular.element("#scroll-up").show();
- };
-
- this.hideButton = function() {
- angular.element("#scroll-up").fadeOut();
- };
-
- this.passwordStrength = function(password){
-
- //Regular Expressions.
- var regex = new Array();
- regex.push("[A-Z]","[a-z]","[0-9]","[$$!%*#?&]");
-
- var passed = 0;
- //Validate for each Regular Expression.
- for (var i = 0; i < regex.length; i++) {
- if (new RegExp(regex[i]).test(password)) {
- passed++;
- }
- }
- //Validate for length of Password.
- if (passed > 2 && password.length > 8) {
- passed++;
- }
-
- var color = "";
- var strength = "";
- if (passed == 1) {
- strength = "Weak";
- color = "red";
- } else if (passed == 2) {
- strength = "Average";
- color = "darkorange";
- } else if (passed == 3) {
- strength = "Good";
- color = "green";
- } else if (passed == 4) {
- strength = "Strong";
- color = "darkgreen";
- } else if (passed == 5) {
- strength = "Very Strong";
- color = "darkgreen";
- }
- return [strength, color];
- };
-
- this.getEnvironment = function() {
- switch (EnvironmentConfig.API) {
- case "http://localhost:8000/api/": return "local";
- case "https://staging.eval.ai/api/": return "staging";
- case "https://eval.ai/api/": return "production";
- default: return "other";
- }
- };
- }
-
-})();
diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js
new file mode 100644
index 0000000000..2d4d564619
--- /dev/null
+++ b/frontend/src/lang/en.js
@@ -0,0 +1,266 @@
+// en.js
+export default {
+ basicInfo: 'Basic Info',
+ saveAs: 'Save as',
+ save: 'Save',
+ create: 'Create',
+ saveFailed: 'Failed',
+ nonEdit: 'Not Editable',
+ name: 'Name',
+ saveOrNot: 'Do you want to save the changes?',
+ aboutToLeave: 'About to leave',
+ notSave: "Don't Save",
+ confirm: 'Confirm',
+ cancel: 'Cancel',
+ pleaseInputName: 'Please input name',
+ note: 'Note',
+ success: 'Success',
+ greeting: 'Hello, welcome to use Arena platform!',
+ yes: 'Yes',
+ no: 'No',
+ back: 'Back',
+ send: 'Send',
+ submit: 'Submit',
+ operate: 'Operate',
+ loadMore: 'Load more',
+ systemInterface: 'System interface',
+ exception: 'exception',
+ interfaceTimeout: 'Interface request timeout',
+ interfaceException: 'Interface connection exception',
+ login: {
+ username: 'User name',
+ password: 'Password',
+ usernamePH: 'Please enter user name (no less than 3 characters)',
+ passwordPH: 'Please enter password(min 8 characters)',
+ usernameVerify1: 'Username is required',
+ usernameVerify2: 'Username is too short',
+ passwordVerify1: 'Passwordis required',
+ passwordVerify2: 'Password is too short',
+ login: 'Log In',
+ goSingup: 'Start with a new account Sign Up',
+ forgotpw: 'Forgot password or username?',
+ },
+ signup: {
+ username: 'User name',
+ email: 'Email',
+ password: 'Password',
+ confirmpw: 'Confirm password',
+ usernamePH: 'Please enter user name (no less than 3 characters)',
+ emailPH: 'Please enter email',
+ passwordPH: 'Please enter password(min 8 characters)',
+ confirmpwPH: 'Please confirm the password again',
+ usernameVerify1: 'Username is required',
+ usernameVerify2: 'Username is too short',
+ passwordVerify1: 'Passwordis required',
+ passwordVerify2: 'Password is too short',
+ confirmpwVerify1: 'Passwords do not match',
+ emailVerify1: 'Email address is required',
+ emailVerify2: 'Please enter a valid email address',
+ signup: 'Sign Up',
+ goLogin: 'Already have an account? Log In',
+ registerSuccess: 'Registered successfully',
+ },
+ lang: {
+ chinese: 'Chinese',
+ english: 'English',
+ },
+ forget: {
+ title: 'Forgot password?',
+ prompt: 'You can reset your password by entering your email.',
+ backlogin: 'Back to login',
+ email: 'Email',
+ emailPH: 'Please enter email',
+ emailVerify1: 'Please enter a valid email address',
+ submit: 'Submit',
+ restext: 'Password reset link has been sent to your registered email address. Please check your email inbox.',
+ backloginTxt: 'Back to Log In',
+ },
+ reset: {
+ setpw: 'Set new password',
+ confirmpw: 'Confirm new password',
+ passwordPH: 'Please enter password(min 8 characters)',
+ confirmpwPH: 'Please confirm the password again',
+ passwordVerify1: 'Passwordis required',
+ passwordVerify2: 'Password is too short',
+ confirmpwVerify1: 'Passwords do not match',
+ submit: 'Submit',
+ goSingup: 'Start with a new account Sign Up',
+ changeSuccess: 'Password changed successfully',
+ restext: 'Password has been reset with the new password.',
+ login: 'Log In',
+ },
+ challenge: {
+ challenge: 'Challenge',
+ participate: 'Participate',
+ ongoing: 'ongoing',
+ eventDetails: 'Event details',
+ overview: 'Overview',
+ leaderboard: 'Leaderboard',
+ submission: 'Submission',
+ allSubmission: 'All Submissions',
+ noTeam: 'No team exists for now.',
+ startCreate: 'Start by creating a new team!',
+ approval: 'Team Approval',
+ please: 'Please',
+ login: 'log in',
+ partiChall: 'to participate in this challenge.',
+ },
+ team: {
+ team: 'Team',
+ members: 'Members',
+ createdBy: 'Created by',
+ createTeam: 'Create Team',
+ editTeam: 'Update Team',
+ teamName: 'Team Name',
+ teamNamePH: 'Please enter Team Name',
+ url: 'URL',
+ urlPH: 'Please enter URL',
+ removeYourself: 'Would you like to remove yourself?',
+ removeNote: 'Note: This action will remove you from the team.',
+ intive: 'Intive',
+ email: 'Email',
+ emailPH: 'Please enter User Email',
+ emailNote: 'Batch invitation, intermediate use ; separation',
+ createSuccess: 'New team has been created',
+ updateSuccess: 'Host team updated',
+ removeSuccess: 'You have removed yourself successfully',
+ intiveSuccess: 'has been added successfully',
+ },
+ user: {
+ profile: 'Profile',
+ logout: 'Log out',
+ modifyPic: 'Modify profile picture',
+ firstName: 'First Name',
+ lastName: 'Last Name',
+ affilliate: 'Affilliate To',
+ profileCompleted: 'Profile Completed',
+ password: 'Password',
+ changePassword: 'Change Password',
+ oldPassword: 'Old Password',
+ newPassword: 'New Password',
+ confirmpw: 'New Password (Again)',
+ oldPasswordPH: 'Please enter old password',
+ newPasswordPH: 'Please enter password(min 8 characters)',
+ confirmpwPH: 'Please confirm the password again',
+ oldPwVerify1: 'Old password is required',
+ oldPwVerify2: 'password is less than 8 characters.',
+ newPwVerify1: 'New password is required',
+ confirmpwVerify1: 'Passwords do not match',
+ pwChangeSuccess: 'Your password has been changed successfully!',
+ profileUpdatedSuccess: 'Profile updated successfully!',
+ },
+ permission: {
+ verifyEmail: 'Please verify your email to continue.',
+ getEmailTxt: "Didn't get the email?",
+ emailVerifiedSuccess: 'Your emails has been verified successfully.',
+ resendEmail: 'Resend Email',
+ sentAgain: 'The verification link was sent again.',
+ continueVerify: 'please verify your email to continue',
+ hasSent: 'The verification mail has been sent to you.
Please confirm!',
+ denied: 'permission-denied',
+ },
+ race_93: {
+ title: 'CARLA Autonomous Driving Challenge 1.0',
+ describe:
+ 'CARLA Autonomous Driving Challenge 1.0 encourages the development of state-of-the-art autonomous driving systems to tackle complex traffic scenarios. Autonomous agents will be tested in CARLA — an open source driving simulator.',
+ },
+ race_100: {
+ title: 'CARLA Autonomous Driving Challenge 2.0',
+ describe:
+ 'The main goal of the CARLA Autonomous Driving Challenge 2.0 is to evaluate the driving proficiency of autonomous agents in realistic traffic scenarios. The leaderboard serves as an open platform for the community to perform fair and reproducible evaluations of autonomous vehicle agents, simplifying the comparison between different approaches.',
+ },
+ overview: {
+ view: {
+ title: 'Overview',
+ con1: 'Visually inspecting bridges plays a crucial role in assessing their structural integrity, traffic safety, and long-term durability in order to find the ideal timing for rehabilitation steps or to take immediate actions (e.g. limiting heavy traffic or closing a bridge). The current inspection process can be made more efficient by making use of computer vision models in order to automate the damage recognition. Therefore, we developed "dacl10k", an exceptionally diverse multi-label semantic segmentation dataset comprising 9,920 images derived by real-world bridge inspections. dacl10k distinguishes 13 damage classes as well as 6 bridge components that play a key role in bridge inspections. Thereby, it enables the classification, measurement and localisation of its classes on a pixel level. The challenge is to develop a model that can detect and classify the 19 classes of the dacl10k dataset.',
+ con2: 'Detailed informations about the dataset can be found in the paper dacl10k: Benchmark for Semantic Bridge Damage Segmentation.',
+ con3: 'We provide a Python toolkit which should act as a simple entry point for the dataset.',
+ con4: 'The Development dataset can be downloaded from [GigaMove] and [AWS].',
+ con5: 'The Tesfinal dataset can be downloaded from [GigaMove] and [AWS].',
+ },
+ eval: {
+ title: 'Evaluation Criteria',
+ con1: 'The driving proficiency of an agent can be characterized by multiple metrics. For this leaderboard we have selected a set of metrics that help understand different aspects of driving. While all routes have the same type of metrics, their respective values are calculated separately.',
+ con2: 'Please refer to the Leaderboard website for more details about the evaluation metrics.',
+ },
+ term: {
+ title: 'Terms and Conditions',
+ con1: 'Updated October 5th, 2020.',
+ con2: 'PLEASE READ THESE TERMS CAREFULLY. SUBMITTING TO THIS LEADERBOARD CONSTITUTES YOUR ACCEPTANCE OF THESE TERMS. IF YOU DO NOT AGREE TO ANY PART OF THESE TERMS, PLEASE DO NOT SUBMIT.',
+ sub1T: '1. How can I participate in the leaderboard?',
+ sub1C1:
+ 'You can participate in the CARLA leaderboard as an individual or as a member of a team. Individuals may form a team with multiple members. The affiliation of each individual must be declared in order to validate and approve your team. Members without a valid affiliation will be banned from the team. The CARLA organization reserves the right to ban team members and even the entire team if any the terms of the leaderboard are violated.',
+ sub1C2:
+ 'Teams can make as many submissions as they wish until they reach their allocated simulation budget or their monthly maximum number of submissions. The organization of the CARLA leaderboard reserves the right to provide teams with additional simulation budget and/or number of submissions.',
+ sub2T: '2. Submissions',
+ sub2C1:
+ 'By making a submission to the CARLA leaderboard you and your team grant the CARLA leaderboard organization the rights to review and analyze your submission to verify that it complies with all the rules of this leaderboard. The submitted code (docker image) will be used for evaluation purposes only and will not be disclosed without the consent of the team.',
+ sub3T: '3. Disqualification',
+ sub3C1:
+ 'You are not allowed to make use of any privilege information offered by the CARLA simulator or derivatives, including world coordinates, planners, or any type of ground truth. Submissions using these features will be rejected and teams will be banned from the platform.',
+ con3: 'If the organization of the CARLA leaderboard detects any infraction of these terms, an attempt to bypass the rules of the leaderboard, or any other behavior that could be perceived as dishonest, the organization reserves the right to disqualify a submission and/or ban you and/or your team members from the participation in the CARLA leaderboard.',
+ },
+ },
+ submission: {
+ guidelines: 'Submission Guidelines',
+ guideTxt: 'Card quickly that customer can. Indeed beat year news learn. Surface she tend. Account play food claim despite daughter change use.',
+ submission: 'Make Submission',
+ selectPhase: 'Selected phase',
+ startDate: 'Start date',
+ endDate: 'End date',
+ todayRemain: 'Today‘s remaining submission',
+ monthRemain: 'Monthly remaining submission',
+ totalRemain: 'Total remaining submission',
+ instruction: 'Submission instructions',
+ install: 'Install arena-cli',
+ addToken: 'Add your Arena account token to arena-cli',
+ copySuccess: 'Command copied to clipboard',
+ clipboardSuccess: 'Copied to clipboard',
+ flagTxt: 'Use --private or --public flag in the submission command to make the submission private or public respectively.',
+ forMore: 'For more commands, please refer to',
+ referDocument: 'arena-cli documentation.',
+ deregisterChallenge: 'Clik here to deregister from this challenge',
+ deregister: 'Deregister',
+ notApproved: 'Sorry,the participant team is not approved by host yet.',
+ deregisterSuccess: 'You have successfully deregistered from the challenge.',
+ list: 'Submission list',
+ deregisterTeam: 'Deregister Partipant Team',
+ deregisterConfirm: 'Are you sure you want to deregister team?',
+ phasePH: 'Select phase',
+ notCancelled: 'Only unproccessed submissions can be cancelled',
+ changeMade: 'The submission is made ',
+ public: 'public',
+ private: 'private',
+ team: 'Team',
+ createdBy: 'Created by',
+ status: 'Status',
+ executTime: 'Execution time (sec.)',
+ submittedFile: 'Submitted file',
+ resultFile: 'Result file',
+ stdoutFile: 'Stdout file',
+ stderrFile: 'Stderr file',
+ submittedAt: 'Submitted at',
+ showOnLeaderboard: 'Show on leaderboard',
+ verifySubmission: 'Verify submission',
+ sureCancelSubmission: 'Are you sure you want to cancel submission?',
+ cancelSuccess: 'Submission cancelled successfully!',
+ },
+ leaderboard: {
+ team: 'Participant team',
+ score: 'Score',
+ lastSubmission: 'Last submission at',
+ rank: 'Rank',
+ orderScore: 'Order by Score',
+ },
+ approval: {
+ teamId: 'Team ID',
+ member: 'Team Member',
+ state: 'State',
+ approve: 'Approve',
+ disagree: 'Disagree',
+ approveTeam: 'Approve team',
+ approveNote: 'Note:participant teams with existing submissions cannot be disapproved',
+ approveSuccess: 'Participant Team Approved successfully.',
+ disapproveSuccess: 'Participant Team Disapproved successfully.',
+ },
+};
diff --git a/frontend/src/lang/index.js b/frontend/src/lang/index.js
new file mode 100644
index 0000000000..afddc3802f
--- /dev/null
+++ b/frontend/src/lang/index.js
@@ -0,0 +1,37 @@
+import { createI18n } from 'vue-i18n';
+import EN from './en';
+import ZH from './zh';
+import Cookies from 'js-cookie';
+
+const messages = {
+ zh: {
+ ...ZH,
+ },
+ en: {
+ ...EN,
+ },
+};
+
+// 获取默认语言
+export function getLanguage() {
+ const chooseLanguage = Cookies.get('language');
+ if (chooseLanguage) return chooseLanguage;
+
+ const language = (navigator.language || navigator.browserLanguage).toLowerCase();
+ const locales = Object.keys(messages);
+ for (const locale of locales) {
+ if (language.indexOf(locale) > -1) {
+ return locale;
+ }
+ }
+ return 'en';
+}
+
+const i18n = createI18n({
+ locale: getLanguage(), // 设置当前语言类型
+ legacy: false, // 如果要支持compositionAPI,此项必须设置为false;
+ globalInjection: true, // 全局注册$t方法
+ messages,
+});
+
+export default i18n;
diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js
new file mode 100644
index 0000000000..9c26c24f6a
--- /dev/null
+++ b/frontend/src/lang/zh.js
@@ -0,0 +1,264 @@
+// zh.js
+export default {
+ basicInfo: '基本信息',
+ saveAs: '另存为',
+ save: '保存',
+ create: '创建',
+ saveFailed: '保存失败',
+ nonEdit: '不可编辑',
+ name: '名称',
+ saveOrNot: '是否保存改动内容?',
+ aboutToLeave: '即将离开',
+ notSave: '不保存',
+ confirm: '确定',
+ cancel: '取消',
+ pleaseInputName: '请输入名称',
+ note: '备注',
+ success: '成功',
+ greeting: '你好,欢迎使用Arena平台',
+ yes: '是',
+ no: '否',
+ back: '返回',
+ send: '发送',
+ submit: '提交',
+ operate: '操作',
+ loadMore: '加载更多',
+ systemInterface: '系统接口',
+ exception: '异常',
+ interfaceTimeout: '接口请求超时',
+ interfaceException: '接口连接异常',
+ login: {
+ username: '用户名',
+ password: '密码',
+ usernamePH: '请输入用户名 (不少于三个字符)',
+ passwordPH: '请输入密码(最少8个字符)',
+ usernameVerify1: '用户名必填',
+ usernameVerify2: '用户名太短',
+ passwordVerify1: '密码必填',
+ passwordVerify2: '密码太短',
+ login: '登录',
+ goSingup: '注册一个账号',
+ forgotpw: '忘记密码或用户名?',
+ },
+ signup: {
+ username: '用户名',
+ email: '邮箱',
+ password: '密码',
+ confirmpw: '确认密码',
+ usernamePH: '请输入用户名 (不少于三个字符)',
+ emailPH: '请输入邮箱',
+ passwordPH: '请输入密码(最少8个字符)',
+ confirmpwPH: '请再次确认密码',
+ usernameVerify1: '用户名必填',
+ usernameVerify2: '用户名太短',
+ passwordVerify1: '密码必填',
+ passwordVerify2: '密码太短',
+ confirmpwVerify1: '密码不匹配',
+ emailVerify1: '请输入邮箱地址',
+ emailVerify2: '请输入一个有效邮箱地址',
+ signup: '注册',
+ goLogin: '已有一个账号?去登录',
+ registerSuccess: '注册成功',
+ },
+ lang: {
+ chinese: '中文',
+ english: '英文',
+ },
+ forget: {
+ title: '忘记密码?',
+ prompt: '输入注册邮箱可以重置密码',
+ backlogin: '返回登陆',
+ email: '邮箱',
+ emailPH: '请输入邮箱',
+ emailVerify1: '请输入一个有效邮箱地址',
+ submit: '提交',
+ restext: '密码重置链接已发送至您的注册邮箱,请在收件箱中查收。',
+ backloginTxt: '返回登录',
+ },
+ reset: {
+ setpw: '设置新密码',
+ confirmpw: '确认新密码',
+ passwordPH: '请输入密码(最少8个字符)',
+ confirmpwPH: '请再次确认密码',
+ passwordVerify1: '密码必填',
+ passwordVerify2: '密码太短',
+ confirmpwVerify1: '密码不匹配',
+ submit: '提交',
+ goSingup: '注册一个账号',
+ changeSuccess: '密码修改成功!',
+ restext: '密码已被新密码重置',
+ login: '登录',
+ },
+ challenge: {
+ challenge: '比赛',
+ participate: '参加',
+ ongoing: '进行中',
+ eventDetails: '比赛详情',
+ overview: '概述',
+ leaderboard: '排行榜',
+ submission: '提交',
+ allSubmission: '所有提交',
+ noTeam: '目前不存在任何团队。',
+ startCreate: '开始创建一个新团队吧!',
+ approval: '团队审批',
+ please: '请',
+ login: '登录',
+ partiChall: '参与比赛。',
+ },
+ team: {
+ team: '团队',
+ members: '成员',
+ createdBy: '创建者用户名',
+ createTeam: '创建团队',
+ editTeam: '编辑团队',
+ teamName: '团队名称',
+ teamNamePH: '请输入团队名称',
+ url: '团队网址',
+ urlPH: '请输入地址',
+ removeYourself: '你想要移除你自己么?',
+ removeNote: '注意:这个操作将使你从团队中删除。',
+ intive: '邀请',
+ email: '邮箱',
+ emailPH: '请输入邮箱',
+ emailNote: '批量邀请,中间使用;隔开',
+ createSuccess: '新的团队已创建成功',
+ updateSuccess: '团队已更新',
+ removeSuccess: '你已经成功移除了你自己',
+ intiveSuccess: '已被成功邀请',
+ },
+ user: {
+ profile: '个人信息',
+ logout: '退出登录',
+ modifyPic: '编辑头像',
+ firstName: '名字',
+ lastName: '姓氏',
+ affilliate: '单位',
+ profileCompleted: '简介完成度',
+ password: '密码',
+ changePassword: '更改密码',
+ oldPassword: '旧密码',
+ newPassword: '新密码',
+ confirmpw: '密码确认',
+ oldPasswordPH: '请输入旧密码',
+ newPasswordPH: '请输入密码(最少8个字符)',
+ confirmpwPH: '请再次确认密码',
+ oldPwVerify1: '旧密码必须填写',
+ oldPwVerify2: '密码至少8个字符',
+ newPwVerify1: '新密码必须填写',
+ confirmpwVerify1: '密码不匹配',
+ pwChangeSuccess: '您的密码已成功更改!',
+ profileUpdatedSuccess: '个人信息更改成功!',
+ },
+ permission: {
+ verifyEmail: '请先校验您的邮箱。',
+ getEmailTxt: '没有收到电子邮件?',
+ emailVerifiedSuccess: '您的电子邮件已成功验证。',
+ resendEmail: '发送邮件',
+ sentAgain: '验证链接已再次发送。',
+ continueVerify: '请验证您的电子邮件以继续',
+ hasSent: '验证邮件已发送给您。
请确认!',
+ denied: '许可被拒绝',
+ },
+ race_93: {
+ title: 'CARLA自动驾驶算法挑战赛 1.0',
+ describe: 'CARLA自动驾驶挑战1.0鼓励开发最优秀的自动驾驶系统,以应对复杂的交通场景。自动驾驶汽车将在CARLA开源的驾驶模拟器中进行测试。',
+ },
+ race_100: {
+ title: 'CARLA 自动驾驶算法挑战赛 2.0',
+ describe:
+ 'CARLA 自动驾驶挑战赛 2.0 的主要目标是评估自动驾驶代理在现实交通场景中的驾驶能力,可以对自动驾驶算法进行公平和可重复的评估,从而简化不同方法之间的比较。',
+ },
+ overview: {
+ view: {
+ title: '概述',
+ con1: '目视检查桥梁在评估其结构完整性、交通安全和长期耐久性方面发挥着至关重要的作用,以便找到修复步骤或立即采取行动(例如限制繁忙交通或关闭桥梁)的理想时机。通过使用计算机视觉模型来自动化损伤识别,可以使当前的检查过程更加高效。因此,我们开发了“dacl10k”,这是一个异常多样化的多标签语义分割数据集,包括9920张通过真实世界桥梁检查获得的图像。dacl10k区分了13个损伤类别以及在桥梁检查中起关键作用的6个桥梁部件。因此,它能够在像素级别上对其类别进行分类、测量和定位。挑战在于开发一种能够检测和分类dacl10k数据集的19类的模型。',
+ con2: '关于该数据集的详细信息可以在论文dacl10k:语义桥梁损伤分割基准中找到。',
+ con3: '我们提供了一个Python工具包,它应该作为数据集的简单入口点。',
+ con4: '开发数据集可以从【gigmove】和【AWS】下载。',
+ con5: 'Tesfinal数据集可以从【GigaMove】和【AWS】下载。',
+ },
+ eval: {
+ title: '评估标准',
+ con1: '智能体的驾驶熟练程度可以用多个指标来表征。对于这个排行榜,我们选择了一组有助于理解驾驶不同方面的指标。虽然所有路由都有相同类型的度量值,但它们各自的值是单独计算的。',
+ con2: '有关评估指标的更多详细信息,请参阅排行榜网站。',
+ },
+ term: {
+ title: '条款和条件',
+ con1: '更新时间:2020年10月5日。',
+ con2: '请仔细阅读这些条款。提交此排行榜即表示您接受这些条款。如果您不同意这些条款的任何部分,请不要提交。',
+ sub1T: '1. 我如何参加排行榜?',
+ sub1C1:
+ '您可以作为个人或团队成员参加CARLA排行榜。个人可以组成一个由多个成员组成的团队。为了验证和批准您的团队,必须声明每个人的隶属关系。没有有效隶属关系的成员将被禁止加入团队。如果违反排行榜的任何条款,CARLA组织保留禁止团队成员甚至整个团队参赛的权利。',
+ sub1C2: '团队可以随心所欲地提交,直到达到分配的模拟预算或每月提交的最大数量。CARLA排行榜的组织保留向团队提供额外模拟预算和/或提交数量的权利。',
+ sub2T: '2. 提交',
+ sub2C1:
+ '通过向CARLA排行榜提交,您和您的团队授予CARLA排行板组织审查和分析您提交的内容以验证其是否符合该排行榜的所有规则的权利。提交的代码(docker图像)仅用于评估目的,未经团队同意,不得披露。',
+ sub3T: '3. 取消资格',
+ sub3C1:
+ '您不允许使用CARLA模拟器或衍生物提供的任何特权信息,包括世界坐标、规划者或任何类型的地面实况。使用这些功能的提交将被拒绝,团队将被禁止进入平台。',
+ con3: '如果CARLA排行榜的组织发现任何违反这些条款的行为、试图绕过排行榜规则的行为或任何其他可能被视为不诚实的行为,该组织保留取消提交资格和/或禁止您和/或您的团队成员参加CARLA排行表的权利。',
+ },
+ },
+ submission: {
+ guidelines: '投稿须知',
+ guideTxt: '客户可以快速刷卡。确实打败了当年的新闻学习。表面她倾向。账户播放食物索赔,尽管女儿改变了用途。',
+ submission: '提交',
+ selectPhase: '选定的阶段',
+ startDate: '开始时间',
+ endDate: '结束时间',
+ todayRemain: '今天剩余提交次数',
+ monthRemain: '当月剩余提交次数',
+ totalRemain: '总共剩余提交次数',
+ instruction: '提交说明',
+ install: '安装',
+ addToken: '将您的Eval帐户token添加到EvalAI-cli',
+ copySuccess: '命令已复制到剪贴板',
+ clipboardSuccess: '已复制到剪贴板',
+ flagTxt: '在提交命令中使用 --private 或 --public 标志可分别将提交设为private或public。',
+ forMore: '有关更多命令,请参阅 ',
+ referDocument: 'arena cli文档。',
+ deregisterChallenge: '点击这里退出此比赛',
+ deregister: '退出比赛',
+ notApproved: '抱歉,参赛团队还没有得到主持人的批准。',
+ deregisterSuccess: '您已成功从比赛中退出。',
+ list: '提交列表',
+ deregisterTeam: '退出比赛',
+ deregisterConfirm: '你确定团队要退出比赛吗?',
+ phasePH: '选择阶段',
+ notCancelled: '只有未处理的提交才能取消',
+ changeMade: '提交已被置为',
+ public: '公开',
+ private: '非公开',
+ team: '参赛团队',
+ createdBy: '创建者',
+ status: '状态',
+ executTime: '执行时间(秒)',
+ submittedFile: '提交文件',
+ resultFile: '执行结果',
+ stdoutFile: '标准输出',
+ stderrFile: '标准错误',
+ submittedAt: '提交时间',
+ showOnLeaderboard: '参与排名',
+ verifySubmission: '验证提交',
+ sureCancelSubmission: '您确定要取消提交吗?',
+ cancelSuccess: '提交成功取消!',
+ },
+ leaderboard: {
+ team: '团队',
+ score: '得分',
+ lastSubmission: '上次提交时间',
+ rank: '排行',
+ orderScore: '按分数排序',
+ },
+ approval: {
+ teamId: '团队ID',
+ member: '团队成员',
+ state: '状态',
+ approve: '批准',
+ disagree: '不同意',
+ approveTeam: '团队审批',
+ approveNote: '注意: 已提交作品的参赛团队不能被拒绝',
+ approveSuccess: '参与者团队批准成功。',
+ disapproveSuccess: '参与者团队否决成功。',
+ },
+};
diff --git a/frontend/src/layout/Index.vue b/frontend/src/layout/Index.vue
new file mode 100644
index 0000000000..f1c2ae25fa
--- /dev/null
+++ b/frontend/src/layout/Index.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('challenge.challenge') }}
+
+
+
+
+
+
+
+ {{ $t('team.team') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/main.js b/frontend/src/main.js
new file mode 100644
index 0000000000..f9b0523e16
--- /dev/null
+++ b/frontend/src/main.js
@@ -0,0 +1,16 @@
+import './styles/global.scss';
+import '@/assets/iconfont/iconfont';
+import 'element-plus/theme-chalk/dark/css-vars.css';
+import 'ress/dist/ress.min.css';
+
+import { createApp } from 'vue';
+import App from './App.vue';
+import router from './router';
+import i18n from './lang/index';
+import './permission';
+import store from './store';
+import Directive from './directives';
+
+const app = createApp(App);
+
+app.use(store).use(router).use(i18n).use(Directive).mount('#app');
diff --git a/frontend/src/permission.js b/frontend/src/permission.js
new file mode 100644
index 0000000000..85a7f02d1d
--- /dev/null
+++ b/frontend/src/permission.js
@@ -0,0 +1,43 @@
+import router from './router';
+import store from './store';
+
+const whiteList = ['/auth/verifyEmail', '/challenge/detail/100'];
+
+// 守卫
+router.beforeEach((to, from, next) => {
+ if (store.state.token) {
+ if (to.path === '/auth/verifyEmail') {
+ next();
+ } else if (to.path.startsWith('/auth/')) {
+ next({ path: '/' });
+ } else {
+ if (!store.state.userInfo.pk) {
+ store
+ .dispatch('getUserInfo')
+ .then((res) => {
+ next({ ...to, replace: true });
+ })
+ .catch((err) => {
+ store
+ .dispatch('logOut')
+ .then((res) => {
+ next({ path: '/' });
+ })
+ .catch((err) => {
+ next({ path: '/' });
+ });
+ });
+ } else {
+ next();
+ }
+ }
+ } else {
+ // 没有token
+ if (to.path.startsWith('/auth/') || whiteList.indexOf(to.path) !== -1) {
+ // 在免登录白名单,直接进入
+ next();
+ } else {
+ next(`/auth/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
+ }
+ }
+});
diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
new file mode 100644
index 0000000000..089a6c6c23
--- /dev/null
+++ b/frontend/src/router/index.js
@@ -0,0 +1,91 @@
+import { createRouter, createWebHistory } from 'vue-router';
+import Layout from '../layout/Index.vue';
+import i18n from '@/lang/index.js';
+import store from '../store';
+const redirect = store.state.token ? '/challenge' : '/challenge/detail/100';
+
+const router = createRouter({
+ history: createWebHistory(import.meta.env.BASE_URL),
+ routes: [
+ {
+ path: '',
+ component: Layout,
+ redirect: redirect,
+ children: [
+ {
+ path: '/challenge',
+ name: 'Challenge',
+ meta: { title: i18n.global.t('challenge.challenge') },
+ children: [
+ {
+ path: '',
+ name: 'ChallengeIndex',
+ component: () => import('../views/challenge/Challenge.vue'),
+ },
+ {
+ path: 'detail/:raceId',
+ component: () => import('../views/challenge/Detail.vue'),
+ name: 'EventDetail',
+ meta: {
+ title: i18n.global.t('challenge.eventDetails'),
+ showcrumb: true,
+ activeMenu: '/challenge',
+ },
+ },
+ ],
+ },
+ {
+ path: '/team',
+ component: () => import('../views/team/Team.vue'),
+ name: 'Team',
+ meta: { title: i18n.global.t('team.team') },
+ },
+ {
+ path: '/profile',
+ component: () => import('../views/user/Profile.vue'),
+ name: 'User',
+ meta: { title: i18n.global.t('user.profile') },
+ },
+ {
+ path: '/permissionDenied',
+ component: () => import('../views/permission/Denied.vue'),
+ name: 'Permission',
+ meta: { title: i18n.global.t('permission.denied') },
+ },
+ ],
+ },
+ {
+ path: '/auth',
+ component: () => import('../views/auth/Index.vue'),
+ children: [
+ {
+ path: 'login',
+ name: 'Login',
+ component: () => import('../views/auth/Login.vue'),
+ },
+ {
+ path: 'signup',
+ name: 'Signup',
+ component: () => import('../views/auth/Signup.vue'),
+ },
+ {
+ path: 'forget',
+ name: 'Forget',
+ component: () => import('../views/auth/Forget.vue'),
+ },
+ {
+ path: 'resetcode/:uid/:token',
+ name: 'Resetcode',
+ component: () => import('../views/auth/Resetcode.vue'),
+ },
+ {
+ path: 'verifyEmail',
+ name: 'VerifyEmail',
+ component: () => import('../views/auth/VerifyEmail.vue'),
+ },
+ ],
+ },
+ ],
+});
+
+export default router;
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
new file mode 100644
index 0000000000..0b1a1a9ecf
--- /dev/null
+++ b/frontend/src/store/index.js
@@ -0,0 +1,89 @@
+import { createStore } from 'vuex';
+import { getUser, login, register, logout } from '@/api/user.js';
+import { getToken, setToken, removeToken, removeJwtToken } from '@/utils/auth';
+
+export default createStore({
+ state: {
+ userInfo: {},
+ token: getToken() || '',
+ },
+ getters: {},
+ mutations: {
+ setUser(state, payload) {
+ state.userInfo = payload;
+ },
+ setToken(state, payload) {
+ state.token = payload;
+ },
+ clearStore(state) {
+ state.userInfo = {};
+ state.token = '';
+ },
+ },
+ actions: {
+ // 登录
+ login({ commit }, userInfo) {
+ return new Promise((resolve, reject) => {
+ login(userInfo)
+ .then((res) => {
+ if (res?.token) {
+ setToken(res.token);
+ commit('setToken', res.token);
+ resolve();
+ } else {
+ reject(new Error('login fail'));
+ }
+ })
+ .catch((error) => {
+ reject(error);
+ });
+ });
+ },
+
+ // 注册
+ signUp({ commit }, userInfo) {
+ return new Promise((resolve, reject) => {
+ register(userInfo)
+ .then((res) => {
+ if (res?.key) {
+ setToken(res.key);
+ commit('setToken', res.key);
+ resolve();
+ } else {
+ reject(new Error('sign up fail'));
+ }
+ })
+ .catch((error) => {
+ reject(error);
+ });
+ });
+ },
+
+ // 获取当前用户信息
+ getUserInfo({ commit }) {
+ return getUser().then((res) => {
+ commit('setUser', res);
+ });
+ },
+
+ // 退出系统
+ logOut({ commit }) {
+ return new Promise((resolve, reject) => {
+ logout()
+ .then((res) => {
+ removeToken();
+ removeJwtToken();
+ commit('clearStore');
+ resolve(res);
+ })
+ .catch((error) => {
+ removeToken();
+ removeJwtToken();
+ commit('clearStore');
+ reject(error);
+ });
+ });
+ },
+ },
+ modules: {},
+});
diff --git a/frontend/src/styles/base.scss b/frontend/src/styles/base.scss
new file mode 100644
index 0000000000..f91c959aec
--- /dev/null
+++ b/frontend/src/styles/base.scss
@@ -0,0 +1,238 @@
+:root {
+ --vt-c-white: #ffffff;
+ --vt-c-white-soft: #f8f8f8;
+ --vt-c-white-mute: #f2f2f2;
+
+ --vt-c-black: #181818;
+ --vt-c-black-soft: #222222;
+ --vt-c-black-mute: #282828;
+
+ --vt-c-indigo: #2c3e50;
+
+ --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
+ --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
+ --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
+ --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
+
+ --vt-c-text-light-1: var(--vt-c-indigo);
+ --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
+ --vt-c-text-dark-1: var(--vt-c-white);
+ --vt-c-text-dark-2: #ffffff;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ font-weight: normal;
+}
+
+body {
+ min-height: 100vh;
+ color: var(--color-text);
+ background: var(--color-background);
+ transition: color 0.5s, background-color 0.5s;
+ line-height: 1;
+ font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ font-size: 14px;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.flex {
+ display: flex;
+}
+
+.flex-between {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.flex-center {
+ display: flex;
+ align-items: center;
+}
+
+/* 页面一级标题,一般用于区块的标题 */
+.first-title {
+ font-size: 18px;
+ font-weight: 400;
+ line-height: 24px;
+}
+
+/* 二级标题, 一般用于卡片或弹框内的标题 */
+.second-title {
+ font-size: 18px;
+ font-weight: 400;
+ line-height: 18px;
+ position: relative;
+ &::before {
+ width: 3px;
+ height: 16px;
+ background-color: var(--el-color-primary);
+ content: '';
+ position: absolute;
+ top: 50%;
+ left: -11px;
+ transform: translateY(-50%);
+ }
+}
+
+.ellipsis {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.small-scrollbar,
+.el-textarea__inner {
+ overflow-y: auto;
+
+ &::-webkit-scrollbar {
+ width: 3px;
+ height: 3px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ border-radius: 4px;
+ background-color: #464951;
+ }
+
+ &::-webkit-scrollbar-track {
+ border-radius: 4px;
+ background-color: transparent;
+ }
+}
+
+.icon {
+ width: 1em;
+ height: 1em;
+ vertical-align: -0.15em;
+ fill: currentColor;
+ overflow: hidden;
+}
+
+/** 基础通用 **/
+
+.mr4 {
+ margin-right: 4px;
+}
+
+.pt5 {
+ padding-top: 5px;
+}
+
+.pr5 {
+ padding-right: 5px;
+}
+
+.pb5 {
+ padding-bottom: 5px;
+}
+
+.mt5 {
+ margin-top: 5px;
+}
+
+.ml5 {
+ margin-left: 5px;
+}
+
+.mr5 {
+ margin-right: 5px;
+}
+
+.mb5 {
+ margin-bottom: 5px;
+}
+
+.mr8 {
+ margin-right: 8px;
+}
+
+.ml8 {
+ margin-left: 8px;
+}
+
+.mb8 {
+ margin-bottom: 8px;
+}
+
+.mt10 {
+ margin-top: 10px;
+}
+
+.mr10 {
+ margin-right: 10px;
+}
+
+.mb10 {
+ margin-bottom: 10px;
+}
+
+.mt16 {
+ margin-top: 16px;
+}
+
+.ml16 {
+ margin-left: 16px;
+}
+
+.mr16 {
+ margin-right: 16px;
+}
+
+.mb16 {
+ margin-bottom: 16px;
+}
+
+.ml20 {
+ margin-left: 20px;
+}
+
+.mr20 {
+ margin-right: 20px;
+}
+
+.mb20 {
+ margin-bottom: 20px;
+}
+
+.mb24 {
+ margin-bottom: 24px;
+}
+
+.mt24 {
+ margin-top: 24px;
+}
+
+.mr24 {
+ margin-right: 24px;
+}
+
+.mt32 {
+ margin-top: 32px;
+}
+
+.mb32 {
+ margin-bottom: 32px;
+}
+
+.pointer {
+ cursor: pointer;
+}
+
+.custom-tag {
+ height: 32px;
+ background: #20551c;
+ border-radius: 2px 2px 2px 2px;
+ border: 1px solid #119d05;
+ line-height: 30px;
+ padding: 0 24px;
+ & + .custom-tag {
+ margin-left: 8px;
+ }
+}
diff --git a/frontend/src/styles/global.scss b/frontend/src/styles/global.scss
new file mode 100644
index 0000000000..6391fe3117
--- /dev/null
+++ b/frontend/src/styles/global.scss
@@ -0,0 +1,388 @@
+@import './base.scss';
+body {
+ --el-color-primary: #4562e3;
+ --el-menu-hover-bg-color: #353e4e;
+ --text-color: #ffffff;
+ --el-bg-color: #292f3a;
+
+ .el-button--primary {
+ --el-button-hover-bg-color: #617bf0;
+ --el-button-hover-border-color: #617bf0;
+ --el-button-disabled-bg-color: #304281;
+ --el-button-disabled-border-color: #304281;
+ --el-button-active-border-color: #2a41a8;
+ --el-button-active-bg-color: #2a41a8;
+ }
+ .el-table {
+ --el-table-header-bg-color: #364052;
+ }
+ .el-dropdown {
+ color: #ffffff;
+ }
+ .el-button {
+ &.is-text {
+ color: var(--text-color);
+ }
+ &.is-text:not(.is-disabled).is-has-bg {
+ background-color: #282f3b;
+ border: 1px solid #394253;
+ }
+ }
+ .el-button--large {
+ font-size: 20px;
+ }
+ // 表单样式统一
+ .el-form-item__label {
+ color: var(--text-color);
+ }
+ // 数据框样式统一
+ .el-input__wrapper {
+ background-color: #343c4d;
+ border-radius: 2px;
+ box-shadow: 0 0 0 1px #343c4d inset;
+ &:hover {
+ box-shadow: 0 0 0 1px var(--el-color-primary) inset;
+ }
+ }
+
+ .el-popper > .el-popper__arrow {
+ display: none;
+ }
+
+ // 选择器统一
+ .el-select__popper.el-popper {
+ background: #343c4d;
+ border-radius: 4px 4px 4px 4px;
+ border: 1px solid #7f889a;
+ box-shadow: none;
+ .el-select-dropdown__list {
+ padding: 4px;
+ .el-select-dropdown__item {
+ border-radius: 4px;
+ &.hover {
+ background: transparent;
+ }
+ &:hover {
+ background: #242e3c;
+ }
+ &.selected {
+ background-color: var(--el-color-primary);
+ color: var(--text-color);
+ }
+ & + .el-select-dropdown__item {
+ margin-top: 2px;
+ }
+ }
+ }
+ }
+
+ .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
+ background-color: #364052;
+ }
+}
+
+.icon-button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ width: 32px;
+ height: 32px;
+ border-radius: 2px 2px 2px 2px;
+ &:hover {
+ background: #343c4d;
+ }
+}
+
+.icon-btn {
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+}
+
+:focus-visible {
+ outline: none !important;
+}
+
+.el-form.auth-form {
+ width: 100%;
+
+ .el-form-item {
+ margin-bottom: 32px;
+
+ .el-form-item__label {
+ color: #ffffff;
+ font-size: 16px;
+ line-height: 16px;
+ margin-bottom: 16px;
+ }
+ }
+
+ .el-input {
+ --el-input-focus-border-color: #4562e3;
+ --el-input-border-color: #353f5c;
+ --el-input-bg-color: #0d1427;
+ --el-input-border-radius: 2px;
+
+ .el-input__wrapper {
+ padding: 0 15px;
+
+ &.is-focus {
+ --el-input-bg-color: #0d1427;
+ box-shadow: 0px 0px 0px 1px #4562e3 inset, 0px 0px 1px 2px #353f5c;
+ }
+
+ &:hover {
+ box-shadow: 0px 0px 0px 1px #4562e3 inset, 0px 0px 1px 2px #353f5c;
+ }
+
+ .el-input__inner {
+ color: #ffffff;
+ height: 40px;
+ border-radius: 0;
+ background-color: transparent !important;
+
+ &::placeholder {
+ color: #9a9a9a;
+ }
+
+ // 自动填空底色去除
+ &:-internal-autofill-previewed,
+ &:-internal-autofill-selected {
+ -webkit-text-fill-color: #ffffff;
+ transition: background-color 5000s ease-out 0.5s;
+ }
+ }
+ }
+ }
+}
+
+.auth-submit-btn {
+ width: 100%;
+ height: 40px;
+ margin-top: 24px;
+ background-color: #4562e3;
+ display: grid;
+ font-size: 20px;
+ color: #ffffff;
+ place-items: center;
+ cursor: pointer;
+ user-select: none;
+ margin-top: 40px;
+ margin-bottom: 32px;
+}
+
+.el-form-item:last-child {
+ margin-bottom: 0;
+}
+
+.el-popover.el-popper.logout-popper {
+ padding: 4px 8px 8px;
+ border-radius: 4px 4px 4px 4px;
+ background-color: #292f3a;
+ color: #ffffff;
+ border: 1px solid #424e61;
+ box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.302);
+ .top {
+ height: 80px;
+ display: flex;
+ padding: 0 8px;
+ align-items: center;
+ border-bottom: 1px solid #434d60;
+
+ .icon {
+ margin-right: 10px;
+ }
+ }
+
+ .item {
+ width: 100%;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ padding-left: 16px;
+ border-radius: 2px;
+ cursor: pointer;
+
+ &:hover {
+ background: #4562e3;
+ color: #ffffff;
+ }
+
+ .icon {
+ margin-right: 16px;
+ }
+ }
+}
+
+// 下拉列表dropdown
+.more-dropdown {
+ margin-top: -6px;
+
+ .el-dropdown-menu {
+ padding: 4px 0;
+ }
+
+ .el-dropdown-menu__item {
+ padding: 0 16px;
+ margin-left: 4px;
+ margin-right: 4px;
+ margin-bottom: 4px;
+ height: 32px;
+ border-radius: 2px;
+ color: #ffffff;
+
+ &:not(.is-disabled):hover,
+ &:not(.is-disabled):focus {
+ background-color: var(--el-color-primary);
+ color: #ffffff;
+ }
+ &.active {
+ background-color: var(--el-color-primary);
+ }
+
+ &.danger:not(.is-disabled):hover,
+ &.danger:not(.is-disabled):focus {
+ background-color: #e6595a;
+ }
+
+ &:last-child {
+ margin-bottom: 0px;
+ }
+ }
+
+ .el-popper__arrow {
+ display: none;
+ }
+}
+
+// 弹框样式统一
+.el-dialog.oa-dialog {
+ background: #292f3a;
+ box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.2);
+ border-radius: 6px 6px 6px 6px;
+ .el-dialog__header {
+ padding: 30px 50px 0 30px;
+ margin-right: 0px;
+
+ .el-dialog__headerbtn {
+ width: 40px;
+ height: 40px;
+ top: 16px;
+ right: 18px;
+
+ .el-dialog__close {
+ font-size: 16px;
+ color: var(--text-color);
+ }
+ }
+ }
+
+ .el-dialog__title {
+ color: var(--text-color);
+ font-weight: 700;
+ font-size: 16px;
+ line-height: 1;
+ }
+
+ .el-dialog__body {
+ padding: 24px 30px;
+ }
+
+ .el-dialog__footer {
+ padding: 0px 30px 24px;
+ }
+}
+
+// 确认框重写 自定义了title 和content元素
+.oa-message-box.el-message-box {
+ padding-bottom: 24px;
+
+ .el-message-box__headerbtn {
+ top: 22px;
+ right: 24px;
+
+ .el-message-box__close {
+ color: var(--text-color);
+ }
+ }
+
+ .el-message-box__content {
+ padding: 10px 24px;
+
+ .el-message-box__message {
+ .title {
+ margin-top: -15px;
+ margin-bottom: 20px;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+
+ & > span {
+ font-size: 16px;
+ color: var(--text-color);
+ font-weight: 700;
+ }
+ }
+
+ .content {
+ padding-top: 20px;
+ }
+ }
+ }
+
+ .el-message-box__btns {
+ padding: 10px 24px 0;
+ }
+}
+
+.custom-radio.el-radio {
+ height: 16px;
+ .el-radio__input {
+ &.is-checked .el-radio__inner {
+ background-color: #fff;
+ }
+ }
+ .el-radio__label {
+ display: none;
+ }
+ .el-radio__inner {
+ width: 16px;
+ height: 16px;
+ &::after {
+ background-color: #4562e3;
+ width: 11px;
+ height: 11px;
+ }
+ }
+}
+
+// 页码样式统一
+.oa-pagination.el-pagination.is-background {
+ justify-content: flex-end;
+
+ .btn-next:not(:disabled),
+ .btn-prev:not(:disabled),
+ .el-pager li {
+ background-color: transparent;
+ color: var(--text-color);
+
+ &:not(.is-active):hover {
+ border: 1px solid #394253;
+ background-color: #282f3b;
+ }
+
+ &:not(.is-active):active {
+ border: 1px solid #4562e3;
+ background-color: #282f3b;
+ }
+ }
+
+ .btn-next:disabled,
+ .btn-prev:disabled {
+ background-color: transparent;
+ }
+}
diff --git a/frontend/src/utils/auth.js b/frontend/src/utils/auth.js
new file mode 100644
index 0000000000..b1ad7a5406
--- /dev/null
+++ b/frontend/src/utils/auth.js
@@ -0,0 +1,27 @@
+const TokenKey = 'Admin-Token';
+
+export function getToken() {
+ return localStorage.getItem(TokenKey);
+}
+
+export function setToken(token) {
+ localStorage.setItem(TokenKey, token);
+}
+
+export function removeToken() {
+ localStorage.removeItem(TokenKey);
+}
+
+const JwtKey = 'Jwt-Token';
+
+export function getJwtToken() {
+ return localStorage.getItem(JwtKey);
+}
+
+export function setJwtToken(token) {
+ localStorage.setItem(JwtKey, token);
+}
+
+export function removeJwtToken() {
+ localStorage.removeItem(JwtKey);
+}
diff --git a/frontend/src/utils/errorCode.js b/frontend/src/utils/errorCode.js
new file mode 100644
index 0000000000..681731d009
--- /dev/null
+++ b/frontend/src/utils/errorCode.js
@@ -0,0 +1,56 @@
+import i18n from '@/lang/index.js';
+export default {
+ 401: '认证失败,无法访问系统资源',
+ 403: '当前操作没有权限',
+ 404: '访问资源不存在',
+ default: '系统未知错误,请反馈给管理员',
+};
+
+// 错误信息
+export const errorMsg = [
+ { zh: '该用户名已经存在。', en: 'A user with that username already exists.' },
+ { zh: '此电子邮件地址已被注册。', en: 'A user is already registered with this e-mail address.' },
+ { zh: '两个密码字段不匹配。', en: "The two password fields didn't match." },
+ { zh: '无法使用提供的凭据登录。', en: 'Unable to log in with provided credentials.' },
+ { zh: '这个密码过于简单。', en: 'This password is too common.' },
+ { zh: '此密码完全是数字。', en: 'This password is entirely numeric.' },
+ { zh: '无效密码', en: 'Invalid password' },
+ { zh: '不存在给定电子邮件的用户。', en: 'User with the given email does not exist.' },
+ { zh: '您无权更改团队详细信息!', en: 'You are not a authorized to change team details!' },
+ { zh: '此团队名称已存在。', en: 'participant team with this team name already exists.' },
+ { zh: '请输入一个有效地址。', en: 'Enter a valid URL.' },
+ { zh: '用户处于非活动状态或已删除', en: 'User inactive or deleted' },
+ { zh: '该用户已经是团队的一员!', en: 'User is already part of the team!' },
+ { zh: '很抱歉,您无法删除此团队,因为它已参加挑战!', en: 'Sorry, you cannot delete this team since it has taken part in challenge(s)!' },
+ { zh: '此电子邮件地址的用户不存在!', en: 'User does not exist with this email address!' },
+ { zh: '请确保此字段的字符数不超过1000个。', en: 'Ensure this field has no more than 1000 characters.' },
+ { zh: '此字段为必填字段。', en: 'This field is required.' },
+ { zh: '团队尚未参加挑战', en: 'Team has not participated in the challenge' },
+ { zh: '很抱歉,您没有删除此参与者团队的权限', en: 'Sorry, you do not have permissions to remove this participant team' },
+ { zh: '请求被阻止。预计2751秒后可用。', en: 'Request was throttled. Expected available in 2751 seconds.' },
+ {
+ zh: '很抱歉,其他团队成员已经参加了挑战。请加入其他团队!',
+ en: 'Sorry, other team member(s) have already participated in the Challenge. Please participate with a different team!',
+ },
+ { zh: '比赛不存在', en: 'Challenge does not exist' },
+ { zh: '您无权提出此请求', en: 'You are not authorized to make this request' },
+ { zh: '队伍名已被占用!', en: 'The team name has already be used!' },
+ { zh: '已提交参赛作品的参赛队伍不能被取消注册。', en: 'Participant teams which have made submissions to a challenge cannot be deregistered.' },
+ { zh: '比赛未开始', en: 'Challenge is not active' },
+ { zh: '团队已存在', en: 'Team already exists' },
+ { zh: '抱歉,比赛已被移除!', en: 'Sorry, the challenge was removed!' },
+ { zh: '抱歉,排行榜是不公开的!', en: 'Sorry, the leaderboard is not public!' },
+ { zh: '您还没有参加比赛', en: "You haven't participated in the challenge" },
+ { zh: '您不是参与者!', en: "You are not a participant!" },
+];
+
+export function getErrMsg(msg) {
+ if (i18n.global.locale.value === 'zh') {
+ for (let i = 0; i < errorMsg.length; i++) {
+ if (errorMsg[i].en === msg) {
+ return errorMsg[i].zh;
+ }
+ }
+ }
+ return msg;
+}
diff --git a/frontend/src/utils/jsencrypt.js b/frontend/src/utils/jsencrypt.js
new file mode 100644
index 0000000000..37b824ae27
--- /dev/null
+++ b/frontend/src/utils/jsencrypt.js
@@ -0,0 +1,39 @@
+import JSEncrypt from "jsencrypt/bin/jsencrypt.min";
+
+// 密钥对生成 http://web.chacuo.net/netrsakeypair
+
+const publicKey =
+ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8sSV5EDqHfOhNPRy0KND6HiEc\n" +
+ "q1LwpYxTKBUHfXb43XVaMn2ySbgOCiMrTtuH0nAfhQ/LuKhxiFnEKEfjTHIHPVG6\n" +
+ "A+Ucaj4Ywm/OIogA1owvxr39zNgP/E52e06RVXm9Kubjj/J1Ik593Kj53XxrX4ss\n" +
+ "oatyw7rUIvl60f+VPQIDAQAB";
+
+const privateKey =
+ "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALyxJXkQOod86E09\n" +
+ "HLQo0PoeIRyrUvCljFMoFQd9dvjddVoyfbJJuA4KIytO24fScB+FD8u4qHGIWcQo\n" +
+ "R+NMcgc9UboD5RxqPhjCb84iiADWjC/Gvf3M2A/8TnZ7TpFVeb0q5uOP8nUiTn3c\n" +
+ "qPndfGtfiyyhq3LDutQi+XrR/5U9AgMBAAECgYBq8Zvjeacyk0C2RiS2l0uZ9umd\n" +
+ "bhyb97gIiXchv6Jmel3AuU00d0Ox8VztdsxFtqeFtcy2EfqmHjmCS7IyyWj2Zw8W\n" +
+ "B3ZdxHPXG0cWC3XaAuRTfR8ftkNt4ECz7BCN0JzftxE2kNxT8EmLc7igmu100XA+\n" +
+ "q70vbhrMYH3E92ngAQJBAPL3BPVSvFdaGp/O/2eiXvnedzP79FTtY5rafxBBXTiU\n" +
+ "Xmqp1zKQyhLjwk8Ln+PjN1FggpKa/gKOtFRX8M4OcwECQQDG0LhR6yohb4TzY25j\n" +
+ "ena9bXFTm70fPDEuBSr+SoCwlr4qXs7tmW78BrBS+eVyTmJu13ZQJ3s88GTe78uz\n" +
+ "5C49AkAlMvDNZrdzYFZHNXghM9j6xLbXfLHx9s6TPPTLVlahfQXfqtVJ5qUpszli\n" +
+ "xNLcH0Ou7+nN7HELjzHI4BX8VnYBAkBc6s1KE9MT30/OhEjiGykFbPHK9n1T7Mi7\n" +
+ "TlUClYVBgqILoVWqe8v/44xiq0INww6D6RT1bw5Ms7kg7AdS4rCtAkEA0rGsJ4q1\n" +
+ "QnG44BLFKJUPsPRNCvIozOmeCBVqipNL3Krk3G+TxX8qhzAnTp07Vx64vTL09ka0\n" +
+ "9HLCE2ZsxYsXBw==";
+
+// 加密
+export function encrypt(txt) {
+ const encryptor = new JSEncrypt();
+ encryptor.setPublicKey(publicKey); // 设置公钥
+ return encryptor.encrypt(txt); // 对数据进行加密
+}
+
+// 解密
+export function decrypt(txt) {
+ const encryptor = new JSEncrypt();
+ encryptor.setPrivateKey(privateKey); // 设置私钥
+ return encryptor.decrypt(txt); // 对数据进行解密
+}
diff --git a/frontend/src/utils/tool.js b/frontend/src/utils/tool.js
new file mode 100644
index 0000000000..90f71ed7c2
--- /dev/null
+++ b/frontend/src/utils/tool.js
@@ -0,0 +1,55 @@
+import i18n from '@/lang/index.js';
+// 验证是否为blob格式
+export function blobValidate(data) {
+ return data.type !== 'application/json';
+}
+
+/**
+ * 确认弹框 默认以删除任务为例
+ * @param {*} params
+ * @returns promise
+ */
+export function oaMessageBox(params = {}, extraConfig = {}) {
+ const {
+ icon,
+ title = '删除所选任务',
+ message = '删除后将无法恢复,请确认是否删除?',
+ confirmButtonText = i18n.global.t('yes'),
+ cancelButtonText = i18n.global.t('no'),
+ } = params;
+ let style = icon ? '' : 'display:none;';
+ return ElMessageBox.confirm(
+ `
+
+
+
+
+ ${title}
+
+
${message}
+ `,
+ {
+ dangerouslyUseHTMLString: true,
+ confirmButtonText,
+ cancelButtonText,
+ cancelButtonClass: 'is-text is-has-bg',
+ customClass: 'oa-message-box',
+ ...extraConfig,
+ }
+ );
+}
+
+// 格式化时间
+export function formatTime(value) {
+ const date = new Date(value);
+ const options = {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ hour12: true,
+ };
+ return date.toLocaleString(i18n.global.locale.value, options);
+}
diff --git a/frontend/src/views/auth/Forget.vue b/frontend/src/views/auth/Forget.vue
new file mode 100644
index 0000000000..9bfe1a5b75
--- /dev/null
+++ b/frontend/src/views/auth/Forget.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+ {{ $t('forget.restext') }}
+ {{ $t('forget.backloginTxt') }}
+
+
+
+
{{ $t('forget.title') }}
+
+
+ {{ $t('forget.prompt') }}
+
+
+
+
+ {{ $t('forget.submit') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/auth/Index.vue b/frontend/src/views/auth/Index.vue
new file mode 100644
index 0000000000..43b8cc9a08
--- /dev/null
+++ b/frontend/src/views/auth/Index.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
diff --git a/frontend/src/views/auth/Login.vue b/frontend/src/views/auth/Login.vue
new file mode 100644
index 0000000000..23718d7cf5
--- /dev/null
+++ b/frontend/src/views/auth/Login.vue
@@ -0,0 +1,132 @@
+
+
+
+
+ {{ $t('greeting') }}
+
+
+
+
+
+
+
+
+ {{ $t('login.forgotpw') }}
+ {{ $t('login.login') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/auth/Resetcode.vue b/frontend/src/views/auth/Resetcode.vue
new file mode 100644
index 0000000000..5d7dab5262
--- /dev/null
+++ b/frontend/src/views/auth/Resetcode.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ {{ $t('reset.restext') }}
+ {{ $t('reset.login') }}
+
+
+ {{ $t('greeting') }}
+
+
+
+
+
+
+
+ {{ $t('reset.submit') }}
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/auth/Signup.vue b/frontend/src/views/auth/Signup.vue
new file mode 100644
index 0000000000..a49553eeca
--- /dev/null
+++ b/frontend/src/views/auth/Signup.vue
@@ -0,0 +1,133 @@
+
+
+
+
+ {{ $t('greeting') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('signup.signup') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/auth/VerifyEmail.vue b/frontend/src/views/auth/VerifyEmail.vue
new file mode 100644
index 0000000000..029be5107a
--- /dev/null
+++ b/frontend/src/views/auth/VerifyEmail.vue
@@ -0,0 +1,29 @@
+
+
+
+
+ {{ $t('permission.emailVerifiedSuccess') }}
+ {{ $t('login.login') }}
+
+
+
+
+
diff --git a/frontend/src/views/challenge/AllSubmission.vue b/frontend/src/views/challenge/AllSubmission.vue
new file mode 100644
index 0000000000..84a9b36532
--- /dev/null
+++ b/frontend/src/views/challenge/AllSubmission.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+ {{ row.status.charAt(0).toUpperCase() + row.status.slice(1) }}
+
+
+
+
+
+ Link
+ -
+
+
+
+
+ Link
+ -
+
+
+
+
+ Link
+ -
+
+
+
+
+
+
+
+
+
+ {{ $t('loadMore') }}...
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Approval.vue b/frontend/src/views/challenge/Approval.vue
new file mode 100644
index 0000000000..d7d242febe
--- /dev/null
+++ b/frontend/src/views/challenge/Approval.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+ {{ row.members.map((item) => item.member_name).join(';') }}
+
+
+
+
+
+ {{ row.approved ? $t('approval.approve') : $t('approval.disagree') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Challenge.vue b/frontend/src/views/challenge/Challenge.vue
new file mode 100644
index 0000000000..daa7deacba
--- /dev/null
+++ b/frontend/src/views/challenge/Challenge.vue
@@ -0,0 +1,58 @@
+
+ {{ $t('challenge.challenge') }}
+
+
+
{{ $t(`race_${item.id}.title`) }}
+
{{ $t(`race_${item.id}.describe`) }}
+
+
{{ $t('challenge.ongoing') }}
+
2023/04/01-2023/12/31
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Detail.vue b/frontend/src/views/challenge/Detail.vue
new file mode 100644
index 0000000000..d4fcaea935
--- /dev/null
+++ b/frontend/src/views/challenge/Detail.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
{{ $t(`race_${raceId}.title`) }}
+
{{ $t('submission.deregister') }}
+
+
+ {{ $t(`race_${raceId}.describe`) }}
+
+
+
2023/04/01-2023/12/31
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Leaderboard.vue b/frontend/src/views/challenge/Leaderboard.vue
new file mode 100644
index 0000000000..67cc14411d
--- /dev/null
+++ b/frontend/src/views/challenge/Leaderboard.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Overview.vue b/frontend/src/views/challenge/Overview.vue
new file mode 100644
index 0000000000..a14c92e1db
--- /dev/null
+++ b/frontend/src/views/challenge/Overview.vue
@@ -0,0 +1,58 @@
+
+ {{ $t('overview.view.title') }}
+
+
{{ $t('overview.view.con1') }}
+
{{ $t('overview.view.con2') }}
+
{{ $t('overview.view.con3') }}
+
{{ $t('overview.view.con4') }}
+
{{ $t('overview.view.con5') }}
+
+ {{ $t('overview.eval.title') }}
+
+
{{ $t('overview.eval.con1') }}
+
{{ $t('overview.eval.con2') }}
+
+ {{ $t('overview.term.title') }}
+
+
{{ $t('overview.term.con1') }}
+
{{ $t('overview.term.con2') }}
+
{{ $t('overview.term.sub1T') }}
+
+ {{ $t('overview.term.sub1C1') }}
+
+
+ {{ $t('overview.term.sub1C2') }}
+
+
{{ $t('overview.term.sub2T') }}
+
+ {{ $t('overview.term.sub2C1') }}
+
+
{{ $t('overview.term.sub3T') }}
+
+ {{ $t('overview.term.sub3C1') }}
+
+
{{ $t('overview.term.con3') }}
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Participate.vue b/frontend/src/views/challenge/Participate.vue
new file mode 100644
index 0000000000..780fc8ff71
--- /dev/null
+++ b/frontend/src/views/challenge/Participate.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
{{ item.team_name }}
+
+
+
+
{{
+ $t('challenge.participate')
+ }}
+
+
+
+
{{ $t('challenge.noTeam') }}
+
{{ $t('challenge.startCreate') }}
+
+
+
{{ $t('team.createTeam') }}
+
+
+
+
+
+
+
+
+
+ {{ $t('create') }}
+
+
+
+
+ {{ $t('challenge.please') }}
+
+ {{ $t('challenge.login') }}
+
+ {{ $t('challenge.partiChall') }}
+
+
+
+
+
+
diff --git a/frontend/src/views/challenge/Submission.vue b/frontend/src/views/challenge/Submission.vue
new file mode 100644
index 0000000000..26aaa25ea1
--- /dev/null
+++ b/frontend/src/views/challenge/Submission.vue
@@ -0,0 +1,362 @@
+
+ {{ $t('submission.guidelines') }}
+ {{ $t('submission.guideTxt') }}
+
+
+ {{ $t('submission.deregisterChallenge') }}:
+ {{ $t('submission.deregister') }}
+
+
{{ $t('submission.notApproved') }}
+
+
+
+ {{ $t('submission.submission') }}
+ {{ $t('submission.selectPhase') }}
+
+
+
+ {{ $t('submission.todayRemain') }}:
+ {{ curPhase.max_submissions_per_day }}
+
+
+ {{ $t('submission.monthRemain') }}:
+ {{ curPhase.max_submissions_per_month }}
+
+
+ {{ $t('submission.totalRemain') }}:
+ {{ curPhase.max_submissions }}
+
+
+
+ —
+
+
+
+
+
+ {{ $t('submission.startDate') }}:
+ {{ formatTime(item.start_date) }}
+
+
+ {{ $t('submission.endDate') }}:
+ {{ formatTime(item.end_date) }}
+
+
+
+
+
{{ $t('submission.instruction') }}
+
+
1. {{ $t('submission.install') }}
+
+ $ {{ commandTxt1 }}
+
+
+
+
+
+
+
+
2. {{ $t('submission.addToken') }}
+
+ $ {{ commandTxt2 }}
+
+
+
+
+
+
+
3. {{ $t('submission.submission') }}
+
+ $ {{ commandTxt3 }}
+
+
+
+
+
+
+
4. {{ $t('submission.flagTxt') }}
+
+ 5. {{ $t('submission.forMore') }}
+
+ {{ $t('submission.referDocument') }}
+
+
+
+
+
+ {{ $t('submission.list') }}
+
+
+
+
+
+
+
+ {{ row.status.charAt(0).toUpperCase() + row.status.slice(1) }}
+
+
+
+
+
+
+ Link
+ -
+
+
+
+
+ Link
+ -
+
+
+
+
+ Link
+ -
+
+
+
+
+
+
+ {{ row.is_public ? $t('submission.public') : $t('submission.private') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('loadMore') }}...
+
+
+
+
+
+
+
diff --git a/frontend/src/views/permission/Denied.vue b/frontend/src/views/permission/Denied.vue
new file mode 100644
index 0000000000..e5906e1082
--- /dev/null
+++ b/frontend/src/views/permission/Denied.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+ {{ isSended ? $t('permission.continueVerify') : $t('permission.verifyEmail') }}
+
+
+
+
+
+ {{ $t('permission.resendEmail') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/team/Team.vue b/frontend/src/views/team/Team.vue
new file mode 100644
index 0000000000..3131486536
--- /dev/null
+++ b/frontend/src/views/team/Team.vue
@@ -0,0 +1,279 @@
+
+
+
{{ $t('team.team') }}
+
+
+
+
+ {{ $t('team.createTeam') }}
+
+
+
+
+
+
{{ item.team_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('team.createdBy') }}:
+ {{ item.created_by }}
+
+
+
{{ $t('team.members') }}:
+
+
+
+
+
+
+
No team
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('cancel') }}
+ {{ $t('save') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('cancel') }}
+ {{ $t('send') }}
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/user/Profile.vue b/frontend/src/views/user/Profile.vue
new file mode 100644
index 0000000000..ee4101e978
--- /dev/null
+++ b/frontend/src/views/user/Profile.vue
@@ -0,0 +1,263 @@
+
+
+
+
+
+ {{ $t('back') }}
+
+
+
{{ $t('user.profile') }}
+
+
+
+
+
{{ store.state.userInfo?.username }}
+
{{ store.state.userInfo?.email }}
+
+
+
+
+
{{ $t('user.profileCompleted') }}
+
+
+
+
+
{{ $t('user.password') }}
+
{{ $t('user.changePassword') }}
+
+
+
{{ $t('user.firstName') }}
+
+
+
+
{{ $t('user.lastName') }}
+
+
+
+
{{ $t('user.affilliate') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('cancel') }}
+ {{ $t('submit') }}
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/web/about-us.html b/frontend/src/views/web/about-us.html
deleted file mode 100644
index 9aea5e17e1..0000000000
--- a/frontend/src/views/web/about-us.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
About Us
-
EvalAI is built by a team of open source enthusiasts working at
- CloudCV . CloudCV aims to make AI research
- reproducible and easily accessible. We want to reduce the barrier to entry for doing research
- and make it easier for researchers, students and developers to develop and use state-of-the-art
- algorithms as a service.
-
With EvalAI, we want to standardize the process of
- evaluating different methods on a dataset and make it simple to host a competition.
- Comparing a new method with other existing approaches is an essential component of
- research and this process has traditionally been affected by difference in evaluation
- metric implementation, different splits of the dataset or minor modifications in the
- algorithm. This makes it extremely hard to reproduce numbers from published papers
- and reliably compare your method with other existing approaches. By building EvalAI, we
- hope to make this easier by standardizing the dataset splits, evaluation metrics and by
- maintaining a public leaderboard of hosted challenges.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/views/web/analytics/host-analytics.html b/frontend/src/views/web/analytics/host-analytics.html
deleted file mode 100644
index 4118655ad9..0000000000
--- a/frontend/src/views/web/analytics/host-analytics.html
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
Challenges Analytics Home
-
-
-
-
-
Select challenge to view Analysis
-
-
- Total Challenges hosted :
-
-
- {{analytics.challengeListCount}}
-
-
-
-
Show Analysis
-
-
-
Challenge Analysis
-
Please select challenge for analysis.
-
There are no challenges to analyze. Click
here to create a new challenge.
-
-
-
-
-
-
-
-
-
-
{{analytics.currentChallengeDetails.title}}
-
- Hosted by: {{analytics.currentChallengeDetails.creator.team_name}}
-
-
-
-
-
- Short Description
-
-
- {{analytics.currentChallengeDetails.short_description}}
-
-
-
-
- Total Participant Teams:
-
-
- {{analytics.totalChallengeTeams}}
-
-
Download
-
-
-
- Challenge Phases
-
-
-
- {{item.name}}
-
-
- Challenge Phase Duration
-
-
- {{item.start_date | date:'medium'}} - {{item.end_date | date:'medium'}}
-
-
-
-
- Total Submissions
-
-
- {{analytics.totalSubmission[item.id] || 0}}
-
-
-
-
-
- Participant Teams
-
-
- {{analytics.totalParticipatedTeams[item.id] || 0}}
-
-
-
-
-
- Latest Submission At
-
-
- {{analytics.lastSubmissionTime[item.id] | date:'medium'}}
-
-
- None
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/views/web/auth/auth.html b/frontend/src/views/web/auth/auth.html
deleted file mode 100644
index a72cc1a28c..0000000000
--- a/frontend/src/views/web/auth/auth.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Evaluating state of the art in AI!
-
-
-
-
-
-
-
-
diff --git a/frontend/src/views/web/auth/get-token.html b/frontend/src/views/web/auth/get-token.html
deleted file mode 100644
index 90232577a5..0000000000
--- a/frontend/src/views/web/auth/get-token.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
diff --git a/frontend/src/views/web/auth/login.html b/frontend/src/views/web/auth/login.html
deleted file mode 100644
index c800bbeee9..0000000000
--- a/frontend/src/views/web/auth/login.html
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
diff --git a/frontend/src/views/web/auth/reset-password-confirm.html b/frontend/src/views/web/auth/reset-password-confirm.html
deleted file mode 100644
index 176036e920..0000000000
--- a/frontend/src/views/web/auth/reset-password-confirm.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
diff --git a/frontend/src/views/web/auth/reset-password.html b/frontend/src/views/web/auth/reset-password.html
deleted file mode 100644
index d05b31ccb7..0000000000
--- a/frontend/src/views/web/auth/reset-password.html
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
-
- Password reset link has been sent to your registered email address. Please check your email inbox.
-
-
-
-
-
- Back to Log In
-
-
-
-
-
-
diff --git a/frontend/src/views/web/auth/signup.html b/frontend/src/views/web/auth/signup.html
deleted file mode 100644
index 4891400a93..0000000000
--- a/frontend/src/views/web/auth/signup.html
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
diff --git a/frontend/src/views/web/auth/verify-email.html b/frontend/src/views/web/auth/verify-email.html
deleted file mode 100644
index 948bd3afd6..0000000000
--- a/frontend/src/views/web/auth/verify-email.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/frontend/src/views/web/challenge-create.html b/frontend/src/views/web/challenge-create.html
deleted file mode 100644
index b1243176f9..0000000000
--- a/frontend/src/views/web/challenge-create.html
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
Challenge creation using GitHub
-
-
-
- Use this repository as template. You can read more about templates here.
- Generate your github personal acccess token and copy it in clipboard.
- Add the github personal access token in the forked repository's secrets with the name AUTH_TOKEN .
- Now, go to EvalAI to fetch the following details -
-
- evalai_user_auth_token - Go to profile page after logging in and click on Get your Auth Token to copy your auth token.
- host_team_pk - Go to host team page and copy the ID for the team you want to use for challenge creation.
- evalai_host_url - Use https://eval.ai for production server and https://staging.eval.ai for staging server.
-
- Create a branch with name challenge in the forked repository from the `master` branch.
-
- Note : Only changes to challenge branch will be synchronized with challenge on EvalAI.
- Add evalai_user_auth_token and host_team_pk in github/host_config.json .
- Read EvalAI challenge creation documentation to know more about how you want to structure your challenge. Once you are ready, start making changes in the yaml file, HTML templates, evaluation script according to your need.
- Commit the changes and push the challenge branch in the repository and wait for the build to complete. View the logs of your build .
- If challenge config contains errors then a issue will be opened automatically in the repository with the errors otherwise the challenge will be created on EvalAI.
- Go to Hosted Challenges to view your challenge. The challenge will be publicly available once EvalAI admin approves the challenge.
- To update the challenge on EvalAI, make changes in the repository and push to the challenge branch and wait for the build to complete.
-
-
-
-
-
-
-
-
diff --git a/frontend/src/views/web/challenge-host-teams.html b/frontend/src/views/web/challenge-host-teams.html
deleted file mode 100644
index 6a31647be6..0000000000
--- a/frontend/src/views/web/challenge-host-teams.html
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
Select a Challenge Host Team
-
-
-
{{challengeHostTeams.paginationMsg}}
-
-
-
-
-
Team Members:
-
{{member.user}}
-
-
-
-
-
-
-
-
-
-
Create a New Team
-
-
-
-
-
-
diff --git a/frontend/src/views/web/challenge-invite.html b/frontend/src/views/web/challenge-invite.html
deleted file mode 100644
index 40514b0241..0000000000
--- a/frontend/src/views/web/challenge-invite.html
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
- Challenge Invitation
-
-
-
-
- You have been invited to participate in {{challenge_invitation.challengeTitle}} hosted by {{challenge_invitation.host}} on EvalAI.
- Please enter your personal information below to participate in the challenge.
-
-
-
-
-
-
-
-
diff --git a/frontend/src/views/web/challenge-list.html b/frontend/src/views/web/challenge-list.html
deleted file mode 100644
index b0e1247c4c..0000000000
--- a/frontend/src/views/web/challenge-list.html
+++ /dev/null
@@ -1,97 +0,0 @@
-