Skip to content

Commit

Permalink
pregame page UI WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
greg2010 committed Feb 25, 2021
1 parent a5b73c9 commit c73f178
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@ import java.net.URLDecoder
import java.util.UUID


object LogicEndpoints extends Endpoints {
object LogicEndpoints {
// TODO: do something about this mess

type Env = Has[CurrentGameModule] with Has[PregameModule]
val currentGameByNameImpl = this.currentGameByName.zServerLogic { case (platform, name, fetchGroups, requestId) =>
val fetchGroupsDefault = fetchGroups.getOrElse(false)
val decodedName = URLDecoder.decode(name, "UTF-8")
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)

(for {
game <- CurrentGameModule.getCurrentGame(platform, decodedName)
uuidAdded <-
if (fetchGroupsDefault)
CurrentGameModule.getGroupsForGameAsync(platform, game).map(u => game.copy(groupUuid = Some(u)))
else IO.succeed(game)
val currentGameByNameImpl = Endpoints.currentGameByName
.zServerLogic { case (platform, name, fetchGroups, requestId) =>
val fetchGroupsDefault = fetchGroups.getOrElse(false)
val decodedName = URLDecoder.decode(name, "UTF-8")
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)

(for {
game <- CurrentGameModule.getCurrentGame(platform, decodedName)
uuidAdded <-
if (fetchGroupsDefault)
CurrentGameModule.getGroupsForGameAsync(platform, game).map(u => game.copy(groupUuid = Some(u)))
else IO.succeed(game)
} yield uuidAdded).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val currentGameGroupsByNameImpl = this.currentGameGroupsByName.zServerLogic { case (platform, name, requestId) =>
val currentGameGroupsByNameImpl = Endpoints.currentGameGroupsByName.zServerLogic { case (platform, name, requestId) =>
val decodedName = URLDecoder.decode(name, "UTF-8")
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)

Expand All @@ -39,38 +40,38 @@ object LogicEndpoints extends Endpoints {
} yield groups).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val currentGameGroupsByUUIDImpl = this.currentGameGroupsByUUID.zServerLogic { case (uuid, requestId) =>
val currentGameGroupsByUUIDImpl = Endpoints.currentGameGroupsByUUID.zServerLogic { case (uuid, requestId) =>
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)

(for {
gg <- CurrentGameModule.getGroupsByUUID(uuid)
} yield gg).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val pregameByNameImpl = this.pregameByName.zServerLogic { case (platform, names, fetchGroups, requestId) =>
val pregameByNameImpl = Endpoints.pregameByName.zServerLogic { case (platform, names, fetchGroups, requestId) =>
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)
(for {
pg <- PregameModule.getPregameLobby(platform, names)
} yield PregameResponse(pg, None)).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val pregameGroupsByNameImpl = this.pregameGroupsByName.zServerLogic { case (platform, names, requestId) =>
val pregameGroupsByNameImpl = Endpoints.pregameGroupsByName.zServerLogic { case (platform, names, requestId) =>
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)
(for {
pg <- PregameModule.getPregameLobby(platform, names)
groups <- PregameModule.getGroupsForPregame(platform, pg)
} yield groups).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val pregameGroupsByUUIDImpl = this.pregameGameGroupsByUUID.zServerLogic { case (uuid, requestId) =>
val pregameGroupsByUUIDImpl = Endpoints.pregameGameGroupsByUUID.zServerLogic { case (uuid, requestId) =>
implicit val getReqId: String = requestId.fold(UUID.randomUUID().toString)(identity)

(for {
gg <- PregameModule.getGroupsByUUID(uuid)
} yield gg).resurrect.flatMapError(ErrorHandler.defaultErrorHandler)
}

val healthzImpl = this.healthz.zServerLogic { _ =>
val healthzImpl = Endpoints.healthz.zServerLogic { _ =>
UIO.succeed("Ok")
}

Expand Down
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ lazy val dependencies = new {
val js = Def.setting(common.value ++ Seq(
"com.raquo" %%% "laminar" % laminarVersion,
"com.raquo" %%% "airstream" % airstreamVersion,
"com.raquo" %%% "waypoint" % "0.2.0"
"com.raquo" %%% "waypoint" % "0.2.0",
"com.softwaremill.sttp.tapir" %%% "tapir-sttp-client" % tapirVersion
))
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import sttp.model.StatusCode

import java.util.UUID

trait Endpoints {
object Endpoints {
private implicit val schemaForPlatform: Schema[Platform] = Schema.string
private implicit val schemaForGQTE : Schema[GameQueueTypeEnum] = Schema.string
private implicit val schemaForPE : Schema[PositionEnum] = Schema.string
Expand Down
38 changes: 26 additions & 12 deletions frontend/src/main/scala/org/kys/athena/App.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,41 @@ import org.kys.athena.util.CSSUtil
import org.kys.athena.components.LandingPage
import org.kys.athena.components.common.{AppBar, Footer}
import org.kys.athena.components.ongoing.OngoingPage
import org.kys.athena.components.pregame.PregamePage
import org.scalajs.dom
import urldsl.errors.DummyError
import urldsl.vocabulary.{FromString, Printer}
import urldsl.vocabulary.{FromString, Printer, UrlMatching}


object App {
implicit val fs = new FromString[Platform, DummyError] {
override def fromString(str: String): Either[DummyError, Platform] = {
Platform.withNameEither(str).left.map(_ => DummyError.dummyError)
}
}
implicit val pr = new Printer[Platform] {
override def print(t: Platform): String = t.entryName
}

implicit val ls = new FromString[List[String], DummyError] {
override def fromString(str: String): Either[DummyError, List[String]] = Right(str.split(',').toList)
}

implicit val sl = new Printer[List[String]] {
override def print(t: List[String]) = t.mkString(",")
}

private val routes: List[Route[_ <: PageRoute, _]] = List(
Route.static(LandingRoute, root / endOfSegments),
Route.withQuery[PregameRoute, Platform, List[String]](
encode = p => UrlMatching(p.realm, p.names),
decode = a => PregameRoute(a.path, a.params),
pattern = (root / segment[Platform] / "pregame" / endOfSegments) ?
(param[List[String]]("summoners"))),
Route[OngoingRoute, (Platform, String)](
encode = p => (p.realm, p.name),
decode = a => OngoingRoute(a._1, a._2),
pattern = {
implicit val fs = new FromString[Platform, DummyError] {
override def fromString(str: String): Either[DummyError, Platform] = {
Platform.withNameEither(str).left.map(_ => DummyError.dummyError)
}
}
implicit val pr = new Printer[Platform] {
override def print(t: Platform): String = t.entryName
}
root / segment[Platform] / segment[String] / endOfSegments
})
pattern = root / segment[Platform] / segment[String] / endOfSegments)
)

private val router = new Router[PageRoute](
Expand All @@ -58,6 +70,8 @@ object App {
LandingPage.render(windowEvents.onMouseMove)
}.collect[OngoingRoute] { page =>
OngoingPage.render(page, hideSearchBar.writer)
}.collect[PregameRoute] { page =>
PregamePage.render(page)
}

def render(): HtmlElement = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package org.kys.athena.components.common
import com.raquo.laminar.api.L._
import org.kys.athena.App
import org.kys.athena.riot.api.dto.common.Platform
import org.kys.athena.routes.OngoingRoute
import org.kys.athena.routes.{OngoingRoute, PregameRoute}
import org.kys.athena.util.assets.AssetLoader
import org.scalajs.dom
import org.scalajs.dom.Event
Expand All @@ -19,7 +19,14 @@ object SearchBar {
Observer[dom.Event](onNext = _ => {
(platform.now(), summoner.now()) match {
case (_, "") => ()
case (p, s) => App.pushState(OngoingRoute(p, s))
case (p, s) => {
val sums = s.split(',').toList
if (sums.length > 1) {
App.pushState(PregameRoute(p, sums))
} else {
App.pushState(OngoingRoute(p, s))
}
}
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package org.kys.athena.components.ongoing
import com.raquo.domtypes.generic.keys.{Style => CStyle}
import com.raquo.laminar.api.L._
import com.raquo.laminar.nodes.ReactiveHtmlElement
import org.kys.athena.http.Client._
import org.kys.athena.http.BackendClient._
import org.kys.athena.http.backend.BackendDataHelpers
import org.kys.athena.http.dd.CombinedDD
import org.kys.athena.http.errors.{BackendApiError, InternalServerError, NotFoundError}
import org.kys.athena.http.models.current._
import org.kys.athena.http.models.premade.{PlayerGroup, PremadeResponse}
import org.kys.athena.components.common
import org.kys.athena.components.common.{ChampionIcon, ImgSized, OpggLink, UggLink}
import org.kys.athena.http.DDClient
import org.kys.athena.routes.OngoingRoute
import org.kys.athena.riot.api.dto.common.{GameQueueTypeEnum, Platform}
import org.kys.athena.riot.api.dto.currentgameinfo.BannedChampion
Expand All @@ -33,7 +34,9 @@ object OngoingPage {
def fetchAndWriteDDragon(ddObs: Observer[DataState[CombinedDD]]): IO[BackendApiError, Unit] = {
for {
dd <- {
ZIO.tupledPar(fetchCachedDDragonChampion(), fetchCachedDDragonRunes(), fetchCachedDDragonSummoners())
ZIO.tupledPar(DDClient.fetchCachedDDragonChampion(),
DDClient.fetchCachedDDragonRunes(),
DDClient.fetchCachedDDragonSummoners())
.either.map {
case Left(ex) => Failed(ex)
case Right((c, r, s)) => Ready(CombinedDD(c, r, s))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.kys.athena.components.pregame

import com.raquo.laminar.api.L._
import org.kys.athena.http.BackendClient.{fetchPregameGameByName, fetchPregameGroupsByName, fetchPregameGroupsByUUID}
import org.kys.athena.http.DDClient
import org.kys.athena.http.dd.CombinedDD
import org.kys.athena.http.errors.{BackendApiError, InternalServerError}
import org.kys.athena.http.models.pregame.PregameResponse
import org.kys.athena.http.models.premade.PlayerGroup
import org.kys.athena.riot.api.dto.common.Platform
import org.kys.athena.routes.PregameRoute
import org.kys.athena.util.CSSUtil.{paletteContainer, paperCls}
import org.kys.athena.util.{DataState, Failed, Loading, Ready}
import zio.{IO, Runtime, UIO, ZIO}


object PregamePage {
@SuppressWarnings(Array("org.wartremover.warts.Product", "org.wartremover.warts.Serializable"))
def fetchAndWriteDDragon(ddObs: Observer[DataState[CombinedDD]]): IO[BackendApiError, Unit] = {
for {
dd <- {
ZIO.tupledPar(DDClient.fetchCachedDDragonChampion(),
DDClient.fetchCachedDDragonRunes(),
DDClient.fetchCachedDDragonSummoners())
.either.map {
case Left(ex) => Failed(ex)
case Right((c, r, s)) => Ready(CombinedDD(c, r, s))
}
}
_ <- UIO.effectTotal(ddObs.onNext(dd))
} yield ()
}

@SuppressWarnings(Array("org.wartremover.warts.Product", "org.wartremover.warts.Serializable"))
def fetchAndWriteGameInfo(platform: Platform,
names: List[String],
ongoingObs: Observer[DataState[PregameResponse]],
groupsObs: Observer[DataState[Set[PlayerGroup]]]): IO[BackendApiError, Unit] = {
for {
_ <- UIO.succeed(ongoingObs.onNext(Loading))
o <- fetchPregameGameByName(platform, names)
.map(r => Ready(r))
.catchAll(err => UIO.succeed(Failed(err)))
_ <- UIO.effectTotal(ongoingObs.onNext(o))

gr <- (o match {
case Failed(_) => IO.fail(InternalServerError("Fetch for players failed, not fetching groups"))
case _ => {
o.map(_.groupUuid).toOption.flatten
.fold(fetchPregameGroupsByName(platform, names))(uuid => fetchPregameGroupsByUUID(uuid))
}
}).map(r => Ready(r))
.catchAll(err => UIO.succeed(Failed(err)))
_ <- UIO.effectTotal(groupsObs.onNext(gr))
} yield ()
}


def fetchAndWriteAll(platform: Platform,
names: List[String],
ddObs: Observer[DataState[CombinedDD]],
ongoingObs: Observer[DataState[PregameResponse]],
groupsObs: Observer[DataState[Set[PlayerGroup]]]): IO[BackendApiError, Unit] = {
ZIO.tupledPar(fetchAndWriteDDragon(ddObs), fetchAndWriteGameInfo(platform, names, ongoingObs, groupsObs)).unit
}


def render(p: PregameRoute): HtmlElement = {
lazy val ddVar = Var[DataState[CombinedDD]](Loading)
lazy val pregameVar = Var[DataState[PregameResponse]](Loading)
lazy val groupsVar = Var[DataState[Set[PlayerGroup]]](Loading)

val runtime: Runtime[zio.ZEnv] = Runtime.default

def refreshGame: Unit = {
runtime.unsafeRunAsync_(fetchAndWriteGameInfo(p.realm,
p.names,
pregameVar.writer,
groupsVar.writer))
}
def refreshAll: Unit = {
runtime.unsafeRunAsync_(fetchAndWriteAll(p.realm,
p.names,
ddVar.writer,
pregameVar.writer,
groupsVar.writer))
}

div(
onMountCallback(_ => refreshAll),
cls := s"flex flex-col items-center justify-center lg:px-12 mx-4 my-2 divide-y divide-gray-500 $paperCls",
backgroundColor := paletteContainer,
span(cls := "text-3xl p-2 text-center", s"Pregame lobby of ${p.names.mkString(", ")}"),
div(
cls := s"flex flex-col lg:flex-row items-center justify-center divide-x divide-gray-500",
children <-- pregameVar.signal.map {
case Loading => List(div())
case Ready(data) =>
data.summoners. map { summoner =>
div(
cls := "flex flex-col justify-center items-center",
span(summoner.name),
span(summoner.summonerLevel.toString),
div(
summoner.rankedLeagues.map { rl =>
div(rl.leagueId)
}
)
)
}.toList
}
))
}
}
Loading

0 comments on commit c73f178

Please sign in to comment.