diff --git a/app/assets/css/cfp.less b/app/assets/css/cfp.less
index e3fa8f64..2ab79eb3 100644
--- a/app/assets/css/cfp.less
+++ b/app/assets/css/cfp.less
@@ -922,6 +922,14 @@ div.chat_list {
background-color: #f6f6f6;
}
+div.chat_new_comments_indicator {
+ text-align: center;
+ background-color: #f6f6f6;
+ border-top: 1px solid red;
+ color: red;
+ border-bottom: 1px solid red;
+}
+
div.chat_people {
overflow: hidden;
clear: both;
diff --git a/app/controllers/CFPAdmin.scala b/app/controllers/CFPAdmin.scala
index 13e87f4f..7fd3957f 100644
--- a/app/controllers/CFPAdmin.scala
+++ b/app/controllers/CFPAdmin.scala
@@ -91,7 +91,8 @@ object CFPAdmin extends SecureCFPController {
val proposalsByAuths = allProposalByProposal(proposal)
val userWatchPref = ProposalUserWatchPreference.proposalUserWatchPreference(proposal.id, userId)
val maybeDelayedReviewReason = Review.proposalDelayedReviewReason(userId, proposal.id)
- views.html.CFPAdmin.showProposal(proposal, proposalsByAuths, speakerDiscussion, internalDiscussion, msgToSpeakerForm, msgInternalForm, voteForm, maybeMyVote, maybeMyPreviousVote, userId, userWatchPref, maybeDelayedReviewReason)
+ val proposalLastVisit = Proposal.userProposalLastVisits(userId).get(proposal.id)
+ views.html.CFPAdmin.showProposal(proposal, proposalsByAuths, speakerDiscussion, internalDiscussion, msgToSpeakerForm, msgInternalForm, voteForm, maybeMyVote, maybeMyPreviousVote, userId, userWatchPref, maybeDelayedReviewReason, proposalLastVisit)
}
def openForReview(proposalId: String) = SecuredAction(IsMemberOf("cfp")) {
diff --git a/app/views/CFPAdmin/showProposal.scala.html b/app/views/CFPAdmin/showProposal.scala.html
index 075e8cd3..e4400210 100644
--- a/app/views/CFPAdmin/showProposal.scala.html
+++ b/app/views/CFPAdmin/showProposal.scala.html
@@ -1,4 +1,4 @@
-@(proposal: Proposal, proposalsByAuths: Map[String, Map[String, Proposal]], speakerComments: List[Comment], internalComments: List[Comment], msgToSpeakerForm: Form[String], msgInternalForm: Form[String], voteForm: Form[Int], maybeMyVote: Option[Review], maybeMyPreviousVote: Option[Review], currentUser: String, userWatchPref: ProposalUserWatchPreference, maybeVoteDelayedReason: Option[String])(implicit flash: Flash, lang: Lang, req: RequestHeader)
+@(proposal: Proposal, proposalsByAuths: Map[String, Map[String, Proposal]], speakerComments: List[Comment], internalComments: List[Comment], msgToSpeakerForm: Form[String], msgInternalForm: Form[String], voteForm: Form[Int], maybeMyVote: Option[Review], maybeMyPreviousVote: Option[Review], currentUser: String, userWatchPref: ProposalUserWatchPreference, maybeVoteDelayedReason: Option[String], proposalLastVisit: Option[org.joda.time.DateTime])(implicit flash: Flash, lang: Lang, req: RequestHeader)
@main("[CFP] " + proposal.id + "/" + proposal.title) {
@@ -258,7 +258,7 @@
@Messages("admin.sp.commi
}
- @tags.renderComments(speakerComments)
+ @tags.renderComments(speakerComments, proposalLastVisit)
@@ -306,7 +306,7 @@ @Messages("admin.sp.internal")
}
- @tags.renderComments(internalComments)
+ @tags.renderComments(internalComments, proposalLastVisit)
diff --git a/app/views/CallForPaper/showCommentForProposal.scala.html b/app/views/CallForPaper/showCommentForProposal.scala.html
index ef0c93cf..7034564e 100644
--- a/app/views/CallForPaper/showCommentForProposal.scala.html
+++ b/app/views/CallForPaper/showCommentForProposal.scala.html
@@ -52,7 +52,7 @@ @Messages("comment.proposal")
- @tags.renderComments(comments)
+ @tags.renderComments(comments, None)
diff --git a/app/views/tags/renderComments.scala.html b/app/views/tags/renderComments.scala.html
index eaceab7c..0f369653 100644
--- a/app/views/tags/renderComments.scala.html
+++ b/app/views/tags/renderComments.scala.html
@@ -1,35 +1,42 @@
-@(comments: List[models.Comment])
- @comments.map { c =>
- @models.Speaker.findByUUID(c.uuidAuthor).map { speaker =>
- @models.Webuser.findByUUID(c.uuidAuthor).map { webuser =>
-
-
-
- @if(speaker.avatarUrl.isEmpty) {
-
?s=35)
- } else {
-

- }
-
-
-
- @webuser.cleanName
- @Messages("tags.renderComment.postedBy",
- library.FormatDate.jodaDateFormat(c.eventDate.get, play.api.i18n.Lang.defaultLang),
- library.FormatDate.jodaTimeFormat(c.eventDate.get, play.api.i18n.Lang.defaultLang))
-
- @defining(c.msg.replaceAll("script", ".script").replaceAll("\n", "
")) { message: String =>
-
@Html(message)
- @models.Proposal.ProposalIDRegExp.findAllIn(message).map { proposalIdRef =>
-
@tags.linkToProposal(proposalIdRef)
- }
- @models.Proposal.HttpUrl.findAllIn(message).map { test =>
-
@test
- }
- }
-
-
-
- }
+@(comments: List[models.Comment], maybeProposalLastVisit: Option[org.joda.time.DateTime])
+ @defining(comments.reverse.find{ comment => maybeProposalLastVisit.map { proposalLastVisit => proposalLastVisit.isBefore(comment.eventDate.get) }.getOrElse(true) }){ maybeFirstUnwatchedComment: Option[Comment] =>
+ @comments.zipWithIndex.map{ case (c, index) =>
+ @models.Speaker.findByUUID(c.uuidAuthor).map { speaker =>
+ @models.Webuser.findByUUID(c.uuidAuthor).map { webuser =>
+
+
+
+ @if(speaker.avatarUrl.isEmpty) {
+
?s=35)
+ } else {
+

+ }
+
+
+
+ @webuser.cleanName
+ @Messages("tags.renderComment.postedBy",
+ library.FormatDate.jodaDateFormat(c.eventDate.get, play.api.i18n.Lang.defaultLang),
+ library.FormatDate.jodaTimeFormat(c.eventDate.get, play.api.i18n.Lang.defaultLang))
+
+ @defining(c.msg.replaceAll("script", ".script").replaceAll("\n", "
")) { message: String =>
+
@Html(message)
+ @models.Proposal.ProposalIDRegExp.findAllIn(message).map { proposalIdRef =>
+
@tags.linkToProposal(proposalIdRef)
+ }
+ @models.Proposal.HttpUrl.findAllIn(message).map { test =>
+
@test
+ }
+ }
+
+
+
+ @if(maybeFirstUnwatchedComment.map(c == _).getOrElse(false)) {
+
+ }
}
+ }
+ }
}
diff --git a/conf/messages b/conf/messages
index 36497803..dc55f3b0 100644
--- a/conf/messages
+++ b/conf/messages
@@ -444,6 +444,7 @@ admin.draft.warning3=Current proposal state :
newProposal.maxLength=Max size is 1200 characters (including Markdown characters, if you want to use it)
preview.txt=Preview Conference guide (sample page)
tags.renderComment.postedBy=Posted on {0} at {1}
+tags.renderComment.newMessages=New messages
admin.btn.sponsor=VIP view on proposals
leaderboard.compute=Computing stats
diff --git a/conf/messages.fr b/conf/messages.fr
index 51fb88f7..e7cb1d08 100644
--- a/conf/messages.fr
+++ b/conf/messages.fr
@@ -383,6 +383,7 @@ admin.draft.warning3=Etat actuel de cette proposition :
newProposal.maxLength=Maximum 1200 caractères. Possibilité d''utiliser Markdown
preview.txt=Aperçu de votre présentation dans le programme papier
tags.renderComment.postedBy=Posté le {0} à {1}
+tags.renderComment.newMessages=Nouveaux messages
admin.btn.sponsor=Voir comme un sponsor
leaderboard.compute=Calcul des stats en cours...