Skip to content

Commit

Permalink
Merge pull request #55 from hmrc/DC-3349X
Browse files Browse the repository at this point in the history
DC-3349: MessageInbox will support both messages and conversations
  • Loading branch information
muralishub authored May 13, 2021
2 parents cf6f4a3 + 1916efb commit d213792
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 69 deletions.
8 changes: 3 additions & 5 deletions app/connectors/SecureMessageConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package connectors

import controllers.generic.models.{ CustomerEnrolment, Tag }
import models.{ Conversation, ConversationHeader, Count, CustomerMessage, Letter }
import models.{ Conversation, Count, CustomerMessage, Letter, MessageHeader }
import play.api.Logging
import play.mvc.Http.Status.CREATED
import uk.gov.hmrc.http.HttpReads.Implicits._
Expand All @@ -34,12 +34,10 @@ class SecureMessageConnector @Inject()(httpClient: HttpClient, servicesConfig: S
def getConversationList(
enrolmentKeys: Option[List[String]],
customerEnrolments: Option[List[CustomerEnrolment]],
tags: Option[List[Tag]])(implicit ec: ExecutionContext, hc: HeaderCarrier): Future[List[ConversationHeader]] = {
tags: Option[List[Tag]])(implicit ec: ExecutionContext, hc: HeaderCarrier): Future[List[MessageHeader]] = {
val queryParams = queryParamsBuilder(enrolmentKeys, customerEnrolments, tags)
httpClient
.GET[List[ConversationHeader]](
s"$secureMessageBaseUrl/secure-messaging/conversations",
queryParams.getOrElse(List()))
.GET[List[MessageHeader]](s"$secureMessageBaseUrl/secure-messaging/messages", queryParams.getOrElse(List()))
}

def getCount(
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/ConversationInboxController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import uk.gov.hmrc.auth.core.{ AuthConnector, AuthorisedFunctions }
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
import uk.gov.hmrc.play.http.HeaderCarrierConverter
import views.html.partials.conversationInbox
import views.viewmodels.ConversationInbox
import views.html.partials.messageInbox
import views.viewmodels.MessageInbox

import javax.inject.{ Inject, Singleton }
import scala.concurrent.{ ExecutionContext, Future }
Expand All @@ -36,7 +36,7 @@ import scala.concurrent.{ ExecutionContext, Future }
class ConversationInboxController @Inject()(
appConfig: AppConfig,
controllerComponents: MessagesControllerComponents,
inbox: conversationInbox,
inbox: messageInbox,
secureMessageConnector: SecureMessageConnector,
val authConnector: AuthConnector)(implicit ec: ExecutionContext)
extends FrontendController(controllerComponents) with I18nSupport with AuthorisedFunctions
Expand All @@ -59,7 +59,7 @@ class ConversationInboxController @Inject()(
Future.successful(
Ok(
inbox.apply(
ConversationInbox(
MessageInbox(
clientService,
messages("conversation.inbox.title"),
conversations.size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ import play.api.libs.json.JodaReads.jodaDateReads
import play.api.libs.json.JodaWrites.jodaDateWrites
import play.api.libs.json.{ Format, Json, OFormat }

final case class ConversationHeader(
client: String,
conversationId: String,
final case class MessageHeader(
messageType: MessageType,
id: String,
subject: String,
issueDate: DateTime,
senderName: Option[String],
unreadMessages: Boolean,
count: Int)
count: Int,
conversationId: Option[String],
client: Option[String]
)

object ConversationHeader {
object MessageHeader {

private val dateFormatString = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

implicit val dateFormat: Format[DateTime] = Format(jodaDateReads(dateFormatString), jodaDateWrites(dateFormatString))

implicit val conversationHeaderReads: OFormat[ConversationHeader] = Json.format[ConversationHeader]
implicit val conversationHeaderReads: OFormat[MessageHeader] = Json.format[MessageHeader]

}
27 changes: 27 additions & 0 deletions app/models/MessageType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2021 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package models
import enumeratum.EnumEntry.{ Lowercase }
import enumeratum.{ Enum, EnumEntry, PlayEnum }

sealed trait MessageType extends EnumEntry with Lowercase

object MessageType extends Enum[MessageType] with PlayEnum[MessageType] {
val values = findValues
case object Conversation extends MessageType
case object Letter extends MessageType
}
17 changes: 12 additions & 5 deletions app/views/helpers/HtmlUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package views.helpers

import cats.implicits.catsSyntaxEq
import models.{ ConversationHeader, FirstReaderInformation, SenderInformation }
import models.{ FirstReaderInformation, MessageHeader, MessageType, SenderInformation }
import org.apache.commons.codec.binary.Base64
import org.joda.time._
import org.joda.time.format.DateTimeFormat
Expand All @@ -37,19 +37,26 @@ object HtmlUtil {
private def dateTimeFormatWithLondonZone(pattern: String) =
DateTimeFormat.forPattern(pattern).withZone(DateTimeZone.forID("Europe/London"))

def getSenderName(conversationHeader: ConversationHeader)(implicit messages: Messages): String =
def getSenderName(conversationHeader: MessageHeader)(implicit messages: Messages): String =
conversationHeader.senderName match {
case Some(name) => name
case _ => messages("conversation.inbox.default.sender")
}

def getMessageDate(conversationHeader: ConversationHeader): String =
def getMessageDate(conversationHeader: MessageHeader): String =
if (conversationHeader.issueDate.toLocalDate.toString === DateTime.now.toLocalDate.toString) {
dtfHours.print(conversationHeader.issueDate) + amOrPm.print(conversationHeader.issueDate).toLowerCase
} else { dtf.print(conversationHeader.issueDate) }

def getConversationUrl(clientService: String, conversationHeader: ConversationHeader): String =
s"/$clientService/conversation/${conversationHeader.client}/${conversationHeader.conversationId}"
def getMessageUrl(clientService: String, messageHeader: MessageHeader): String =
if (messageHeader.messageType.entryName === MessageType.Conversation.entryName) {
(messageHeader.client, messageHeader.conversationId) match {
case (Some(client), Some(conversationId)) => s"/$clientService/conversation/$client/$conversationId"
case _ => ""
}
} else {
s"/$clientService/messages/${messageHeader.id}"
}

def readableTime(dateTime: DateTime): String =
conversationDateTimeFormat.print(dateTime) + amOrPm.print(dateTime).toLowerCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
* limitations under the License.
*@

@import models.ConversationHeader
@import models.MessageHeader
@import views.helpers.HtmlUtil._
@import uk.gov.hmrc.urls.Link
@import views.viewmodels.ConversationInbox
@import views.viewmodels.MessageInbox

@this()
@(params: ConversationInbox)(implicit messages: Messages)
@(params: MessageInbox)(implicit messages: Messages)
@import params._
<style>
.header-status {
Expand Down Expand Up @@ -108,7 +108,7 @@ <h1 class="govuk-heading-xl">@heading</h1>
<!-- status -->
<div class="conversation-status">@{
if(conversationHeader.unreadMessages) {
<a href={getConversationUrl(clientService,conversationHeader)} target="_self" data-sso="false" class="no--underline" aria-hidden="true">
<a href={getMessageUrl(clientService,conversationHeader)} target="_self" data-sso="false" class="no--underline" aria-hidden="true">
<span class="dot-unread">Unread</span>
</a>
<span class="govuk-visually-hidden">unread message</span>
Expand All @@ -124,7 +124,7 @@ <h1 class="govuk-heading-xl">@heading</h1>
<span class="govuk-visually-hidden">from</span><span class='black-text'>{getSenderName(conversationHeader)}</span>
}
Link.toInternalPage(
url = getConversationUrl(clientService,conversationHeader),
url = getMessageUrl(clientService,conversationHeader),
Some(senderSpan.mkString),
None,
Some("no-underline")
Expand All @@ -148,7 +148,7 @@ <h1 class="govuk-heading-xl">@heading</h1>
subjectMaybeRead
}
Link.toInternalPage(
url = getConversationUrl(clientService,conversationHeader),
url = getMessageUrl(clientService,conversationHeader),
Some(subjectMaybeWithCount.mkString),
None,
Some("no-underline conversation-subject")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@

package views.viewmodels

import models.ConversationHeader
import models.MessageHeader
import play.api.libs.functional.syntax._
import play.api.libs.json.{ Json, OWrites, Reads, __ }

final case class ConversationInbox(
final case class MessageInbox(
clientService: String,
heading: String,
total: Int,
unread: Int,
conversationHeaders: List[ConversationHeader])
object ConversationInbox {
conversationHeaders: List[MessageHeader])
object MessageInbox {

def defaultObject: ConversationInbox = ConversationInbox("", "", 0, 0, List.empty[ConversationHeader])
def defaultObject: MessageInbox = MessageInbox("", "", 0, 0, List.empty[MessageHeader])

implicit def jsonReads: Reads[ConversationInbox] =
implicit def jsonReads: Reads[MessageInbox] =
(
(__ \ "clientService").readWithDefault[String](defaultObject.clientService) and
(__ \ "heading").readWithDefault[String](defaultObject.heading) and
(__ \ "total").readWithDefault[Int](defaultObject.total) and
(__ \ "unread").readWithDefault[Int](defaultObject.unread) and
(__ \ "conversationHeaders").readWithDefault[List[ConversationHeader]](defaultObject.conversationHeaders)
)(ConversationInbox.apply _)
(__ \ "conversationHeaders").readWithDefault[List[MessageHeader]](defaultObject.conversationHeaders)
)(MessageInbox.apply _)

implicit def jsonWrites: OWrites[ConversationInbox] = Json.writes[ConversationInbox]
implicit def jsonWrites: OWrites[MessageInbox] = Json.writes[MessageInbox]

}
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ dependencyUpdatesFilter -= moduleFilter(organization = "com.github.ghik")
dependencyUpdatesFilter -= moduleFilter(organization = "com.typesafe.play")
dependencyUpdatesFilter -= moduleFilter(organization = "org.scalatest")
dependencyUpdatesFilter -= moduleFilter(organization = "org.scalatestplus.play")
dependencyUpdatesFilter -= moduleFilter(name = "enumeratum-play")
dependencyUpdatesFailBuild := true
sources in (Compile, doc) := Seq.empty

Expand Down
12 changes: 7 additions & 5 deletions it/ConversationInboxPartialISpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import com.google.inject.AbstractModule
import connectors.SecureMessageConnector
import controllers.generic.models.{ CustomerEnrolment, Tag }
import models.ConversationHeader
import models.{ MessageHeader, MessageType }
import net.codingwell.scalaguice.ScalaModule
import org.joda.time.DateTime
import org.mockito.ArgumentMatchers
Expand Down Expand Up @@ -60,14 +60,16 @@ class ConversationInboxPartialISpec extends PlaySpec with ServiceSpec with Mocki
)(any[ExecutionContext], any[HeaderCarrier])).thenReturn(
Future.successful(
List(
ConversationHeader(
"cdcm",
MessageHeader(
MessageType.Conversation,
"123456",
"D-80542-20201120",
"DMS7324874993",
new DateTime(),
Some("CDS Exports Team"),
unreadMessages = true,
1)))
1,
Some(""),
Some(""))))
)
val response = wsClient
.url(resource("/secure-message-frontend/cdcm/messages?" +
Expand Down
3 changes: 2 additions & 1 deletion project/AppDependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ object AppDependencies {
"com.typesafe.play" %% "play-json-joda" % "2.9.1",
"com.iheart" %% "play-swagger" % "0.10.4",
"org.typelevel" %% "cats-core" % "2.6.0",
"org.scala-lang.modules" %% "scala-xml" % "1.3.0"
"org.scala-lang.modules" %% "scala-xml" % "1.3.0",
"com.beachape" %% "enumeratum-play" % "1.5.17"
)

val test = Seq(
Expand Down
22 changes: 15 additions & 7 deletions test/connectors/SecureMessageConnectorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,23 @@ class SecureMessageConnectorSpec extends PlaySpec with MockitoSugar {
)
when(
mockHttpClient
.GET[List[ConversationHeader]](
any[String],
ArgumentMatchers.eq(expectedQueryParams),
any[Seq[(String, String)]])(
any[HttpReads[List[ConversationHeader]]],
.GET[List[MessageHeader]](any[String], ArgumentMatchers.eq(expectedQueryParams), any[Seq[(String, String)]])(
any[HttpReads[List[MessageHeader]]],
any[HeaderCarrier],
any[ExecutionContext]))
.thenReturn(Future.successful(
List(ConversationHeader("cdcm", "123", "ABC", new DateTime(), None, unreadMessages = true, 1))))
.thenReturn(
Future.successful(
List(
MessageHeader(
MessageType.Conversation,
"123",
"ABC",
new DateTime(),
None,
unreadMessages = true,
1,
Some("123"),
Some("CDCM")))))
private val result = await(
connector.getConversationList(
Some(List("HMRC-CUS-ORG")),
Expand Down
22 changes: 12 additions & 10 deletions test/controllers/ConversationInboxControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import akka.util.Timeout
import config.AppConfig
import connectors.SecureMessageConnector
import controllers.generic.models.{ CustomerEnrolment, Tag }
import models.ConversationHeader
import models.{ MessageHeader, MessageType }
import org.joda.time.DateTime
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.any
Expand All @@ -33,8 +33,8 @@ import play.api.test.Helpers.{ GET, contentAsString, status }
import play.api.test.{ FakeRequest, Helpers }
import play.twirl.api.Html
import uk.gov.hmrc.http.HeaderCarrier
import views.html.partials.conversationInbox
import views.viewmodels.{ ConversationInbox }
import views.html.partials.messageInbox
import views.viewmodels.MessageInbox

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
Expand All @@ -55,15 +55,17 @@ class ConversationInboxControllerSpec extends PlaySpec with MockitoSugar with Mo
.thenReturn(
Future(
List(
ConversationHeader(
"cdcm",
"D-80542-20201120",
MessageHeader(
MessageType.Conversation,
"123456",
"DMS7324874993",
new DateTime(),
Some("CDS Exports Team"),
unreadMessages = true,
1))))
when(mockConversationsInboxPartial.apply(any[ConversationInbox])(any[Messages])).thenReturn(new Html("test"))
1,
Some("D-80542-20201120"),
Some("cdcm")))))
when(mockConversationsInboxPartial.apply(any[MessageInbox])(any[Messages])).thenReturn(new Html("test"))
private val controller = new ConversationInboxController(
mockAppConfig,
Helpers.stubMessagesControllerComponents(),
Expand All @@ -87,7 +89,7 @@ class ConversationInboxControllerSpec extends PlaySpec with MockitoSugar with Mo
ArgumentMatchers.eq(None),
ArgumentMatchers.eq(None)
)(any[ExecutionContext], any[HeaderCarrier])).thenReturn(Future(List()))
when(mockConversationsInboxPartial.apply(any[ConversationInbox])(any[Messages])).thenReturn(new Html("test"))
when(mockConversationsInboxPartial.apply(any[MessageInbox])(any[Messages])).thenReturn(new Html("test"))
private val controller = new ConversationInboxController(
mockAppConfig,
Helpers.stubMessagesControllerComponents(),
Expand All @@ -106,7 +108,7 @@ class ConversationInboxControllerSpec extends PlaySpec with MockitoSugar with Mo
implicit val mockAppConfig: AppConfig = mock[AppConfig]
val mockMessagesApi: MessagesApi = mock[MessagesApi]
implicit val messages: MessagesImpl = MessagesImpl(Lang("en"), mockMessagesApi)
val mockConversationsInboxPartial: conversationInbox = mock[conversationInbox]
val mockConversationsInboxPartial: messageInbox = mock[messageInbox]
val mockSecureMessageConnector: SecureMessageConnector = mock[SecureMessageConnector]

}
Expand Down
Loading

0 comments on commit d213792

Please sign in to comment.