more work on relay

This commit is contained in:
Thibault Duplessis 2017-09-29 13:33:37 -05:00
parent 95acc48450
commit f5b543e27d
9 changed files with 170 additions and 26 deletions

View file

@ -179,7 +179,7 @@ object Study extends LilaController {
}
private def createStudy(data: lila.study.DataForm.Data, me: lila.user.User)(implicit ctx: Context) =
env.api.create(data, me) flatMap {
env.api.create(lila.study.StudyMaker.Data(data), me) flatMap {
_.fold(notFound) { sc =>
Redirect(routes.Study.show(sc.study.id.value)).fuccess
}

View file

@ -1,6 +1,11 @@
@(sel: lila.relay.Relay.Selection)(implicit ctx: Context)
@sublist(relays: List[lila.relay.Relay.WithStudy]) = {
@if(relays.isEmpty) {
<div class="norelays">
<p>None yet.</p>
</div>
} else {
<div class="list">
@relays.map { r =>
<div class="relay">
@ -9,6 +14,7 @@
}
</div>
}
}
@base.layout(
title = "Live tournament broadcasts",

View file

@ -5,9 +5,9 @@
<p>None yet.</p>
</div>
} else {
<div class="list infinitescroll">
<div class="relays infinitescroll">
@pager.currentPageResults.map { s =>
<div class="study paginated_element">
<div class="relay paginated_element">
@widget(s)
</div>
}

25
bin/relay/yarn.lock Normal file
View file

@ -0,0 +1,25 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
fs-extra@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
universalify "^0.1.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
optionalDependencies:
graceful-fs "^4.1.6"
universalify@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"

View file

@ -4,7 +4,7 @@ import org.joda.time.DateTime
import reactivemongo.bson._
import lila.db.dsl._
import lila.study.{ StudyApi, Study }
import lila.study.{ StudyApi, Study, Settings }
import lila.user.User
final class RelayApi(
@ -42,13 +42,20 @@ final class RelayApi(
)).sort($sort asc "startsAt").list[Relay]()
def closed = coll.find($doc(
"closedAt" $exists false
"closedAt" $exists true
)).sort($sort asc "startsAt").list[Relay]()
def create(data: RelayForm.Data, user: User): Fu[Relay] = {
val relay = data make user
coll.insert(relay) >>
studyApi.create(lila.study.DataForm.Data(), user, relay.studyId.some) inject relay
studyApi.create(lila.study.StudyMaker.Data(
id = relay.studyId.some,
name = Study.Name(relay.name).some,
settings = Settings.init.copy(
chat = Settings.UserSelection.Everyone,
sticky = false
).some
), user) inject relay
}
private def withStudy(relays: List[Relay]): Fu[List[Relay.WithStudy]] =

View file

@ -152,20 +152,20 @@ object Study {
def makeId = Id(scala.util.Random.alphanumeric take idSize mkString)
def make(user: User, from: From, forceId: Option[Study.Id] = None) = {
def make(user: User, from: From, id: Option[Study.Id] = None, name: Option[Name] = None, settings: Option[Settings] = None) = {
val owner = StudyMember(
id = user.id,
role = StudyMember.Role.Write,
addedAt = DateTime.now
)
Study(
_id = forceId | makeId,
name = Name(s"${user.username}'s Study"),
_id = id | makeId,
name = name | Name(s"${user.username}'s Study"),
members = StudyMembers(Map(user.id -> owner)),
position = Position.Ref(Chapter.Id(""), Path.root),
ownerId = user.id,
visibility = Visibility.Public,
settings = Settings.init,
settings = settings | Settings.init,
from = from,
likes = Likes(1),
createdAt = DateTime.now,

View file

@ -83,9 +83,9 @@ final class StudyApi(
def studyIdOf = chapterRepo.studyIdOf _
def create(data: DataForm.Data, user: User, forceId: Option[Study.Id] = None): Fu[Option[Study.WithChapter]] = (data.as match {
def create(data: StudyMaker.Data, user: User): Fu[Option[Study.WithChapter]] = (data.form.as match {
case DataForm.AsNewStudy =>
studyMaker(data, user, forceId) flatMap { res =>
studyMaker(data, user) flatMap { res =>
studyRepo.insert(res.study) >>
chapterRepo.insert(res.chapter) >>-
indexStudy(res.study) >>-
@ -100,7 +100,7 @@ final class StudyApi(
_ <- addChapter(
byUserId = user.id,
studyId = study.id,
data = data.toChapterData,
data = data.form.toChapterData,
sticky = study.settings.sticky,
socket = socket,
uid = Uid("") // the user is not in the study yet
@ -108,7 +108,7 @@ final class StudyApi(
made <- byIdWithChapter(studyId)
} yield made
case _ => fuccess(none)
} orElse create(data.copy(asStr = none), user)
} orElse create(data.copy(form = data.form.copy(asStr = none)), user)
}) addEffect {
_ ?? { sc =>
bus.publish(actorApi.StartStudy(sc.study.id), 'startStudy)

View file

@ -10,21 +10,21 @@ private final class StudyMaker(
chapterMaker: ChapterMaker
) {
def apply(data: DataForm.Data, user: User, forceId: Option[Study.Id] = None): Fu[Study.WithChapter] =
(data.gameId ?? GameRepo.gameWithInitialFen).flatMap {
case Some((game, initialFen)) => createFromPov(Pov(game, data.orientation), initialFen, user, forceId)
case None => createFromScratch(data, user, forceId)
def apply(data: StudyMaker.Data, user: User): Fu[Study.WithChapter] =
(data.form.gameId ?? GameRepo.gameWithInitialFen).flatMap {
case Some((game, initialFen)) => createFromPov(data, Pov(game, data.form.orientation), initialFen, user)
case None => createFromScratch(data, user)
}
private def createFromScratch(data: DataForm.Data, user: User, forceId: Option[Study.Id] = None): Fu[Study.WithChapter] = {
val study = Study.make(user, Study.From.Scratch, forceId)
private def createFromScratch(data: StudyMaker.Data, user: User): Fu[Study.WithChapter] = {
val study = Study.make(user, Study.From.Scratch, data.id, data.name, data.settings)
chapterMaker.fromFenOrPgnOrBlank(study, ChapterMaker.Data(
game = none,
name = Chapter.Name("Chapter 1"),
variant = data.variantStr,
fen = data.fenStr,
pgn = data.pgnStr,
orientation = data.orientation.name,
variant = data.form.variantStr,
fen = data.form.fenStr,
pgn = data.form.pgnStr,
orientation = data.form.orientation.name,
mode = ChapterMaker.Mode.Normal.key,
initial = true
),
@ -34,9 +34,9 @@ private final class StudyMaker(
}
}
private def createFromPov(pov: Pov, initialFen: Option[FEN], user: User, forceId: Option[Study.Id] = None): Fu[Study.WithChapter] =
private def createFromPov(data: StudyMaker.Data, pov: Pov, initialFen: Option[FEN], user: User): Fu[Study.WithChapter] =
chapterMaker.game2root(pov.game, initialFen) map { root =>
val study = Study.make(user, Study.From.Game(pov.game.id), forceId).copy(name = Study.Name("Game study"))
val study = Study.make(user, Study.From.Game(pov.game.id), data.id, Study.Name("Game study").some)
val chapter: Chapter = Chapter.make(
studyId = study.id,
name = Chapter.Name(Namer.gameVsText(pov.game, withRatings = false)(lightUser)),
@ -58,3 +58,13 @@ private final class StudyMaker(
chapterMaker.notifyChat(swc.study, pov.game, user.id)
}
}
object StudyMaker {
case class Data(
form: DataForm.Data = DataForm.Data(),
id: Option[Study.Id] = None,
name: Option[Study.Name] = None,
settings: Option[Settings] = None
)
}

View file

@ -5,3 +5,99 @@
.relay_form textarea.description {
height: 10em;
}
.relays .list {
display: flex;
flex-flow: row wrap;
border-top: 1px solid #ccc;
}
.relays .norelays {
text-align: center;
font-size: 2em;
}
.relays .norelays p {
opacity: 0.6;
}
.relays .relay {
flex: 0 0 50%;
max-width: 50%;
border-bottom: 1px solid #ccc;
box-sizing: border-box;
padding: 10px 10px 20px 10px;
position: relative;
}
body.dark .relays .top .search input,
body.dark .relays .list,
body.dark .relays .relay {
border-color: #3d3d3d;
}
.relays .relay {
border-right: 1px solid #ccc;
}
.relays .relay:hover {
background: rgba(191, 231, 255, 0.5);
}
.relays .relay a.overlay {
position: absolute;
z-index: 2;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.relays .body {
display: flex;
padding-left: 10px;
}
.relays .relay ol.chapters {
flex: 0 0 58%;
max-width: 58%;
}
.relays .relay ol.members {
flex: 0 0 40%;
max-width: 40%;
margin-left: 2%;
}
.relays .relay ol li {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.relays .relay ol li::before {
opacity: 0.5;
}
.relays .relay h2 {
display: block;
position: relative;
box-sizing: border-box;
height: 60px;
padding-left: 64px
}
.relays .relay h2 strong {
font-size: 1.5em;
font-weight: normal;
color: #3893E8;
display: block;
margin: 11px 0 1px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.relays .relay h2 span {
font-size: 1em;
display: block;
opacity: 0.8;
}
.relays .relay h2 span i {
opacity: 0.5;
}
.relays h2 .icon {
position: absolute;
top: 0;
left: 15px;
}
.relays h2 .icon::before {
color: #3893E8;
font-size: 34px;
line-height: 43px;
opacity: 0.8;
}