app/controllers/Application.scala (158 lines of code) (raw):
package controllers
import com.gu.pandomainauth.PanDomainAuthSettingsRefresher
import com.gu.permissions.{PermissionDefinition, PermissionsProvider}
import com.gu.workflow.api.{DesksAPI, SectionDeskMappingsAPI, SectionsAPI, StubAPI}
import com.gu.workflow.lib.{Priorities, StatusDatabase, TagService}
import config.Config
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json, parser}
import lib.{AtomWorkshopConfig, ComposerConfig, MediaAtomMakerConfig}
import models.api.ApiResponseFt
import models.{Desk, EditorialSupportStaff, Section}
import play.api.{Logger, Logging}
import play.api.libs.ws.WSClient
import play.api.mvc._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
class Application(
val editorialSupportTeams: EditorialSupportTeamsController,
val sectionsAPI: SectionsAPI,
val tagService: TagService,
val desksAPI: DesksAPI,
val sectionDeskMappingsAPI: SectionDeskMappingsAPI,
override val permissions: PermissionsProvider,
override val config: Config,
override val controllerComponents: ControllerComponents,
override val wsClient: WSClient,
override val panDomainSettings: PanDomainAuthSettingsRefresher,
stubsApi: StubAPI,
) extends BaseController with PanDomainAuthActions with Logging {
def getSortedSections(): Future[List[Section]] = {
sectionsAPI.getSections.asFuture.map {
case Left(err) => logger.error(s"error fetching sections: $err"); List()
case Right(sections) => sections.sortBy(_.name)
}
}
def getSortedDesks(): Future[List[Desk]] = {
desksAPI.getDesks.asFuture.map {
case Right(desks) => desks.sortBy(_.name)
case Left(err) => logger.error(s"error fetching desks: $err"); List()
}
}
def getSectionsInDesks(): Future[List[models.api.SectionsInDeskMapping]] = {
sectionDeskMappingsAPI.getSectionsInDesks.asFuture.map {
case Right(mappings) => mappings
case Left(err) => logger.error(s"error fetching section desk mappings: $err"); List()
}
}
def index = AuthAction { request =>
Redirect(routes.Application.dashboard)
}
def dashboard = app("Workflow")
def training = AuthAction { request =>
Redirect("https://sites.google.com/a/guardian.co.uk/esd/web-tools/composer-workflow/workflow/how-to-use-workflow-quick-instructions")
}
def faqs = AuthAction { request =>
Ok(views.html.faqs())
}
def troubleshooting = Action { request =>
Ok(views.html.troubleshooting())
}
def editorialSupport = AuthAction { implicit request =>
val staff = editorialSupportTeams.listStaff()
val teams = EditorialSupportStaff.groupByTeams(staff)
val fronts = EditorialSupportStaff.getTeam("Fronts", teams)
val other = teams.filterNot(_.name == "Fronts")
Ok(views.html.editorialSupportStatus(other, fronts))
}
def updateEditorialSupport = AuthAction(parse.form(EditorialSupportStaff.form)) { implicit request =>
editorialSupportTeams.updateStaff(request.body)
// Get the browser to reload the page once we've sucessfully updated
Redirect(routes.Application.editorialSupport)
}
// limited tag fields we want output into the DOM
case class LimitedTag(id: Long, externalName: String)
object LimitedTag {
implicit val encoder: Encoder[LimitedTag] = deriveEncoder
implicit val decoder: Decoder[LimitedTag] = deriveDecoder
}
private val pinboardPermission = PermissionDefinition("pinboard", "pinboard")
def app(title: String) = AuthAction.async { request =>
for {
sections <- getSortedSections()
desks <- getSortedDesks()
sectionsInDesks <- getSectionsInDesks()
commissioningDesks <- tagService.getTags(
Map(
"limit" -> "200",
"query" -> "tracking/commissioningdesk/",
"type" -> "tracking",
"searchField" -> "path"
).toList
)
}
yield {
val statuses = StatusDatabase.statuses
val user = request.user
val jsonConfig = Json.obj(
("composer", Json.obj(
("create", Json.fromString(ComposerConfig(config).newContentUrl)),
("view", Json.fromString(ComposerConfig(config).adminUrl)),
("details", Json.fromString(ComposerConfig(config).contentDetails)),
("templates", Json.fromString(ComposerConfig(config).templates))
)),
("mediaAtomMaker", Json.obj(
("create", Json.fromString(MediaAtomMakerConfig(config).newContentUrl)),
("view", Json.fromString(MediaAtomMakerConfig(config).viewContentUrl))
)),
("atomWorkshop", Json.obj(
("create", Json.fromString(AtomWorkshopConfig(config).newContentUrl)),
("view", Json.fromString(AtomWorkshopConfig(config).viewContentUrl))
)),
("statuses", statuses.asJson),
("desks", desks.asJson),
("sections", sections.asJson),
("sectionsInDesks", sectionsInDesks.asJson), // TODO: Combine desks & sectionsInDesks
("priorities", Priorities.all.asJson),
("viewerUrl", Json.fromString(config.viewerUrl)),
("storyPackagesUrl", Json.fromString(config.storyPackagesUrl)),
("presenceUrl", Json.fromString(config.presenceUrl)),
("user", parser.parse(user.toJson).getOrElse(Json.Null)),
("incopyOpenUrl", Json.fromString(config.incopyOpenUrl)),
("incopyExportUrl", Json.fromString(config.incopyExportUrl)),
("indesignExportUrl", Json.fromString(config.indesignExportUrl)),
("composerRestorerUrl", Json.fromString(config.composerRestorerUrl)),
("commissioningDesks", commissioningDesks.map(t => LimitedTag(t.id, t.externalName)).asJson),
("atomTypes", config.atomTypes.asJson),
("sessionId", Json.fromString(config.sessionId)),
("gaId", Json.fromString(config.googleTrackingId)),
("tagManagerUrl", Json.fromString(config.tagManagerUrl)),
("stage", Json.fromString(config.stage.toString)),
("telemetryUrl", Json.fromString(config.telemetryUrl))
)
val hasPinboardPermission = permissions.hasPermission(pinboardPermission, request.user.email)
Ok(views.html.app(
title,
Some(user),
config = jsonConfig,
gaId = config.googleTrackingId,
presenceClientLib = config.presenceClientLib,
maybePinboardLoaderUrl = if(hasPinboardPermission) Some(config.pinboardLoaderUrl) else None
))
}
}
def redirect(stubId: Long) = AuthAction.async { request =>
stubsApi.getStub(stubId).map{
case Some(stub) if stub.composerId.isDefined => Redirect(
url = s"${config.composerUrl}/content/${stub.composerId.get}",
queryStringParams = request.queryString // forward any query params
)
case _ => NotFound
}.asFuture.map{
case Left(err) => {
logger.error(s"could not get stub with id $stubId, for redirect. Error: $err")
InternalServerError
}
case Right(result) => result
}
}
}