From 11c8f00f0f5271f55c2452d725ad0301e0565d17 Mon Sep 17 00:00:00 2001 From: johnsonpham Date: Fri, 23 Oct 2015 17:01:12 +0700 Subject: [PATCH 01/44] Implement html, css for Funnel of Challenge phase on the Challenge details page --- .../modules/contest-detail/contestDetail.html | 128 +++++++++++++----- .../modules/translation/messages_en.json | 7 +- .../webapp/assets/sass/contest-detail.sass | 52 +++++++ 3 files changed, 151 insertions(+), 36 deletions(-) diff --git a/src/main/webapp/assets/modules/contest-detail/contestDetail.html b/src/main/webapp/assets/modules/contest-detail/contestDetail.html index a1aa8eb4f..ba21f0bb8 100644 --- a/src/main/webapp/assets/modules/contest-detail/contestDetail.html +++ b/src/main/webapp/assets/modules/contest-detail/contestDetail.html @@ -2,16 +2,15 @@

{{contestDetail.challengeName}} - - {{contestDetail.currentPhase | textTruncate: 'lowercase' | translate}} - - {{contestDetail.progress.translate | translate}} - + + + + + +

- -
@@ -247,36 +245,96 @@

-
-
-
- - +
+
+
+
+ {{'registration' | translate}}
-
-
- - - - - -
-
- - - - - -
+
+

+
+
+
+
+
+ {{'idea' | translate}} +
+
+

+

+
+
+
+
+
+ {{'uiux' | translate}} +
+
+

+

-
- +
+
+
+
+ {{'prototype' | translate}} +
+
+

+

+
+
+
+
+
+ {{'finalApp' | translate}} +
+
+

+

- +
+
+
+
+ {{'winner' | translate}} +
+
+

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/webapp/assets/modules/translation/messages_en.json b/src/main/webapp/assets/modules/translation/messages_en.json index d10b59a90..b55edcd75 100644 --- a/src/main/webapp/assets/modules/translation/messages_en.json +++ b/src/main/webapp/assets/modules/translation/messages_en.json @@ -814,5 +814,10 @@ "removeConfirmation": "Removing this criteria will impact all contestants' scores you gave already.
Are you sure you want to remove it?", "totalScoreIs": "Total score is", "emailSettingDescription": "Configure settings to personalize emails to tech talents", - "updateEvaluationCriteria": "Scoring criteria are updated." + "updateEvaluationCriteria": "Scoring criteria are updated.", + "registrantsNumber": "{{number}} registrant(s)", + "participantsNumber": "{{number}} participant(s)", + "submissionsNumber": "{{number}} submission(s)", + "selectedNumber": "{{number}} selected", + "winner": "Winner" } \ No newline at end of file diff --git a/src/main/webapp/assets/sass/contest-detail.sass b/src/main/webapp/assets/sass/contest-detail.sass index c5ee21056..c755bae3b 100644 --- a/src/main/webapp/assets/sass/contest-detail.sass +++ b/src/main/webapp/assets/sass/contest-detail.sass @@ -997,6 +997,58 @@ .popover.top > .arrow::after, .popover.top > .arrow border-top-color: #fff + .funnel-challenge-phase-block + width: 100% + clear: both + .challenge-phase-item + width: 16.66667% + float: left + padding: 0 5px 0 0 + .registrants-phase + width: 100% + clear: both + padding-top: 5px + p + margin: 0 + padding: 0 + font-size: 12px + text-align: right + strong + font-weight: 500 + .phase-name + width: 100% + clear: both + display: inline-block + border-radius: 4px + color: #fff + font-weight: 400 + padding: 4px 0 + text-align: center + .phase-name.registration + background-color: #1ea185 + .phase-name.idea + background-color: #9bba5c + .phase-name.uiux + background-color: #9F472B + .phase-name.prototype + background-color: #bd392f + .phase-name.final-app + background-color: #257abb + .phase-name.winner + background-color: #FFAA00 + .current-phase + text-align: center + width: 100% + clear: both + height: 40px + i + display: none + font-size: 35px + margin: auto + font-weight: 300 + .current-phase.active + i + display: inline-block .alert margin-top: 20px .evaluation-criteria From fbc04f9f88419194ff1557973fa1912d1a7d2e7b Mon Sep 17 00:00:00 2001 From: johnsonpham Date: Fri, 23 Oct 2015 18:00:24 +0700 Subject: [PATCH 02/44] Implement angularjs for Funnel Challenge Phase --- .../modules/contest-detail/contestDetail.html | 122 ++++++++++-------- .../contest-detail/contestDetailController.js | 47 +++++++ .../webapp/assets/sass/contest-detail.sass | 10 +- 3 files changed, 121 insertions(+), 58 deletions(-) diff --git a/src/main/webapp/assets/modules/contest-detail/contestDetail.html b/src/main/webapp/assets/modules/contest-detail/contestDetail.html index ba21f0bb8..bf3589908 100644 --- a/src/main/webapp/assets/modules/contest-detail/contestDetail.html +++ b/src/main/webapp/assets/modules/contest-detail/contestDetail.html @@ -52,7 +52,6 @@

{{contestDetail.challengeName}}

-

{{contestDetail.progress.translate | translate}} @@ -246,64 +245,77 @@

-
-
-
- {{'registration' | translate}} -
-
-

-
-
-
-
-
- {{'idea' | translate}} -
-
-

-

-
-
-
-
-
- {{'uiux' | translate}} -
-
-

-

-
-
-
-
-
- {{'prototype' | translate}} -
-
-

-

-
-
-
-
-
- {{'finalApp' | translate}} +
+
+
+
-

-

-
-
-
-
-
- {{'winner' | translate}} -
-
-

+

+

+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/webapp/assets/modules/contest-detail/contestDetailController.js b/src/main/webapp/assets/modules/contest-detail/contestDetailController.js index 0175fe99d..362f93731 100644 --- a/src/main/webapp/assets/modules/contest-detail/contestDetailController.js +++ b/src/main/webapp/assets/modules/contest-detail/contestDetailController.js @@ -1,6 +1,53 @@ techlooper.controller('contestDetailController', function ($scope, apiService, localStorageService, $location, $routeParams, jsonValue, $translate, utils, $filter, $timeout, resourcesService) { + $scope.phaseList =[ + { + "name": "registration", + "registration": 200, + "participant": null, + "submission": null + }, + { + "name": "idea", + "registration": null, + "participant": 185, + "submission": 160, + "selected": null + }, + { + "name": "uiux", + "registration": null, + "participant": 130, + "submission": 100, + "selected": null + }, + { + "name": "prototype", + "registration": null, + "participant": 50, + "submission": 30, + "selected": null + }, + { + "name": "finalApp", + "registration": null, + "participant": 0, + "submission": 0, + "selected": null + }, + { + "name": "winner", + "registration": null, + "participant": null, + "submission": null, + "selected": 0 + } + ]; + $scope.selectedPhase = 0; + $scope.reviewPhase= function(index) { + $scope.selectedPhase = index; + }; utils.sendNotification(jsonValue.notifications.loading); var parts = $routeParams.id.split("-"); var lastPart = parts.pop(); diff --git a/src/main/webapp/assets/sass/contest-detail.sass b/src/main/webapp/assets/sass/contest-detail.sass index c755bae3b..0ed2a57f0 100644 --- a/src/main/webapp/assets/sass/contest-detail.sass +++ b/src/main/webapp/assets/sass/contest-detail.sass @@ -1008,6 +1008,7 @@ width: 100% clear: both padding-top: 5px + cursor: pointer p margin: 0 padding: 0 @@ -1024,6 +1025,8 @@ font-weight: 400 padding: 4px 0 text-align: center + span + cursor: pointer .phase-name.registration background-color: #1ea185 .phase-name.idea @@ -1032,7 +1035,7 @@ background-color: #9F472B .phase-name.prototype background-color: #bd392f - .phase-name.final-app + .phase-name.finalApp background-color: #257abb .phase-name.winner background-color: #FFAA00 @@ -1040,12 +1043,13 @@ text-align: center width: 100% clear: both - height: 40px + height: 30px i display: none - font-size: 35px + font-size: 30px margin: auto font-weight: 300 + cursor: pointer .current-phase.active i display: inline-block From df47a656be5ef4e5810c6edb142c61d48fe7f2f4 Mon Sep 17 00:00:00 2001 From: johnsonpham Date: Mon, 26 Oct 2015 11:39:55 +0700 Subject: [PATCH 03/44] update email Challenge summary daily --- .../template/challengeDailySummary.en.ftl | 61 +- .../template/challengeDailySummary.vi.ftl | 778 +++++++++--------- 2 files changed, 423 insertions(+), 416 deletions(-) diff --git a/src/main/resources/template/challengeDailySummary.en.ftl b/src/main/resources/template/challengeDailySummary.en.ftl index 00ec33cbe..a94527000 100644 --- a/src/main/resources/template/challengeDailySummary.en.ftl +++ b/src/main/resources/template/challengeDailySummary.en.ftl @@ -207,17 +207,17 @@

<#list latestRegistrants as registrant> - - - + + + - - - + + + - <#if latestSubmissions?has_content> + <#if latestSubmissions?has_content> - +
- - - -
+ + + +
${registrant_index + 1}${registrant.registrantFirstName} ${registrant.registrantLastName}
${registrant_index + 1}${registrant.registrantFirstName} ${registrant.registrantLastName}
@@ -292,7 +292,7 @@
@@ -315,35 +315,38 @@ <#list latestSubmissions as latestSubmission> + + + + + + + - @@ -356,7 +359,7 @@
+ +
+ + + + + +
${latestSubmission_index + 1}${latestSubmission.registrantName}
+
- - - - - -
${latestSubmission_index + 1}${latestSubmission.registrantName}
- + -
+ - - -
- Review - Feedback - - Accept + + Review All
diff --git a/src/main/resources/template/challengeDailySummary.vi.ftl b/src/main/resources/template/challengeDailySummary.vi.ftl index 0556b68af..423121848 100644 --- a/src/main/resources/template/challengeDailySummary.vi.ftl +++ b/src/main/resources/template/challengeDailySummary.vi.ftl @@ -2,412 +2,416 @@ - - - - - - + @media (device-width: 320px) { + body { + max-width: 100% !important; + } + [class=hidden] { + display: none + } + [class=body-content] { + max-width: 100% !important; + width: 100% !important; + } + p[class=bottom-links] span { + display: block; + } + [class=cta-large] { + font-size: 24px !important; + } + [class=candidate] td { + font-size: 24px !important; + line-height: 30px !important; + } + [class=content-padding] { + padding: 20px !important; + } + [class=email] { + color: #00b9f2; + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + vertical-align: middle; + width: 240px; + } + [class=small-text] { + font-size: 13px !important; + white-space: nowrap !important + } + [class=logo] img { + width: 100px; + } + [class=fullWidth] { + width: 100% !important; + } + [class=btnFull] { + width: 100% !important; + padding: 10px 0 !important + } + .fullWidth { + width: 100% !important; + } + } + + - -
- - - + +
+ + + + +
+
+ + - +
-
- - + + + +
+ + + + + + + +
+ + + + + +
+
+ + + - + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+

Thử Thách Trực Tuyến

+
+

Xây Dựng Đội Ngũ Phát Triển Sản Phẩm Của Chính Bạn Thông Qua Các Cuộc Thi Trực Tuyến.

+
+ +
+

Xin chào,

+
+ +
+

Dưới đây là báo cáo hằng ngày cho thử thách ${challengeName} trong vòng 24 giờ qua

+
+ +
+ + + + + + + + + + + + + + <#if latestSubmissions?has_content> + + - - + + + + + + + + + + + + +
+ - - + -
Thử thách của bạn mở rộng như thế nào trong 24 giờ qua
- - +
+ - - - + -
- - - - - - + +
- - - - + + <#if latestRegistrants?has_content> + + + + + + + +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <#if latestSubmissions?has_content> - - - - - - - - - - - - - + + + +
-

Thử Thách Trực Tuyến

-
-

Xây Dựng Đội Ngũ Phát Triển Sản Phẩm Của Chính Bạn Thông Qua Các Cuộc Thi Trực Tuyến.

-
- -
-

Xin chào,

-
- -
-

Dưới đây là báo cáo hằng ngày cho thử thách ${challengeName} trong vòng 24 giờ qua

-
- -
- - - - - <#if latestRegistrants?has_content> - - - - - - - -
- - - - -
Thử thách của bạn mở rộng như thế nào trong 24 giờ qua
- - - - - - - -
- -
- Bạn nhận được thêm ${numberOfRegistrants} đăng ký mới -
- <#if latestRegistrants?has_content> - - <#list latestRegistrants as registrant> - - - - - - - - - - - - - -
- - - -
${registrant_index + 1}${registrant.registrantFirstName} ${registrant.registrantLastName}
- - - -
- -
- - - - -
- Gửi Email Cho Tất Cả -
-
- -
-
- -
- - - - -
- - - - -
Đây có phải là thời điểm để quảng bá cho thử thách của bạn?
- - - - - - - - - - -
- -
Nếu bạn muốn nhận thêm nhiều lượt đăng ký, trả lời email này để chúng tôi có thể hỗ trợ bạn.
- -
-
-
- -
- - - - - - - - -
- - - - -
Khám phá số lượng bài nộp mới vào thử thách
- - - - - - - - <#list latestSubmissions as latestSubmission> - - - - - - - -
- -
- Bạn nhận được thêm ${numberOfSubmissions} bài nộp mới : -
- -
- - - - - -
${latestSubmission_index + 1}${latestSubmission.registrantName}
- - - - - - -
- Xem Trước - Phản Hồi - - Đi Tiếp -
-
-
- -
-
- -
- - - - -
- -
-
- - - - - - - -
-

KẾT NỐI VỚI CHÚNG TÔI

-
- - LinkedIn - -
- - - - - -
-
+ Bạn nhận được thêm ${numberOfRegistrants} đăng ký mới +
+ <#if latestRegistrants?has_content> + + <#list latestRegistrants as registrant> + + + + + + + + + + + + + +
+ + + +
${registrant_index + 1}${registrant.registrantFirstName} ${registrant.registrantLastName}
+ + + +
+ +
+ + + + +
+ Gửi Email Cho Tất Cả +
+
+ +
+
+ +
+ + + + +
+ + + + +
Đây có phải là thời điểm để quảng bá cho thử thách của bạn?
+ + + + + + + + + + +
+ +
Nếu bạn muốn nhận thêm nhiều lượt đăng ký, trả lời email này để chúng tôi có thể hỗ trợ bạn.
+ +
+
+
+ +
+ + + + + + + +
+ + + + +
Khám phá số lượng bài nộp mới vào thử thách
+ + + + + + + + <#list latestSubmissions as latestSubmission> + + + + + + + + + + + + - + + +
+ +
+ Bạn nhận được thêm ${numberOfSubmissions} bài nộp mới : +
+ +
+ + + + + +
${latestSubmission_index + 1}${latestSubmission.registrantName}
+
+ +
+ + + +
+ Xem Tất Cả +
-
+
+ +
-
+ +
+ + + + +
+ +
+
+ + + + + + + +
+

KẾT NỐI VỚI CHÚNG TÔI

+
+ + LinkedIn + +
+ + + + + +
+
+
-
+
From ca7ad01887c192aa2f047cc4c1084101bff2b8a8 Mon Sep 17 00:00:00 2001 From: khoa-nd Date: Mon, 26 Oct 2015 13:21:18 +0700 Subject: [PATCH 04/44] Add current phase field when user submits the form --- .../ChallengeSubmissionController.java | 31 ++- .../entity/ChallengeSubmissionEntity.java | 220 ++++++++++-------- .../techlooper/service/ChallengeService.java | 91 ++++---- .../service/impl/ChallengeServiceImpl.java | 18 +- .../impl/ChallengeSubmissionServiceImpl.java | 64 +++-- .../assets/modules/common/apiService.js | 60 +++-- .../common/challenge/submissionChallenge.html | 4 + .../common/challenge/submissionChallenge.js | 7 + 8 files changed, 278 insertions(+), 217 deletions(-) diff --git a/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java b/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java index a1695efe3..001deb481 100644 --- a/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java +++ b/src/main/java/com/techlooper/controller/ChallengeSubmissionController.java @@ -1,12 +1,12 @@ package com.techlooper.controller; +import com.techlooper.entity.ChallengeRegistrantEntity; import com.techlooper.entity.ChallengeSubmissionEntity; +import com.techlooper.model.ChallengePhaseEnum; import com.techlooper.model.ChallengeSubmissionDto; +import com.techlooper.service.ChallengeService; import com.techlooper.service.ChallengeSubmissionService; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -16,12 +16,23 @@ @RestController public class ChallengeSubmissionController { - @Resource - private ChallengeSubmissionService challengeSubmissionService; + @Resource + private ChallengeSubmissionService challengeSubmissionService; - @RequestMapping(value = "user/challengeSubmission", method = RequestMethod.POST) - public ChallengeSubmissionEntity submitMyResult(@RequestBody ChallengeSubmissionDto challengeSubmissionDto) { - return challengeSubmissionService.submitMyResult(challengeSubmissionDto); - } + @Resource + private ChallengeService challengeService; + + @RequestMapping(value = "user/challengeSubmission", method = RequestMethod.POST) + public ChallengeSubmissionEntity submitMyResult(@RequestBody ChallengeSubmissionDto challengeSubmissionDto) { + return challengeSubmissionService.submitMyResult(challengeSubmissionDto); + } + + @RequestMapping(value = "user/challengeSubmissionPhase/{registrantEmail}/{challengeId}", method = RequestMethod.GET) + public ChallengePhaseEnum challengeSubmissionPhase(@PathVariable String registrantEmail, @PathVariable Long challengeId) { + ChallengeRegistrantEntity registrantEntity = + challengeService.findRegistrantByChallengeIdAndEmail(challengeId, registrantEmail); + return (registrantEntity != null && registrantEntity.getActivePhase() != null) ? + registrantEntity.getActivePhase() : ChallengePhaseEnum.REGISTRATION; + } } diff --git a/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java b/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java index 1ec4de309..fde23ee4c 100644 --- a/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java +++ b/src/main/java/com/techlooper/entity/ChallengeSubmissionEntity.java @@ -1,10 +1,8 @@ package com.techlooper.entity; +import com.techlooper.model.ChallengePhaseEnum; import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.DateFormat; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.*; import static org.springframework.data.elasticsearch.annotations.FieldType.Long; import static org.springframework.data.elasticsearch.annotations.FieldType.String; @@ -12,139 +10,155 @@ @Document(indexName = "techlooper", type = "challengeSubmission") public class ChallengeSubmissionEntity { - @Id - private Long challengeSubmissionId; + @Id + private Long challengeSubmissionId; - @Field(type = Long) - private Long registrantId; + @Field(type = Long) + private Long registrantId; - @Field(type = String) - private String registrantName; + @Field(type = String) + private String registrantName; - @Field(type = Long) - private Long challengeId; + @Field(type = Long) + private Long challengeId; - @Field(type = String) - private String submissionURL; + @Field(type = String) + private String submissionURL; - @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy") - private String submissionDateTime; + @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd/MM/yyyy") + private String submissionDateTime; - @Field(type = String) - private String submissionDescription; + @Field(type = String) + private String submissionDescription; - public java.lang.Long getRegistrantId() { - return registrantId; - } + @Field(type = String, index = FieldIndex.not_analyzed) + private ChallengePhaseEnum submissionPhase; - public void setRegistrantId(java.lang.Long registrantId) { - this.registrantId = registrantId; - } - - public java.lang.Long getChallengeSubmissionId() { - return challengeSubmissionId; - } - - public void setChallengeSubmissionId(java.lang.Long challengeSubmissionId) { - this.challengeSubmissionId = challengeSubmissionId; - } - - public java.lang.String getRegistrantName() { - return registrantName; - } - - public void setRegistrantName(java.lang.String registrantName) { - this.registrantName = registrantName; - } - - public java.lang.Long getChallengeId() { - return challengeId; - } - - public void setChallengeId(java.lang.Long challengeId) { - this.challengeId = challengeId; - } - - public java.lang.String getSubmissionURL() { - return submissionURL; - } - - public void setSubmissionURL(java.lang.String submissionURL) { - this.submissionURL = submissionURL; - } - - public java.lang.String getSubmissionDateTime() { - return submissionDateTime; - } + public java.lang.Long getRegistrantId() { + return registrantId; + } - public void setSubmissionDateTime(java.lang.String submissionDateTime) { - this.submissionDateTime = submissionDateTime; - } + public void setRegistrantId(java.lang.Long registrantId) { + this.registrantId = registrantId; + } - public java.lang.String getSubmissionDescription() { - return submissionDescription; - } + public java.lang.Long getChallengeSubmissionId() { + return challengeSubmissionId; + } - public void setSubmissionDescription(java.lang.String submissionDescription) { - this.submissionDescription = submissionDescription; - } + public void setChallengeSubmissionId(java.lang.Long challengeSubmissionId) { + this.challengeSubmissionId = challengeSubmissionId; + } - public static class ChallengeSubmissionEntityBuilder { - private ChallengeSubmissionEntity challengeSubmissionEntity; + public java.lang.String getRegistrantName() { + return registrantName; + } - private ChallengeSubmissionEntityBuilder() { - challengeSubmissionEntity = new ChallengeSubmissionEntity(); + public void setRegistrantName(java.lang.String registrantName) { + this.registrantName = registrantName; } - private ChallengeSubmissionEntityBuilder(ChallengeSubmissionEntity challengeSubmissionEntity) { - this.challengeSubmissionEntity = challengeSubmissionEntity; + public java.lang.Long getChallengeId() { + return challengeId; } - public ChallengeSubmissionEntityBuilder withChallengeSubmissionId(Long challengeSubmissionId) { - challengeSubmissionEntity.challengeSubmissionId = challengeSubmissionId; - return this; + public void setChallengeId(java.lang.Long challengeId) { + this.challengeId = challengeId; } - public ChallengeSubmissionEntityBuilder withRegistrantId(Long registrantId) { - challengeSubmissionEntity.registrantId = registrantId; - return this; + public java.lang.String getSubmissionURL() { + return submissionURL; } - public ChallengeSubmissionEntityBuilder withRegistrantName(String registrantName) { - challengeSubmissionEntity.registrantName = registrantName; - return this; + public void setSubmissionURL(java.lang.String submissionURL) { + this.submissionURL = submissionURL; } - public ChallengeSubmissionEntityBuilder withChallengeId(Long challengeId) { - challengeSubmissionEntity.challengeId = challengeId; - return this; + public java.lang.String getSubmissionDateTime() { + return submissionDateTime; } - public ChallengeSubmissionEntityBuilder withSubmissionURL(String submissionURL) { - challengeSubmissionEntity.submissionURL = submissionURL; - return this; + public void setSubmissionDateTime(java.lang.String submissionDateTime) { + this.submissionDateTime = submissionDateTime; } - public ChallengeSubmissionEntityBuilder withSubmissionDateTime(String submissionDateTime) { - challengeSubmissionEntity.submissionDateTime = submissionDateTime; - return this; + public java.lang.String getSubmissionDescription() { + return submissionDescription; } - public ChallengeSubmissionEntityBuilder withSubmissionDescription(String submissionDescription) { - challengeSubmissionEntity.submissionDescription = submissionDescription; - return this; + public void setSubmissionDescription(java.lang.String submissionDescription) { + this.submissionDescription = submissionDescription; } - public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity() { - return new ChallengeSubmissionEntityBuilder(); + public ChallengePhaseEnum getSubmissionPhase() { + return submissionPhase; } - public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity(ChallengeSubmissionEntity entity) { - return new ChallengeSubmissionEntityBuilder(entity); + public void setSubmissionPhase(ChallengePhaseEnum submissionPhase) { + this.submissionPhase = submissionPhase; } - public ChallengeSubmissionEntity build() { - return challengeSubmissionEntity; + public static class ChallengeSubmissionEntityBuilder { + private ChallengeSubmissionEntity challengeSubmissionEntity; + + private ChallengeSubmissionEntityBuilder() { + challengeSubmissionEntity = new ChallengeSubmissionEntity(); + } + + private ChallengeSubmissionEntityBuilder(ChallengeSubmissionEntity challengeSubmissionEntity) { + this.challengeSubmissionEntity = challengeSubmissionEntity; + } + + public ChallengeSubmissionEntityBuilder withChallengeSubmissionId(Long challengeSubmissionId) { + challengeSubmissionEntity.challengeSubmissionId = challengeSubmissionId; + return this; + } + + public ChallengeSubmissionEntityBuilder withRegistrantId(Long registrantId) { + challengeSubmissionEntity.registrantId = registrantId; + return this; + } + + public ChallengeSubmissionEntityBuilder withRegistrantName(String registrantName) { + challengeSubmissionEntity.registrantName = registrantName; + return this; + } + + public ChallengeSubmissionEntityBuilder withChallengeId(Long challengeId) { + challengeSubmissionEntity.challengeId = challengeId; + return this; + } + + public ChallengeSubmissionEntityBuilder withSubmissionURL(String submissionURL) { + challengeSubmissionEntity.submissionURL = submissionURL; + return this; + } + + public ChallengeSubmissionEntityBuilder withSubmissionDateTime(String submissionDateTime) { + challengeSubmissionEntity.submissionDateTime = submissionDateTime; + return this; + } + + public ChallengeSubmissionEntityBuilder withSubmissionDescription(String submissionDescription) { + challengeSubmissionEntity.submissionDescription = submissionDescription; + return this; + } + + public ChallengeSubmissionEntityBuilder withSubmissionPhase(ChallengePhaseEnum submissionPhase) { + challengeSubmissionEntity.submissionPhase = submissionPhase; + return this; + } + + public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity() { + return new ChallengeSubmissionEntityBuilder(); + } + + public static ChallengeSubmissionEntityBuilder challengeSubmissionEntity(ChallengeSubmissionEntity entity) { + return new ChallengeSubmissionEntityBuilder(entity); + } + + public ChallengeSubmissionEntity build() { + return challengeSubmissionEntity; + } } - } } diff --git a/src/main/java/com/techlooper/service/ChallengeService.java b/src/main/java/com/techlooper/service/ChallengeService.java index 8e4d5022a..c04cbb9bb 100644 --- a/src/main/java/com/techlooper/service/ChallengeService.java +++ b/src/main/java/com/techlooper/service/ChallengeService.java @@ -20,89 +20,90 @@ */ public interface ChallengeService { - ChallengeEntity savePostChallenge(ChallengeDto challengeDto) throws Exception; + ChallengeEntity savePostChallenge(ChallengeDto challengeDto) throws Exception; - void sendPostChallengeEmailToEmployer(ChallengeEntity challengeEntity) - throws MessagingException, IOException, TemplateException; + void sendPostChallengeEmailToEmployer(ChallengeEntity challengeEntity) + throws MessagingException, IOException, TemplateException; - void sendPostChallengeEmailToTechloopies(ChallengeEntity challengeEntity, Boolean isNewChallenge) - throws MessagingException, IOException, TemplateException; + void sendPostChallengeEmailToTechloopies(ChallengeEntity challengeEntity, Boolean isNewChallenge) + throws MessagingException, IOException, TemplateException; - void sendEmailNotifyRegistrantAboutChallengeTimeline(ChallengeEntity challengeEntity, - ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) throws Exception; + void sendEmailNotifyRegistrantAboutChallengeTimeline(ChallengeEntity challengeEntity, + ChallengeRegistrantEntity challengeRegistrantEntity, ChallengePhaseEnum challengePhase) throws Exception; - ChallengeDetailDto getChallengeDetail(Long challengeId, String loginEmail); + ChallengeDetailDto getChallengeDetail(Long challengeId, String loginEmail); - Long getNumberOfRegistrants(Long challengeId); + Long getNumberOfRegistrants(Long challengeId); - void sendApplicationEmailToContestant(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) - throws MessagingException, IOException, TemplateException; + void sendApplicationEmailToContestant(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) + throws MessagingException, IOException, TemplateException; - void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) - throws MessagingException, IOException, TemplateException; + void sendApplicationEmailToEmployer(ChallengeEntity challengeEntity, ChallengeRegistrantEntity challengeRegistrantEntity) + throws MessagingException, IOException, TemplateException; - ChallengeRegistrantEntity joinChallengeEntity(ChallengeRegistrantDto challengeRegistrantDto); + ChallengeRegistrantEntity joinChallengeEntity(ChallengeRegistrantDto challengeRegistrantDto); - long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto); + long joinChallenge(ChallengeRegistrantDto challengeRegistrantDto); - List listChallenges(); + List listChallenges(); - List listChallenges(String ownerEmail); + List listChallenges(String ownerEmail); - List listChallengesByPhase(ChallengePhaseEnum challengePhase); + List listChallengesByPhase(ChallengePhaseEnum challengePhase); - Long getTotalNumberOfChallenges(); + Long getTotalNumberOfChallenges(); - Double getTotalAmountOfPrizeValues(); + Double getTotalAmountOfPrizeValues(); - Long getTotalNumberOfRegistrants(); + Long getTotalNumberOfRegistrants(); - ChallengeDetailDto getTheLatestChallenge(); + ChallengeDetailDto getTheLatestChallenge(); - Collection findByOwnerAndCondition(String owner, Predicate condition); + Collection findByOwnerAndCondition(String owner, Predicate condition); - Collection findInProgressChallenges(String owner); + Collection findInProgressChallenges(String owner); // Collection findRegistrantsByChallengeId(Long challengeId); - Long countRegistrantsByChallengeId(Long challengeId); + Long countRegistrantsByChallengeId(Long challengeId); - boolean delete(Long id, String ownerEmail); + boolean delete(Long id, String ownerEmail); - ChallengeDto findChallengeById(Long id, String ownerEmail); + ChallengeDto findChallengeById(Long id, String ownerEmail); - Set findRegistrantsByOwner(RegistrantFilterCondition condition) throws ParseException; + Set findRegistrantsByOwner(RegistrantFilterCondition condition) throws ParseException; - ChallengeRegistrantDto saveRegistrant(String ownerEmail, ChallengeRegistrantDto challengeRegistrantDto); + ChallengeRegistrantDto saveRegistrant(String ownerEmail, ChallengeRegistrantDto challengeRegistrantDto); - List findChallengeRegistrantWithinPeriod( - Long challengeId, Long currentDateTime, TimePeriodEnum period); + List findChallengeRegistrantWithinPeriod( + Long challengeId, Long currentDateTime, TimePeriodEnum period); - List filterChallengeRegistrantByDate(RegistrantFilterCondition condition) throws ParseException; + List filterChallengeRegistrantByDate(RegistrantFilterCondition condition) throws ParseException; - List findChallengeSubmissionWithinPeriod( - Long challengeId, Long currentDateTime, TimePeriodEnum period); + List findChallengeSubmissionWithinPeriod( + Long challengeId, Long currentDateTime, TimePeriodEnum period); - void sendDailySummaryEmailToChallengeOwner(ChallengeEntity challengeEntity) throws Exception; + void sendDailySummaryEmailToChallengeOwner(ChallengeEntity challengeEntity) throws Exception; - boolean isOwnerOfChallenge(String ownerEmail, Long challengeId); + boolean isOwnerOfChallenge(String ownerEmail, Long challengeId); - ChallengeEntity findChallengeIdAndOwnerEmail(Long challengeId, String ownerEmail); + ChallengeEntity findChallengeIdAndOwnerEmail(Long challengeId, String ownerEmail); - boolean sendEmailToDailyChallengeRegistrants(String challengeOwner, Long challengeId, Long now, EmailContent emailContent); + boolean sendEmailToDailyChallengeRegistrants(String challengeOwner, Long challengeId, Long now, EmailContent emailContent); - boolean sendEmailToRegistrant(String challengeOwner, Long challengeId, Long registrantId, EmailContent emailContent); + boolean sendEmailToRegistrant(String challengeOwner, Long challengeId, Long registrantId, EmailContent emailContent); - List findChallengeSubmissionByRegistrant(Long challengeId, Long registrantId); + List findChallengeSubmissionByRegistrant(Long challengeId, Long registrantId); - void updateSendEmailToContestantResultCode(ChallengeRegistrantEntity challengeRegistrantEntity, EmailSentResultEnum code); + void updateSendEmailToContestantResultCode(ChallengeRegistrantEntity challengeRegistrantEntity, EmailSentResultEnum code); - void updateSendEmailToChallengeOwnerResultCode(ChallengeEntity challengeEntity, EmailSentResultEnum code); + void updateSendEmailToChallengeOwnerResultCode(ChallengeEntity challengeEntity, EmailSentResultEnum code); - Set findRegistrantByChallengeSubmissionDate(Long challengeId, String fromDate, String toDate); + Set findRegistrantByChallengeSubmissionDate(Long challengeId, String fromDate, String toDate); - ChallengeRegistrantDto acceptRegistrant(String ownerEmail, Long registrantId); + ChallengeRegistrantDto acceptRegistrant(String ownerEmail, Long registrantId); - void calculateChallengePhases(ChallengeDetailDto challengeDetailDto); + void calculateChallengePhases(ChallengeDetailDto challengeDetailDto); + ChallengeRegistrantEntity findRegistrantByChallengeIdAndEmail(Long challengeId, String email); } diff --git a/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java b/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java index 648fbef10..0fb8fb80b 100644 --- a/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java +++ b/src/main/java/com/techlooper/service/impl/ChallengeServiceImpl.java @@ -468,14 +468,22 @@ private List sortChallengesByDescendingStartDate(List 0); + List registrantEntities = DataUtils.getAllEntities(challengeRegistrantRepository, searchQueryBuilder); + if (!registrantEntities.isEmpty()) { + return registrantEntities.get(0); + } + return null; + } + + public boolean checkIfChallengeRegistrantExist(Long challengeId, String email) { + return findRegistrantByChallengeIdAndEmail(challengeId, email) != null; } @Override diff --git a/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java b/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java index ba8df4002..abf149cda 100644 --- a/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java +++ b/src/main/java/com/techlooper/service/impl/ChallengeSubmissionServiceImpl.java @@ -4,22 +4,17 @@ import com.techlooper.entity.ChallengeRegistrantEntity; import com.techlooper.entity.ChallengeSubmissionEntity; import com.techlooper.entity.ChallengeSubmissionEntity.ChallengeSubmissionEntityBuilder; +import com.techlooper.model.ChallengePhaseEnum; import com.techlooper.model.ChallengeSubmissionDto; -import com.techlooper.repository.elasticsearch.ChallengeRegistrantRepository; import com.techlooper.repository.elasticsearch.ChallengeSubmissionRepository; import com.techlooper.service.ChallengeService; import com.techlooper.service.ChallengeSubmissionService; import com.techlooper.util.DateTimeUtils; import org.dozer.Mapper; import org.elasticsearch.common.joda.time.DateTime; -import org.elasticsearch.index.query.MatchQueryBuilder; -import org.elasticsearch.index.query.TermQueryBuilder; import org.springframework.stereotype.Service; import javax.annotation.Resource; -import java.util.Iterator; - -import static org.elasticsearch.index.query.QueryBuilders.*; /** * Created by phuonghqh on 10/9/15. @@ -27,34 +22,31 @@ @Service public class ChallengeSubmissionServiceImpl implements ChallengeSubmissionService { - @Resource - private ChallengeRegistrantRepository challengeRegistrantRepository; - - @Resource - private ChallengeService challengeService; - - @Resource - private Mapper dozerMapper; - - @Resource - private ChallengeSubmissionRepository challengeSubmissionRepository; - - public ChallengeSubmissionEntity submitMyResult(ChallengeSubmissionDto challengeSubmissionDto) { - MatchQueryBuilder registrantEmailQuery = matchQuery("registrantEmail", challengeSubmissionDto.getRegistrantEmail()).minimumShouldMatch("100%"); - TermQueryBuilder challengeQuery = termQuery("challengeId", challengeSubmissionDto.getChallengeId()); - Iterator registrantIterator = challengeRegistrantRepository.search( - boolQuery().must(registrantEmailQuery).must(challengeQuery)).iterator(); - - ChallengeRegistrantEntity registrant = registrantIterator.hasNext() ? registrantIterator.next() : - challengeService.joinChallengeEntity(dozerMapper.map(challengeSubmissionDto, ChallengeRegistrantDto.class)); - - ChallengeSubmissionEntity challengeSubmissionEntity = dozerMapper.map(challengeSubmissionDto, ChallengeSubmissionEntity.class); - ChallengeSubmissionEntityBuilder.challengeSubmissionEntity(challengeSubmissionEntity) - .withChallengeSubmissionId(DateTime.now().getMillis()) - .withRegistrantId(registrant.getRegistrantId()) - .withRegistrantName(String.format("%s %s", registrant.getRegistrantFirstName(), registrant.getRegistrantLastName())) - .withSubmissionDateTime(DateTimeUtils.currentDate()); - - return challengeSubmissionRepository.save(challengeSubmissionEntity); - } + @Resource + private ChallengeService challengeService; + + @Resource + private Mapper dozerMapper; + + @Resource + private ChallengeSubmissionRepository challengeSubmissionRepository; + + public ChallengeSubmissionEntity submitMyResult(ChallengeSubmissionDto challengeSubmissionDto) { + ChallengeRegistrantEntity registrant = challengeService.findRegistrantByChallengeIdAndEmail( + challengeSubmissionDto.getChallengeId(), challengeSubmissionDto.getRegistrantEmail()); + if (registrant == null) { + registrant = challengeService.joinChallengeEntity(dozerMapper.map(challengeSubmissionDto, ChallengeRegistrantDto.class)); + } + ChallengePhaseEnum activePhase = registrant.getActivePhase() == null ? ChallengePhaseEnum.REGISTRATION : registrant.getActivePhase(); + + ChallengeSubmissionEntity challengeSubmissionEntity = dozerMapper.map(challengeSubmissionDto, ChallengeSubmissionEntity.class); + ChallengeSubmissionEntityBuilder.challengeSubmissionEntity(challengeSubmissionEntity) + .withChallengeSubmissionId(DateTime.now().getMillis()) + .withRegistrantId(registrant.getRegistrantId()) + .withRegistrantName(String.format("%s %s", registrant.getRegistrantFirstName(), registrant.getRegistrantLastName())) + .withSubmissionDateTime(DateTimeUtils.currentDate()) + .withSubmissionPhase(activePhase); + + return challengeSubmissionRepository.save(challengeSubmissionEntity); + } } diff --git a/src/main/webapp/assets/modules/common/apiService.js b/src/main/webapp/assets/modules/common/apiService.js index 6d5ee90a8..dcef95b0d 100644 --- a/src/main/webapp/assets/modules/common/apiService.js +++ b/src/main/webapp/assets/modules/common/apiService.js @@ -30,12 +30,16 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht //}, getSocialLoginUrl: function (provider) { - return $http.get("social/" + provider + "/loginUrl", {transformResponse: function (d, h) {return d;}}); + return $http.get("social/" + provider + "/loginUrl", { + transformResponse: function (d, h) { + return d; + } + }); }, getContestDetail: function (id) { return $http.get("challenge/" + id) - .success(function(data) { + .success(function (data) { $filter("challengeDetail")(data); }); }, @@ -49,16 +53,20 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht registrantEmail: registrantEmail, lang: lang }, - {transformResponse: function (d, h) {return d;}}); + { + transformResponse: function (d, h) { + return d; + } + }); }, searchContests: function () { return $http.get("challenge/list"); - //.success(function (contests) { - // $.each(contests, function (i, contest) { - // $filter("progress")(contest, "challenge"); - // }); - //}); + //.success(function (contests) { + // $.each(contests, function (i, contest) { + // $filter("progress")(contest, "challenge"); + // }); + //}); }, getSuggestSkills: function (text) { @@ -97,7 +105,11 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht projectId: projectId, registrantFirstName: firstName, registrantLastName: lastName, registrantEmail: email, registrantPhoneNumber: phoneNumber, resumeLink: resumeLink, lang: lang }, - {transformResponse: function (d, h) {return d;}}); + { + transformResponse: function (d, h) { + return d; + } + }); }, /** @@ -202,8 +214,8 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht * */ getChallengeRegistrants: function (registrantFilterCondition) { return $http.post("challenges/" + registrantFilterCondition.challengeId + "/registrants", registrantFilterCondition) - .success(function(registrants) { - $.each(registrants, function(i, registrant) { + .success(function (registrants) { + $.each(registrants, function (i, registrant) { $filter("challengeRegistrant")(registrant); }); }); @@ -235,7 +247,11 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht * @see com.techlooper.controller.ChallengeController.getChallengeRegistrant * */ getChallengeRegistrantFullName: function (challengeRegistrantId) { - return $http.get("challengeRegistrant/fullName/" + challengeRegistrantId, {transformResponse: function (d, h) {return d;}}); + return $http.get("challengeRegistrant/fullName/" + challengeRegistrantId, { + transformResponse: function (d, h) { + return d; + } + }); }, /** @@ -264,7 +280,11 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht * @see com.techlooper.controller.SharingController.getUrlResponseCode * */ getUrlResponseCode: function (url) { - return $http.post("resource/getUrlResponseCode", {url: url}, {transformResponse: function (d, h) {return d;}}); + return $http.post("resource/getUrlResponseCode", {url: url}, { + transformResponse: function (d, h) { + return d; + } + }); }, saveEmailSetting: function (emailSetting) { @@ -275,33 +295,37 @@ techlooper.factory("apiService", function ($rootScope, $location, jsonValue, $ht return $http.get("user/employer/emailSetting"); }, - getAvailableEmailTemplates : function () { + getAvailableEmailTemplates: function () { return $http.get("emailTemplates"); }, - getTemplateById : function (templateId) { + getTemplateById: function (templateId) { return $http.get("emailTemplates/" + templateId); }, /** * @see com.techlooper.controller.ChallengeCriteriaController.saveChallengeCriteria * */ - saveChallengeCriteria: function(criteria) { + saveChallengeCriteria: function (criteria) { return $http.post("challenge/criteria", criteria); }, /** * @see com.techlooper.controller.ChallengeCriteriaController.saveChallengeRegistrantCriteria * */ - saveChallengeRegistrantCriteria: function(criteria) { + saveChallengeRegistrantCriteria: function (criteria) { return $http.post("challengeRegistrant/criteria", criteria); }, /** * @see com.techlooper.controller.ChallengeCriteriaController.findByChallengeRegistrantId * */ - findRegistrantCriteriaByRegistrantId: function(registrantId) { + findRegistrantCriteriaByRegistrantId: function (registrantId) { return $http.get("challengeRegistrant/" + registrantId + "/criteria"); + }, + + findRegistrantActivePhase: function (challengeId, registrantEmail) { + return $http.get("user/challengeSubmissionPhase/" + registrantEmail + "/" + challengeId); } }; diff --git a/src/main/webapp/assets/modules/common/challenge/submissionChallenge.html b/src/main/webapp/assets/modules/common/challenge/submissionChallenge.html index b08cc2c72..9c893e0d5 100644 --- a/src/main/webapp/assets/modules/common/challenge/submissionChallenge.html +++ b/src/main/webapp/assets/modules/common/challenge/submissionChallenge.html @@ -8,6 +8,10 @@ {{submission.registrantEmail}}
+
+ + {{submission.submissionPhase | textTruncate: 'lowercase' | translate}} +