diff --git a/client/src/main/scala/drt/client/SPAMain.scala b/client/src/main/scala/drt/client/SPAMain.scala index d89cea1437..01172c2861 100644 --- a/client/src/main/scala/drt/client/SPAMain.scala +++ b/client/src/main/scala/drt/client/SPAMain.scala @@ -4,20 +4,23 @@ import diode.Action import drt.client.actions.Actions._ import drt.client.components.TerminalDesksAndQueues.{ChartsView, Deployments, DeskType, DisplayType, Ideal, TableView} import drt.client.components.styles._ -import drt.client.components.{ContactPage, FeedsStatusPage, ForecastUploadComponent, GlobalStyles, Layout, PortConfigPage, PortDashboardPage, TerminalComponent, TrainingHubComponent, UserDashboardPage} +import drt.client.components.{FeedsStatusPage, ForecastUploadComponent, GlobalStyles, Layout, PortConfigPage, PortDashboardPage, TerminalComponent, TrainingHubComponent, UserDashboardPage} import drt.client.logger._ +import drt.client.modules.GoogleEventTracker import drt.client.services.JSDateConversions.SDate import drt.client.services._ import drt.client.services.handlers.GetFeedSourceStatuses import drt.client.spa.TerminalPageModes.{Current, Staffing} import drt.client.spa.{TerminalPageMode, TerminalPageModes} +import drt.shared.DrtPortConfigs import io.kinoplan.scalajs.react.material.ui.core.system.ThemeProvider import japgolly.scalajs.react.Callback import japgolly.scalajs.react.extra.router._ import org.scalajs.dom -import org.scalajs.dom.console +import org.scalajs.dom.{console, window} import scalacss.ProdDefaults._ import uk.gov.homeoffice.drt.Urls +import uk.gov.homeoffice.drt.ports.PortCode import uk.gov.homeoffice.drt.ports.Terminals.Terminal import uk.gov.homeoffice.drt.time.{LocalDate, SDateLike} @@ -26,7 +29,28 @@ import scala.util.Try object SPAMain { - sealed trait Loc + sealed trait Loc { + val url: String + def href: String = window.location.href.split("#").headOption match { + case Some(head) => head + url + case None => url + } + val portCodeStr = dom.document.getElementById("port-code").getAttribute("value") + val portConfig = DrtPortConfigs.confByPort(PortCode(portCodeStr)) + + def terminalPart(maybeTerminal: Option[Terminal]): String = { + val terminalShortName = maybeTerminal.map { t => + val terminalStr = t.toString + if (terminalStr.take(1) == "T") terminalStr.drop(1) else terminalStr + } + terminalShortName.map(t => s", Terminal $t").getOrElse("") + } + + def title(pageName: String, maybeTerminal: Option[Terminal]) = + s"$pageName at ${portConfig.portCode.iata} (${portConfig.portName})${terminalPart(maybeTerminal)} - DRT" + + def title(maybeTerminal: Option[Terminal]): String + } sealed trait UrlParameter { val name: String @@ -77,6 +101,8 @@ object SPAMain { } object TerminalPageTabLoc { + val hashValue: String = "#terminal" + def apply(terminalName: String, mode: TerminalPageMode, subMode: String, @@ -89,6 +115,21 @@ object SPAMain { subMode: String = "arrivals", queryParams: Map[String, String] = Map.empty[String, String] ) extends Loc { + private val queryString = if (queryParams.nonEmpty) s"?${queryParams.map { case (k, v) => s"$k=$v" }.mkString("&")}" else "" + override val url = s"${TerminalPageTabLoc.hashValue}/$terminalName/$modeStr/$subMode$queryString" + def pageName = (modeStr.toLowerCase, subMode.toLowerCase) match { + case ("current", "arrivals") => "Arrivals" + case ("current", "desksandqueues") => "Desks and queues" + case ("current", "staffing") => "Staff movements" + case ("current", "simulations") => "Simulate day" + case ("dashboard", "summary") => "Terminal dashboard" + case ("planning", _) => "Staff planning" + case ("staffing", _) => "Monthly staffing" + case _ => "" + } + + override def title(maybeTerminal: Option[Terminal]): String = title(pageName, maybeTerminal) + val terminal: Terminal = Terminal(terminalName) val maybeViewDate: Option[LocalDate] = queryParams.get(UrlDateParameter.paramName) .filter(_.matches(".+")) @@ -150,19 +191,52 @@ object SPAMain { def serverLogEndpoint: String = absoluteUrl("logging") - case class PortDashboardLoc(period: Option[Int]) extends Loc + object PortDashboardLoc { + val hashValue: String = "#portDashboard" + } + case class PortDashboardLoc(period: Option[Int]) extends Loc { + override val url = s"${PortDashboardLoc.hashValue}/$period" + override def title(maybeTerminal: Option[Terminal]): String = title("Dashboard", maybeTerminal) + } + + case object StatusLoc extends Loc { + val hashValue: String = "#status" + override val url = s"$hashValue" + override def title(maybeTerminal: Option[Terminal]): String = title("Feeds status", maybeTerminal) + } - case object StatusLoc extends Loc + case object UserDashboardLoc extends Loc { + val hashValue: String = "" + override val url = "" + override def title(maybeTerminal: Option[Terminal]): String = title("Dashboard", maybeTerminal) + } - case object UserDashboardLoc extends Loc + object TrainingHubLoc { + val hashValue: String = "#trainingHub" + } + case class TrainingHubLoc(modeStr: String = "dropInBooking") extends Loc { + override val url = s"${TrainingHubLoc.hashValue}/$modeStr" - case object ContactUsLoc extends Loc + val subTtitle = modeStr match { + case "dropInBooking" => "Book a drop-in" + case "trainingMaterial" => "Training material" + case _ => "" + } - case class TrainingHubLoc(modeStr: String = "dropInBooking") extends Loc + override def title(maybeTerminal: Option[Terminal]): String = title(s"Training hub - $subTtitle", maybeTerminal) + } - case object PortConfigLoc extends Loc + case object PortConfigLoc extends Loc { + val hashValue: String = "#config" + override val url = s"$hashValue" + override def title(maybeTerminal: Option[Terminal]): String = title("Port config", maybeTerminal) + } - case object ForecastFileUploadLoc extends Loc + case object ForecastFileUploadLoc extends Loc { + val hashValue: String = "#forecastFileUpload" + override val url = s"$hashValue" + override def title(maybeTerminal: Option[Terminal]): String = title("Forecast upload", maybeTerminal) + } private val initialRequestsActions = Seq( GetApplicationVersion, @@ -195,7 +269,6 @@ object SPAMain { dashboardRoute(dsl) | terminalRoute(dsl) | statusRoute(dsl) | - contactRoute(dsl) | trainingHubRoute(dsl) | portConfigRoute(dsl) | forecastFileUploadRoute(dsl) @@ -203,66 +276,71 @@ object SPAMain { rule.notFound(redirectToPage(PortDashboardLoc(None))(SetRouteVia.HistoryReplace)) } .renderWith(Layout(_, _)) + .setTitle(_.title(maybeTerminal)) .onPostRender((maybePrevLoc, currentLoc) => { - Callback( - (maybePrevLoc, currentLoc) match { - case (Some(p: TerminalPageTabLoc), c: TerminalPageTabLoc) => - if (c.updateRequired(p)) SPACircuit.dispatch(c.loadAction) - case (_, c: TerminalPageTabLoc) => - SPACircuit.dispatch(c.loadAction) - case (_, UserDashboardLoc) => - SPACircuit.dispatch(GetUserDashboardState) - case _ => - } - ) + val title = currentLoc.title(maybeTerminal) + log.info(s"Sending pageview: $title (${currentLoc.href})") + Callback(GoogleEventTracker.sendPageView(title, currentLoc.href)) >> + Callback( + (maybePrevLoc, currentLoc) match { + case (Some(p: TerminalPageTabLoc), c: TerminalPageTabLoc) => + if (c.updateRequired(p)) SPACircuit.dispatch(c.loadAction) + case (_, c: TerminalPageTabLoc) => + SPACircuit.dispatch(c.loadAction) + case (_, UserDashboardLoc) => + SPACircuit.dispatch(GetUserDashboardState) + case _ => + } + ) }) + private def maybeTerminal: Option[Terminal] = { + val terminalRegex = """.+terminal/([A-Z0-9]+)/.+""".r + val url = window.location.href + url match { + case terminalRegex(t) => Some(Terminal(t)) + case _ => None + } + } + def homeRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { import dsl._ staticRoute(root, UserDashboardLoc) ~> renderR((router: RouterCtl[Loc]) => UserDashboardPage(router)) } - - def statusRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { + def dashboardRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { import dsl._ - val proxy = SPACircuit.connect(m => (m.loggedInUserPot, m.airportConfig)) - - staticRoute("#status", StatusLoc) ~> renderR(_ => proxy(p => FeedsStatusPage(p()._1, p()._2))) - } - - def contactRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { - import dsl._ + val proxy = SPACircuit.connect(_.airportConfig) - staticRoute("#contact", ContactUsLoc) ~> renderR(_ => ContactPage()) + dynamicRouteCT((PortDashboardLoc.hashValue / int.option).caseClass[PortDashboardLoc]) ~> + dynRenderR { case (page: PortDashboardLoc, router) => + proxy(p => PortDashboardPage(router, page, p())) + } } - def forecastFileUploadRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { + def terminalRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { import dsl._ - val proxy = SPACircuit.connect(_.airportConfig) - - staticRoute("#forecastFileUpload", ForecastFileUploadLoc) ~> renderR(_ => proxy(ac => ForecastUploadComponent(ac()))) - } + val requiredTerminalName = string("[a-zA-Z0-9]+") + val requiredTopLevelTab = string("[a-zA-Z0-9]+") + val requiredSecondLevelTab = string("[a-zA-Z0-9]+") - def portConfigRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { - import dsl._ - val proxy = SPACircuit.connect(m => - PortConfigPage.Props(m.redListUpdates, m.egateBanksUpdates, m.slaConfigs, m.loggedInUserPot, m.airportConfig, m.gateStandWalkTime) - ) - staticRoute("#config", PortConfigLoc) ~> render(proxy(props => PortConfigPage(props()))) + dynamicRouteCT( + (TerminalPageTabLoc.hashValue / requiredTerminalName / requiredTopLevelTab / requiredSecondLevelTab / "" ~ queryToMap).caseClass[TerminalPageTabLoc]) ~> + dynRenderR { case (page: TerminalPageTabLoc, router) => + val props = TerminalComponent.Props(terminalPageTab = page, router) + ThemeProvider(DrtTheme.theme)(TerminalComponent(props)) + } } - def dashboardRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { + def statusRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { import dsl._ - val proxy = SPACircuit.connect(_.airportConfig) + val proxy = SPACircuit.connect(m => (m.loggedInUserPot, m.airportConfig)) - dynamicRouteCT(("#portDashboard" / int.option).caseClass[PortDashboardLoc]) ~> - dynRenderR { case (page: PortDashboardLoc, router) => - proxy(p => PortDashboardPage(router, page, p())) - } + staticRoute(StatusLoc.hashValue, StatusLoc) ~> renderR(_ => proxy(p => FeedsStatusPage(p()._1, p()._2))) } def trainingHubRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { @@ -271,7 +349,7 @@ object SPAMain { val proxy = SPACircuit.connect(m => (m.loggedInUserPot, m.airportConfig)) dynamicRouteCT( - ("#trainingHub" / string("[a-zA-Z0-9]*")).caseClass[TrainingHubLoc]) ~> + (TrainingHubLoc.hashValue / string("[a-zA-Z0-9]*")).caseClass[TrainingHubLoc]) ~> dynRenderR { case (page: TrainingHubLoc, router) => proxy { p => val props = TrainingHubComponent.Props(trainingHubLoc = page, router, p()._1, p()._2) @@ -280,19 +358,20 @@ object SPAMain { } } - def terminalRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { + def portConfigRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { import dsl._ + val proxy = SPACircuit.connect(m => + PortConfigPage.Props(m.redListUpdates, m.egateBanksUpdates, m.slaConfigs, m.loggedInUserPot, m.airportConfig, m.gateStandWalkTime) + ) + staticRoute(PortConfigLoc.hashValue, PortConfigLoc) ~> render(proxy(props => PortConfigPage(props()))) + } - val requiredTerminalName = string("[a-zA-Z0-9]+") - val requiredTopLevelTab = string("[a-zA-Z0-9]+") - val requiredSecondLevelTab = string("[a-zA-Z0-9]+") + def forecastFileUploadRoute(dsl: RouterConfigDsl[Loc, Unit]): dsl.Rule = { + import dsl._ - dynamicRouteCT( - ("#terminal" / requiredTerminalName / requiredTopLevelTab / requiredSecondLevelTab / "" ~ queryToMap).caseClass[TerminalPageTabLoc]) ~> - dynRenderR { case (page: TerminalPageTabLoc, router) => - val props = TerminalComponent.Props(terminalPageTab = page, router) - ThemeProvider(DrtTheme.theme)(TerminalComponent(props)) - } + val proxy = SPACircuit.connect(_.airportConfig) + + staticRoute(ForecastFileUploadLoc.hashValue, ForecastFileUploadLoc) ~> renderR(_ => proxy(ac => ForecastUploadComponent(ac()))) } val pathToThisApp: String = dom.document.location.pathname diff --git a/client/src/main/scala/drt/client/components/ContactPage.scala b/client/src/main/scala/drt/client/components/ContactPage.scala deleted file mode 100644 index 76d1ddb233..0000000000 --- a/client/src/main/scala/drt/client/components/ContactPage.scala +++ /dev/null @@ -1,203 +0,0 @@ -package drt.client.components - -import diode.data.Pot -import drt.client.SPAMain -import drt.client.components.styles.DrtTheme -import drt.client.modules.GoogleEventTracker -import drt.client.services.SPACircuit -import drt.client.services.handlers.GetABFeature -import drt.shared.{ContactDetails, OutOfHoursStatus} -import io.kinoplan.scalajs.react.material.ui.core.system.SxProps -import io.kinoplan.scalajs.react.material.ui.core.{MuiButton, MuiGrid, MuiPaper, MuiTypography} -import japgolly.scalajs.react.component.Scala.Component -import japgolly.scalajs.react.vdom.html_<^._ -import japgolly.scalajs.react.{Callback, CtorType, ScalaComponent} -import org.scalajs.dom -import uk.gov.homeoffice.drt.ABFeature -import drt.client.components.styles.DrtTheme._ - -object ContactPage { - - case class Props() - - val component: Component[Props, Unit, Unit, CtorType.Props] = ScalaComponent.builder[Props]("ContactUs") - .render_P(_ => - MuiGrid(container = true)( - MuiGrid(item = true, xs = 6)( - <.div(^.className := "contact-us", ContactDetailsComponent())), - MuiGrid(item = true, xs = 6)( - <.div(FeedBackComponent()) - ) - )) - .componentDidMount(_ => Callback { - GoogleEventTracker.sendPageView(s"contact") - }) - .build - - def apply(): VdomElement = component(Props()) -} - -case class ContactModel(contactDetails: Pot[ContactDetails], oohStatus: Pot[OutOfHoursStatus]) - -object ContactDetailsComponent { - - case class Props() - - val component: Component[Props, Unit, Unit, CtorType.Props] = ScalaComponent.builder[Props]("ContactUs") - .render_P { _ => - val contactDetailsRCP = SPACircuit.connect(m => ContactModel(m.contactDetails, m.oohStatus)) - <.div( - contactDetailsRCP(contactDetailsMP => { - <.div(contactDetailsMP().contactDetails.renderReady(details => { - contactDetailsMP().oohStatus.renderReady(oohStatus => { - val email = details.supportEmail.getOrElse("DRT Support Email Missing") - val oohPhone = details.oohPhone.getOrElse("OOH Contact Number Missing") - val contactUsHeader = MuiGrid(item = true, xs = 12)(MuiTypography(sx = SxProps(Map( - "color" -> DrtTheme.theme.palette.primary.`700`, - "fontSize" -> DrtTheme.theme.typography.h2.fontSize, - "fontWeight" -> DrtTheme.theme.typography.h2.fontWeight - )))("Contacting the DRT team")) - - val emailHeader = "Email :" - val officeHourLabel = "Office hours :" - val officeHours = "Monday to Friday (9 am to 5 pm)" - - val oohMesssage = MuiGrid(container = true, spacing = 2)( - contactUsHeader, - MuiGrid(item = true, xs = 2)( - MuiTypography(variant = "h7", sx = SxProps(Map("fontWeight" -> "bold")))( - officeHourLabel - ) - ), - MuiGrid(item = true, xs = 10)( - MuiTypography(variant = "h7", sx = SxProps(Map("float" -> "left")))( - officeHours - ) - ), - MuiGrid(item = true, xs = 2)( - MuiTypography(variant = "h7", sx = SxProps(Map("fontWeight" -> "bold")))( - emailHeader - ) - ), - MuiGrid(item = true, xs = 10)( - MuiTypography(variant = "h7", sx = SxProps(Map("float" -> "left")))( - <.a(^.href := s"mailto:$email", email) - ) - ), - MuiGrid(item = true, xs = 6)( - MuiTypography(variant = "h7", sx = SxProps(Map("fontWeight" -> "bold")))( - "Contact number (outside of office hours) :" - ) - ), - MuiGrid(item = true, xs = 6)( - MuiTypography(variant = "h7", sx = SxProps(Map("float" -> "left")))( - oohPhone - ) - ), - ) - - val inHoursMessage = MuiGrid(container = true, spacing = 2)( - contactUsHeader, - MuiGrid(item = true, xs = 2)( - MuiTypography(variant = "h7", sx = SxProps(Map("fontWeight" -> "bold")))( - officeHourLabel - ) - ), - MuiGrid(item = true, xs = 10)( - MuiTypography(variant = "h7", sx = SxProps(Map("float" -> "left")))( - officeHours - ) - ), - MuiGrid(item = true, xs = 2)( - MuiTypography(variant = "h7", sx = SxProps(Map("fontWeight" -> "bold")))( - emailHeader - ) - ), - MuiGrid(item = true, xs = 10)( - MuiTypography(variant = "h7", sx = SxProps(Map("float" -> "left")))( - <.a(^.href := s"mailto:$email", email) - ) - ) - ) - - <.div(if (oohStatus.isOoh) oohMesssage else inHoursMessage) - }) - })) - }) - ) - }.build - - def apply(): VdomElement = component(Props()) - -} - -case class FeedbackModel(abFeatures: Pot[Seq[ABFeature]]) - -object FeedBackComponent { - - case class Props() - - val component: Component[Props, Unit, Unit, CtorType.Props] = ScalaComponent.builder[Props]("ContactUs") - .render_P { _ => - val feedbackRCP = SPACircuit.connect(m => FeedbackModel(m.abFeatures)) - <.div( - feedbackRCP(feedbackMP => { - <.div( - feedbackMP().abFeatures.renderReady { abFeatures => - val aORbTest = abFeatures.headOption.map(_.abVersion).getOrElse("B") - val bannerHead = aORbTest match { - case "A" => "Your feedback improves DRT for everyone" - case _ => "Help us improve the DRT experience" - } - <.div( - MuiPaper(sx = SxProps(Map("elevation" -> "4", "padding" -> "16px", "margin" -> "20px", "backgroundColor" -> "#0E2560")))( - MuiGrid(container = true, spacing = 2)( - MuiGrid(item = true, xs = 12)( - MuiTypography(variant = "h4", sx = SxProps(Map("color" -> "white", "fontWeight" -> "bold")))( - bannerHead - ) - ), - MuiGrid(item = true, xs = 12)( - MuiTypography(variant = "h7", sx = SxProps(Map("color" -> "white", "padding" -> "2px 0")))( - "Complete a short survey (takes 2 minutes to complete)" - ) - ), - MuiGrid(item = true, xs = 12)( - MuiGrid(container = true, direction = "column")( - MuiGrid(item = true, xs = 12)( - MuiTypography(variant = "h7", - sx = SxProps(Map("color" -> "white", "padding" -> "2px 0", "fontWeight" -> "bold")))( - "Your feedback improves how our data can:" - ) - ), - MuiGrid(item = true, xs = 12)( - MuiTypography(variant = "h7", sx = SxProps(Map("color" -> "white", "padding" -> "0px 0")))( - <.ul( - <.li("support resource planning capability"), - <.li("facilitate smoother journeys for legitimate passengers"), - <.li("identify potential risks"), - <.li("create a more resilient Border") - )) - ) - ) - ), - MuiGrid(item = true, xs = 12)( - MuiButton(variant = "outlined", sx = SxProps(Map("textTransform" -> "none", - "border" -> "1px solid white", - "color" -> "white", - "fontWeight" -> "bold", - "fontSize" -> buttonTheme.typography.fontSize)))( - "Give feedback", ^.onClick --> Callback(dom.window.open(s"${SPAMain.urls.rootUrl}/feedback/contact-us/$aORbTest", "_blank")), - ) - ) - ))) - }) - })) - }.componentDidMount(_ => - Callback(SPACircuit.dispatch(GetABFeature("feedback"))) - ) - .build - - def apply(): VdomElement = component(Props()) - -} diff --git a/client/src/main/scala/drt/client/components/DropInDialog.scala b/client/src/main/scala/drt/client/components/DropInDialog.scala index 35b9d1f4a9..2acb51a891 100644 --- a/client/src/main/scala/drt/client/components/DropInDialog.scala +++ b/client/src/main/scala/drt/client/components/DropInDialog.scala @@ -97,7 +97,6 @@ object DropInDialog extends WithScalaCssImplicits { .builder[Props]("DropDialogComponent") .initialStateFromProps(_ => State(1)) .renderBackend[Backend] - .componentDidMount(_ => Callback(GoogleEventTracker.sendPageView("drop-dialog-component"))) .build def apply(date: String, diff --git a/client/src/main/scala/drt/client/components/FeatureGuideModalComponent.scala b/client/src/main/scala/drt/client/components/FeatureGuideModalComponent.scala index 1d67559d4b..3254be267c 100644 --- a/client/src/main/scala/drt/client/components/FeatureGuideModalComponent.scala +++ b/client/src/main/scala/drt/client/components/FeatureGuideModalComponent.scala @@ -107,12 +107,10 @@ object FeatureGuideModalComponent extends WithScalaCssImplicits { .builder[Props]("NavBar") .initialStateFromProps(_ => State(1)) .renderBackend[Backend] - .componentDidMount(_ => Callback(GoogleEventTracker.sendPageView("feature-guide"))) .build def apply(showDialog: Boolean, closeDialog: ReactEvent => Callback, trainingDataTemplates: Seq[FeatureGuide]): VdomElement = component(Props(showDialog, closeDialog, trainingDataTemplates)) - } diff --git a/client/src/main/scala/drt/client/components/FeedsStatusPage.scala b/client/src/main/scala/drt/client/components/FeedsStatusPage.scala index 787c9a0868..d694b041b2 100644 --- a/client/src/main/scala/drt/client/components/FeedsStatusPage.scala +++ b/client/src/main/scala/drt/client/components/FeedsStatusPage.scala @@ -158,10 +158,6 @@ object FeedsStatusPage { ) } } - .componentDidMount { p => - Callback(SetDocumentTitle("Feeds status", p.props.airportConfigPot)) >> - Callback(GoogleEventTracker.sendPageView("feed-status")) - } .build private def displayTime(date: MillisSinceEpoch): String = { diff --git a/client/src/main/scala/drt/client/components/FlightTableContent.scala b/client/src/main/scala/drt/client/components/FlightTableContent.scala index 8c5c72ebbf..b0826950bb 100644 --- a/client/src/main/scala/drt/client/components/FlightTableContent.scala +++ b/client/src/main/scala/drt/client/components/FlightTableContent.scala @@ -171,10 +171,6 @@ object FlightTableContent { val component: Component[Props, Unit, Backend, CtorType.Props] = ScalaComponent.builder[Props]("FlightTableContent") .renderBackend[Backend] - .componentDidMount { p => - Callback(SetDocumentTitle("Arrivals", p.props.terminal, p.props.airportConfig)) >> - Callback(log.info("FlightTableContent mounted")) - } .build def apply(props: Props): VdomElement = component(props) diff --git a/client/src/main/scala/drt/client/components/ForecastUploadComponent.scala b/client/src/main/scala/drt/client/components/ForecastUploadComponent.scala index 2162b0b616..c5c2f15b74 100644 --- a/client/src/main/scala/drt/client/components/ForecastUploadComponent.scala +++ b/client/src/main/scala/drt/client/components/ForecastUploadComponent.scala @@ -73,10 +73,7 @@ object ForecastUploadComponent { } ) } - .componentDidMount { p => - Callback(SetDocumentTitle("Forecast Upload", p.props.airportConfigPot)) >> - Callback(GoogleEventTracker.sendPageView(s"forecastFileUpload")) - }.build + .build def apply(airportConfigPot: Pot[AirportConfig]): VdomElement = component(Props(airportConfigPot)) diff --git a/client/src/main/scala/drt/client/components/MonthlyStaffing.scala b/client/src/main/scala/drt/client/components/MonthlyStaffing.scala index afd82e3727..4ee747d6c0 100644 --- a/client/src/main/scala/drt/client/components/MonthlyStaffing.scala +++ b/client/src/main/scala/drt/client/components/MonthlyStaffing.scala @@ -243,10 +243,6 @@ object MonthlyStaffing { ) } .configure(Reusability.shouldComponentUpdate) - .componentDidMount { p => - Callback(SetDocumentTitle("Monthly Staffing", p.props.terminalPageTab.terminal, p.props.airportConfig)) >> - Callback(GoogleEventTracker.sendPageView(s"${p.props.terminalPageTab.terminal}/planning/${defaultStartDate(p.props.terminalPageTab.dateFromUrlOrNow).toISODateOnly}/${p.props.terminalPageTab.subMode}")) - } .build def updatedShiftAssignments( diff --git a/client/src/main/scala/drt/client/components/PortConfigPage.scala b/client/src/main/scala/drt/client/components/PortConfigPage.scala index d85f6afd11..19fb214bf6 100644 --- a/client/src/main/scala/drt/client/components/PortConfigPage.scala +++ b/client/src/main/scala/drt/client/components/PortConfigPage.scala @@ -60,37 +60,11 @@ object PortConfigPage { ) mp.render(identity) } - .componentDidMount { p => - Callback(SetDocumentTitle("Port Config", p.props.airportConfig)) >> - Callback(GoogleEventTracker.sendPageView(s"port-config")) - } .build def apply(props: Props): VdomElement = component(props) } -object SetDocumentTitle { - def apply(pageName: String, airportConfigPot: Pot[AirportConfig]): Unit = { - document.title = airportConfigPot match { - case Ready(airportConfig) => constructTitle(pageName, airportConfig.portCode, airportConfig.portName, None) - case _ => "Loading..." - } - } - - def apply(pageName: String, airportConfig: AirportConfig): Unit = { - document.title = constructTitle(pageName, airportConfig.portCode, airportConfig.portName, None) - } - - def apply(pageName: String, terminal: Terminal, airportConfig: AirportConfig): Unit = { - document.title = constructTitle(pageName, airportConfig.portCode, airportConfig.portName, Option(terminal)) - } - - private def constructTitle(pageName: String, portCode: PortCode, portName: String, maybeTerminal: Option[Terminal]): String = { - val terminal = maybeTerminal.map(t => s", Terminal ${t.toString}").getOrElse("") - s"$pageName at ${portCode.iata} ($portName)$terminal - DRT" - } -} - object PortConfigDetails { case class Props(airportConfig: AirportConfig, gateStandWalktime: WalkTimes, updatesByTerminal: Map[Terminal, EgateBanksUpdates]) extends UseValueEq diff --git a/client/src/main/scala/drt/client/components/PortDashboardPage.scala b/client/src/main/scala/drt/client/components/PortDashboardPage.scala index cfd0f4a551..5b368d139f 100644 --- a/client/src/main/scala/drt/client/components/PortDashboardPage.scala +++ b/client/src/main/scala/drt/client/components/PortDashboardPage.scala @@ -117,13 +117,6 @@ object PortDashboardPage { })) } }) - .componentWillReceiveProps(p => Callback { - GoogleEventTracker.sendPageView(s"dashboard${p.nextProps.dashboardPage.period.map(period => s"/$period").getOrElse("")}") - }) - .componentDidMount { p => - Callback(SetDocumentTitle("Dashboard", p.props.airportConfig)) >> - Callback(GoogleEventTracker.sendPageView(s"dashboard${p.props.dashboardPage.period.map(period => s"/$period").getOrElse("")}")) - } .build def apply(router: RouterCtl[Loc], dashboardPage: PortDashboardLoc = PortDashboardLoc(None), airportConfig: Pot[AirportConfig]): VdomElement = component(Props(router, dashboardPage, airportConfig)) diff --git a/client/src/main/scala/drt/client/components/PortExportDashboardPage.scala b/client/src/main/scala/drt/client/components/PortExportDashboardPage.scala index a8e4b161af..08ae83b4a2 100644 --- a/client/src/main/scala/drt/client/components/PortExportDashboardPage.scala +++ b/client/src/main/scala/drt/client/components/PortExportDashboardPage.scala @@ -27,9 +27,6 @@ object PortExportDashboardPage { })) }) }) - .componentDidMount(_ => Callback { - GoogleEventTracker.sendPageView(s"dashboard") - }) .build def apply(loggedInUser: LoggedInUser): VdomElement = component(Props(loggedInUser)) diff --git a/client/src/main/scala/drt/client/components/TerminalComponent.scala b/client/src/main/scala/drt/client/components/TerminalComponent.scala index 1c9af176d8..295f87de8d 100644 --- a/client/src/main/scala/drt/client/components/TerminalComponent.scala +++ b/client/src/main/scala/drt/client/components/TerminalComponent.scala @@ -267,51 +267,32 @@ object TerminalComponent { <.ul(^.className := "nav nav-tabs", <.li(^.className := tabClass(Current) + " " + timeMachineClass, - <.a(^.id := "currentTab", "Queues & Arrivals", VdomAttr("data-toggle") := "tab"), - ^.onClick ==> { e: ReactEventFromInput => - e.preventDefault() - GoogleEventTracker.sendEvent(terminalName, "click", "Queues & Arrivals") - props.router.set(props.terminalPageTab.update( - mode = Current, - subMode = subMode, - queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), viewTypeQueryParam).queryParams - )) - }), + props.router.link(props.terminalPageTab.update( + mode = Current, + subMode = subMode, + queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), viewTypeQueryParam).queryParams + ))(^.id := "currentTab", "Queues & Arrivals", VdomAttr("data-toggle") := "tab")), <.li(^.className := tabClass(Planning), - <.a(^.id := "planning-tab", VdomAttr("data-toggle") := "tab", "Planning"), - ^.onClick ==> { e: ReactEventFromInput => - e.preventDefault() - GoogleEventTracker.sendEvent(terminalName, "click", "Planning") - props.router.set(props.terminalPageTab.update( - mode = Planning, - subMode = subMode, - queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams - )) - } + props.router.link(props.terminalPageTab.update( + mode = Planning, + subMode = subMode, + queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams + ))(^.id := "planning-tab", VdomAttr("data-toggle") := "tab", "Planning"), ), if (loggedInUser.roles.contains(StaffEdit)) <.li(^.className := tabClass(Staffing), - <.a(^.id := "monthlyStaffingTab", ^.className := "flex-forizontally", VdomAttr("data-toggle") := "tab", "Monthly Staffing", " ", monthlyStaffingTooltip), - ^.onClick ==> { e: ReactEventFromInput => - e.preventDefault() - GoogleEventTracker.sendEvent(terminalName, "click", "Monthly Staffing") - props.router.set(props.terminalPageTab.update( - mode = Staffing, - subMode = "15", - queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams - )) - } + props.router.link(props.terminalPageTab.update( + mode = Staffing, + subMode = "15", + queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams + ))(^.id := "monthlyStaffingTab", ^.className := "flex-forizontally", VdomAttr("data-toggle") := "tab", "Monthly Staffing", " ", monthlyStaffingTooltip) ) else "", <.li(^.className := tabClass(Dashboard), - <.a(^.id := "terminalDashboardTab", VdomAttr("data-toggle") := "tab", s"$terminalName Dashboard"), ^.onClick --> { - GoogleEventTracker.sendEvent(terminalName, "click", "Terminal Dashboard") - props.router.set( - props.terminalPageTab.update( - mode = Dashboard, - subMode = "summary", - queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams) - ) - } + props.router.link(props.terminalPageTab.update( + mode = Dashboard, + subMode = "summary", + queryParams = props.terminalPageTab.withUrlParameters(UrlDateParameter(None), UrlTimeMachineDateParameter(None)).queryParams + ))(^.id := "terminalDashboardTab", VdomAttr("data-toggle") := "tab", s"$terminalName Dashboard") ) ) } diff --git a/client/src/main/scala/drt/client/components/TerminalContentComponent.scala b/client/src/main/scala/drt/client/components/TerminalContentComponent.scala index 15fc63fbb4..e8b6068efe 100644 --- a/client/src/main/scala/drt/client/components/TerminalContentComponent.scala +++ b/client/src/main/scala/drt/client/components/TerminalContentComponent.scala @@ -107,30 +107,37 @@ object TerminalContentComponent { <.div(^.className := "tabs-with-export", <.ul(^.className := "nav nav-tabs", <.li(^.className := arrivalsActive, - <.a(^.id := "arrivalsTab", VdomAttr("data-toggle") := "tab", "Arrivals"), ^.onClick --> { - GoogleEventTracker.sendEvent(terminalName, "Arrivals", props.terminalPageTab.dateFromUrlOrNow.toISODateOnly) - props.router.set(props.terminalPageTab.copy(subMode = "arrivals")) - }), + props.router.link(props.terminalPageTab.copy(subMode = "arrivals"))( + ^.id := "arrivalsTab", VdomAttr("data-toggle") := "tab", "Arrivals") + ), <.li(^.className := desksAndQueuesActive, - <.a(^.className := "flexed-anchor", ^.id := "desksAndQueuesTab", VdomAttr("data-toggle") := "tab", "Desks & Queues"), ^.onClick --> { - GoogleEventTracker.sendEvent(terminalName, "Desks & Queues", props.terminalPageTab.dateFromUrlOrNow.toISODateOnly) - props.router.set(props.terminalPageTab.copy( - subMode = "desksAndQueues", - queryParams = props.terminalPageTab.queryParams.updated("viewType", props.defaultDesksAndQueuesViewType) - )) - }), + props.router.link(props.terminalPageTab.copy( + subMode = "desksAndQueues", + queryParams = props.terminalPageTab.queryParams.updated("viewType", props.defaultDesksAndQueuesViewType) + ))( + ^.className := "flexed-anchor", + ^.id := "desksAndQueuesTab", + VdomAttr("data-toggle") := "tab", + "Desks & Queues" + ) + ), <.li(^.className := staffingActive, - <.a(^.className := "flexed-anchor", ^.id := "staffMovementsTab", VdomAttr("data-toggle") := "tab", "Staff Movements", staffMovementsTabTooltip), - ^.onClick --> { - GoogleEventTracker.sendEvent(terminalName, "Staff Movements", props.terminalPageTab.dateFromUrlOrNow.toISODateOnly) - props.router.set(props.terminalPageTab.copy(subMode = "staffing")) - }), + props.router.link(props.terminalPageTab.copy(subMode = "staffing"))( + ^.className := "flexed-anchor", + ^.id := "staffMovementsTab", + VdomAttr("data-toggle") := "tab", + "Staff Movements", + staffMovementsTabTooltip) + ), displayForRole( <.li(^.className := simulationsActive, - <.a(^.className := "flexed-anchor", ^.id := "simulationDayTab", VdomAttr("data-toggle") := "tab", "Simulate Day"), ^.onClick --> { - GoogleEventTracker.sendEvent(terminalName, "Simulate Day", props.terminalPageTab.dateFromUrlOrNow.toISODateOnly) - props.router.set(props.terminalPageTab.copy(subMode = "simulations")) - }), + props.router.link(props.terminalPageTab.copy(subMode = "simulations"))( + ^.className := "flexed-anchor", + ^.id := "simulationDayTab", + VdomAttr("data-toggle") := "tab", + "Simulate Day" + ) + ), ArrivalSimulationUpload, props.loggedInUser ) ), @@ -303,16 +310,6 @@ object TerminalContentComponent { val component: Component[Props, State, Backend, CtorType.Props] = ScalaComponent.builder[Props]("TerminalContentComponent") .initialStateFromProps(p => State(p.terminalPageTab.subMode)) .renderBackend[TerminalContentComponent.Backend] - .componentDidMount { p => - Callback { - val hours = p.props.defaultTimeRangeHours - val page = s"${p.props.terminalPageTab.terminal}/${p.props.terminalPageTab.mode}/${p.props.terminalPageTab.subMode}" - val pageWithTime = s"$page/${hours.start}/${hours.end}" - val pageWithDate = p.props.terminalPageTab.maybeViewDate - .map(s => s"$page/$s/${hours.start}/${hours.end}").getOrElse(pageWithTime) - GoogleEventTracker.sendPageView(pageWithDate) - } - } .build def apply(props: Props): VdomElement = component(props) diff --git a/client/src/main/scala/drt/client/components/TerminalDashboardComponent.scala b/client/src/main/scala/drt/client/components/TerminalDashboardComponent.scala index aa77ea5c81..daeff8f190 100644 --- a/client/src/main/scala/drt/client/components/TerminalDashboardComponent.scala +++ b/client/src/main/scala/drt/client/components/TerminalDashboardComponent.scala @@ -189,10 +189,6 @@ object TerminalDashboardComponent { } <.div(pot.render(identity)) } - .componentDidMount { p => - Callback(SetDocumentTitle("Terminal Dashboard", p.props.terminalPageTabLoc.terminal, p.props.airportConfig)) >> - Callback(GoogleEventTracker.sendPageView(page = s"terminal-dashboard-${p.props.terminalPageTabLoc.terminal}")) - } .build private def cmsForTerminalAndQueue(crunchMinutes: SortedMap[TQM, CrunchMinute], queue: Queue, terminal: Terminal): Iterable[CrunchMinute] = diff --git a/client/src/main/scala/drt/client/components/TerminalDesksAndQueues.scala b/client/src/main/scala/drt/client/components/TerminalDesksAndQueues.scala index a59ad357f4..37fd6531e4 100644 --- a/client/src/main/scala/drt/client/components/TerminalDesksAndQueues.scala +++ b/client/src/main/scala/drt/client/components/TerminalDesksAndQueues.scala @@ -299,10 +299,7 @@ object TerminalDesksAndQueues { showWaitColumn = !p.featureFlags.displayWaitTimesToggle) } .renderBackend[Backend] - .componentDidMount { p => - Callback(SetDocumentTitle("Desks and Queues", p.props.terminal, p.props.airportConfig)) >> - StickyTableHeader("[data-sticky]") - } + .componentDidMount(_ => StickyTableHeader("[data-sticky]")) .build def documentScrollTop: Double = Math.max(dom.document.documentElement.scrollTop, dom.document.body.scrollTop) diff --git a/client/src/main/scala/drt/client/components/TerminalPlanningComponent.scala b/client/src/main/scala/drt/client/components/TerminalPlanningComponent.scala index adfd7f335f..38c2f631bb 100644 --- a/client/src/main/scala/drt/client/components/TerminalPlanningComponent.scala +++ b/client/src/main/scala/drt/client/components/TerminalPlanningComponent.scala @@ -205,9 +205,7 @@ object TerminalPlanningComponent { } .configure(Reusability.shouldComponentUpdate) .componentDidMount { p => - Callback(SetDocumentTitle("Staff Planning", p.props.page.terminal, p.props.airportConfig)) >> - Callback(SPACircuit.dispatch(GetForecastWeek(p.props.page.dateFromUrlOrNow, Terminal(p.props.page.terminalName), p.props.timePeriod))) >> - Callback(GoogleEventTracker.sendPageView(s"${p.props.page.terminal}/planning/${defaultStartDate(p.props.page.dateFromUrlOrNow).toISODateOnly}")) + Callback(SPACircuit.dispatch(GetForecastWeek(p.props.page.dateFromUrlOrNow, Terminal(p.props.page.terminalName), p.props.timePeriod))) } .build diff --git a/client/src/main/scala/drt/client/components/TerminalStaffing.scala b/client/src/main/scala/drt/client/components/TerminalStaffing.scala index 663d861939..4d1ca2f34f 100644 --- a/client/src/main/scala/drt/client/components/TerminalStaffing.scala +++ b/client/src/main/scala/drt/client/components/TerminalStaffing.scala @@ -211,9 +211,6 @@ object TerminalStaffing { private val component = ScalaComponent.builder[Props]("TerminalStaffing") .renderBackend[Backend] - .componentDidMount { p => - Callback(SetDocumentTitle("Desks and Queues", p.props.terminal, p.props.airportConfig)) - } .build private object MovementDisplay { diff --git a/client/src/main/scala/drt/client/components/TrainingHubComponent.scala b/client/src/main/scala/drt/client/components/TrainingHubComponent.scala index 8951b0fc48..996faf6a0e 100644 --- a/client/src/main/scala/drt/client/components/TrainingHubComponent.scala +++ b/client/src/main/scala/drt/client/components/TrainingHubComponent.scala @@ -4,7 +4,6 @@ import diode.data.Pot import diode.{FastEqLowPri, UseValueEq} import drt.client.SPAMain._ import drt.client.logger.{Logger, LoggerFactory} -import drt.client.modules.GoogleEventTracker import drt.client.services._ import drt.client.spa.TrainingHubPageMode import drt.client.spa.TrainingHubPageModes.{DropInBooking, TrainingMaterial} @@ -12,7 +11,7 @@ import drt.shared.{DropIn, DropInRegistration} import japgolly.scalajs.react.component.Scala.Component import japgolly.scalajs.react.extra.router.RouterCtl import japgolly.scalajs.react.vdom.html_<^._ -import japgolly.scalajs.react.{Callback, CtorType, ReactEventFromInput, Reusability, ScalaComponent} +import japgolly.scalajs.react.{CtorType, Reusability, ScalaComponent} import org.scalajs.dom.html.UList import uk.gov.homeoffice.drt.auth.LoggedInUser import uk.gov.homeoffice.drt.ports.AirportConfig @@ -67,39 +66,24 @@ object TrainingHubComponent { )) } .configure(Reusability.shouldComponentUpdate) - .componentDidMount { p => - Callback(SetDocumentTitle("Training Hub", p.props.airportConfigPot)) - } .build private def trainingTabs(props: Props): VdomTagOf[UList] = { - val trainingName = props.trainingHubLoc.modeStr - def tabClass(mode: TrainingHubPageMode): String = if (props.trainingHubLoc.modeStr == mode.asString) activeClass else "" <.ul(^.className := "nav nav-tabs", <.li(^.className := tabClass(DropInBooking), - <.a(^.id := "dropInBooking", "Book a Drop-in Session", VdomAttr("data-toggle") := "tab"), - ^.onClick ==> { e: ReactEventFromInput => - e.preventDefault() - GoogleEventTracker.sendEvent(trainingName, "click", "Book a Drop-in Session") - props.router.set(props.trainingHubLoc.copy( - modeStr = DropInBooking.asString - )) - } + props.router.link(props.trainingHubLoc.copy(modeStr = DropInBooking.asString))( + ^.id := "dropInBooking", "Book a Drop-in Session", VdomAttr("data-toggle") := "tab" + ) ), <.li(^.className := tabClass(TrainingMaterial), - <.a(^.id := "trainingMaterial", "Training Material", VdomAttr("data-toggle") := "tab"), - ^.onClick ==> { e: ReactEventFromInput => - e.preventDefault() - GoogleEventTracker.sendEvent(trainingName, "click", "Training Material") - props.router.set(props.trainingHubLoc.copy( - modeStr = TrainingMaterial.asString - )) - }) + props.router.link(props.trainingHubLoc.copy(modeStr = TrainingMaterial.asString))( + ^.id := "trainingMaterial", "Training Material", VdomAttr("data-toggle") := "tab" + ) + ) ) } def apply(props: Props): VdomElement = component(props) - } diff --git a/client/src/main/scala/drt/client/components/TrainingMaterialComponent.scala b/client/src/main/scala/drt/client/components/TrainingMaterialComponent.scala index 9487bd4f04..bfc311e801 100644 --- a/client/src/main/scala/drt/client/components/TrainingMaterialComponent.scala +++ b/client/src/main/scala/drt/client/components/TrainingMaterialComponent.scala @@ -13,9 +13,6 @@ object TrainingMaterialComponent { .render_P(_ => <.div(^.className := "training-material", <.h3("Training Material"), TrainingMaterialDetailComponent()) ) - .componentDidMount(_ => Callback { - GoogleEventTracker.sendPageView(s"Training Material") - }) .build def apply(): VdomElement = component(Props()) diff --git a/client/src/main/scala/drt/client/components/UserDashboardPage.scala b/client/src/main/scala/drt/client/components/UserDashboardPage.scala index a02ef6c2bc..9499a797c1 100644 --- a/client/src/main/scala/drt/client/components/UserDashboardPage.scala +++ b/client/src/main/scala/drt/client/components/UserDashboardPage.scala @@ -31,9 +31,6 @@ object UserDashboardPage { } }) - .componentDidMount(_ => Callback { - GoogleEventTracker.sendPageView(s"dashboard") - }) .build def apply(router: RouterCtl[Loc]): VdomElement = component(Props(router)) diff --git a/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationComponent.scala b/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationComponent.scala index 19e439a246..12fe2af309 100644 --- a/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationComponent.scala +++ b/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationComponent.scala @@ -2,9 +2,7 @@ package drt.client.components.scenarios import diode.UseValueEq import diode.data.Pot -import drt.client.components.SetDocumentTitle import drt.client.components.styles.DefaultFormFieldsStyle -import drt.client.modules.GoogleEventTracker import drt.shared.SimulationResult import io.kinoplan.scalajs.react.material.ui.core._ import japgolly.scalajs.react._ @@ -61,10 +59,6 @@ object ScenarioSimulationComponent extends ScalaCssReactImplicits { State(SimulationFormFields(p.terminal, p.date, p.airportConfig, p.slaConfigs), Map()) ) .renderBackend[Backend] - .componentDidMount { p => - Callback(SetDocumentTitle("Simulate Day", p.props.terminal, p.props.airportConfig)) >> - Callback(GoogleEventTracker.sendPageView(s"Arrival Simulations Page")) - } .build def apply(props: Props): VdomElement = component(props) diff --git a/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationFormComponent.scala b/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationFormComponent.scala index 95a3096ab9..e65fdb01c4 100644 --- a/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationFormComponent.scala +++ b/client/src/main/scala/drt/client/components/scenarios/ScenarioSimulationFormComponent.scala @@ -302,7 +302,6 @@ object ScenarioSimulationFormComponent extends ScalaCssReactImplicits { ) ) } - .componentDidMount(_ => Callback(GoogleEventTracker.sendPageView(s"Arrival Simulations Page"))) .build private def submitButton(showCharts: Callback, form: SimulationFormFields): WithPropsAndTagsMods = { diff --git a/client/src/main/scala/drt/client/modules/GoogleAnalytics.scala b/client/src/main/scala/drt/client/modules/GoogleAnalytics.scala index 8a63b07535..169ee16c28 100644 --- a/client/src/main/scala/drt/client/modules/GoogleAnalytics.scala +++ b/client/src/main/scala/drt/client/modules/GoogleAnalytics.scala @@ -4,54 +4,31 @@ import org.scalajs.dom import scala.scalajs.js import scala.scalajs.js.annotation.JSGlobalScope -import scala.util.Try -import com.dedipresta.crypto.hash.sha256.Sha256 object GoogleEventTracker { - - @js.native - @JSGlobalScope - object Globals extends js.Object { - var gtag: js.Any = js.native - } - def trackingCode: String = dom.document.getElementById("ga-code").getAttribute("value") def port: String = dom.document.getElementById("port-code").getAttribute("value") - def userId: String = dom.document.getElementById("user-id").getAttribute("value") - - def isScriptLoaded: Boolean = Try(Globals.gtag.isInstanceOf[js.Function]).isSuccess - - private var hasCreateTrackerRun = false - - private def runCreateTracker(): Unit = { - if (!hasCreateTrackerRun && userId.nonEmpty && port.nonEmpty && trackingCode.nonEmpty) { - val userUUID = Sha256.hashString(userId) - GoogleAnalytics.gtag("config", trackingCode, js.Dictionary("user_id" -> userUUID, "anonymize_ip" -> true)) - hasCreateTrackerRun = true - } - } - - def sendPageView(page: String): Unit = { - if (isScriptLoaded) { - runCreateTracker() - if (hasCreateTrackerRun) { - GoogleAnalytics.gtag("event", "page_view", js.Dictionary("page" -> s"/$port/$page")) + def sendPageView(title: String, url: String): Unit = { + if (trackingCode.nonEmpty) { + GoogleAnalytics.gtag("event", "page_view", js.Dictionary( + "page_title" -> title, + "page_location" -> url, + )) } - } } def sendEvent(category: String, action: String, label: String): Unit = { - if (isScriptLoaded && hasCreateTrackerRun) GoogleAnalytics.gtag("event", s"${port}_$category", js.Dictionary("action" -> action, "label" -> label)) + if (trackingCode.nonEmpty) GoogleAnalytics.gtag("event", s"${port}_$category", js.Dictionary("action" -> action, "label" -> label)) } def sendEvent(category: String, action: String, label: String, value: String): Unit = { - if (isScriptLoaded && hasCreateTrackerRun) GoogleAnalytics.gtag("event", s"${port}_$category", js.Dictionary("action" -> action, "label" -> label, "value" -> value)) + if (trackingCode.nonEmpty) GoogleAnalytics.gtag("event", s"${port}_$category", js.Dictionary("action" -> action, "label" -> label, "value" -> value)) } def sendError(description: String, fatal: Boolean): Unit = { - if (isScriptLoaded && hasCreateTrackerRun) GoogleAnalytics.gtag("event", "exception", js.Dictionary("exDescription" -> description, "exFatal" -> fatal)) + if (trackingCode.nonEmpty) GoogleAnalytics.gtag("event", "exception", js.Dictionary("exDescription" -> description, "exFatal" -> fatal)) } } diff --git a/server/src/main/twirl/views/index.scala.html b/server/src/main/twirl/views/index.scala.html index 251ddbd620..071e535763 100644 --- a/server/src/main/twirl/views/index.scala.html +++ b/server/src/main/twirl/views/index.scala.html @@ -16,13 +16,16 @@ } diff --git a/shared/src/main/scala/drt/shared/HasAirportConfig.scala b/shared/src/main/scala/drt/shared/HasAirportConfig.scala index d1ac2172cb..643d43e57a 100644 --- a/shared/src/main/scala/drt/shared/HasAirportConfig.scala +++ b/shared/src/main/scala/drt/shared/HasAirportConfig.scala @@ -21,13 +21,10 @@ object DrtPortConfigs { import uk.gov.homeoffice.drt.ports.config._ - val testPorts: List[AirportConfigLike] = List(Test, Test2) - val allPorts: List[AirportConfigLike] = AirportConfigs.allPorts ::: testPorts + private val testPorts: List[AirportConfigLike] = List(Test, Test2) + private val allPorts: List[AirportConfigLike] = AirportConfigs.allPorts ::: testPorts - val allPortConfigs: List[AirportConfig] = allPorts.map(_.config) - val testPortConfigs: List[AirportConfig] = testPorts.map(_.config) - - def portGroups: List[String] = allPortConfigs.filterNot(testPorts.contains).map(_.portCode.toString.toUpperCase).sorted + private val allPortConfigs: List[AirportConfig] = allPorts.map(_.config) val confByPort: Map[PortCode, AirportConfig] = allPortConfigs.map(c => (c.portCode, c)).toMap }