Skip to content

Commit

Permalink
Merge branch 'master' into modules/gathering
Browse files Browse the repository at this point in the history
* master:
  ui/study class TopicsCtrl
  close study topics popup on save
  refactor ui/study ctrl.setTab and make broadcast current round clickable
  use tabindex rather than href="#" to make an element tabbable
  add broadcast round form help
  cleanup and format
  the broadcast round we display is not always the one we link to
  Fix Copy PGN tab navigation
  Fix tab title for recently created tournament page
  Fix Copy PGN for chrome
  allow prismic images in markdown
  • Loading branch information
ornicar committed Apr 27, 2023
2 parents 7574191 + 0bae582 commit fa8edd4
Show file tree
Hide file tree
Showing 17 changed files with 110 additions and 104 deletions.
2 changes: 1 addition & 1 deletion app/mashup/Preload.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ object Preload:
tours: List[Tournament],
swiss: Option[Swiss],
events: List[Event],
relays: List[lila.relay.RelayTour.ActiveWithNextRound],
relays: List[lila.relay.RelayTour.ActiveWithSomeRounds],
simuls: List[Simul],
featured: Option[Game],
leaderboard: List[User.LightPerf],
Expand Down
8 changes: 4 additions & 4 deletions app/views/relay/bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import lila.relay.RelayTour

object bits:

def spotlight(tr: RelayTour.ActiveWithNextRound)(using Context) =
def spotlight(tr: RelayTour.ActiveWithSomeRounds)(using Context) =
a(
href := tr.path,
cls := s"tour-spotlight event-spotlight relay-spotlight id_${tr.tour.id}"
Expand All @@ -18,11 +18,11 @@ object bits:
span(cls := "content")(
span(cls := "name")(tr.tour.name),
span(cls := "more")(
tr.round.caption.fold(tr.round.name.value)(_.value),
tr.display.caption.fold(tr.display.name.value)(_.value),
"",
if tr.round.hasStarted
if tr.display.hasStarted
then trans.eventInProgress()
else tr.round.startsAt.map(momentFromNow(_)) | "Soon"
else tr.display.startsAt.map(momentFromNow(_)) | "Soon"
)
)
)
Expand Down
6 changes: 4 additions & 2 deletions app/views/relay/roundForm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ object roundForm:
form3.group(
form("delay"),
raw("Delay in seconds"),
help = raw(
"Optional, how long to delay moves coming from the source."
help = frag(
"Optional, how long to delay moves coming from the source.",
br,
"Add this delay to the start date of the event. E.g. if a tournament starts at 20:00 with a delay of 15 minutes, set the start date to 20:15."
).some,
half = true
)(form3.input(_, typ = "number")),
Expand Down
6 changes: 3 additions & 3 deletions app/views/relay/tour.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object tour:
import trans.broadcast.*

def index(
active: List[RelayTour.ActiveWithNextRound],
active: List[RelayTour.ActiveWithSomeRounds],
pager: Paginator[RelayTour.WithLastRound],
query: String = ""
)(using Context) =
Expand Down Expand Up @@ -79,8 +79,8 @@ object tour:
div(cls := "relay-widget__info")(
p(tr.tour.description),
p(cls := "relay-widget__info__meta")(
tr.tour.active option frag(strong(tr.round.name), br),
if ongoing(tr) then trans.playingRightNow() else tr.round.startsAt.map(momentFromNow(_))
tr.tour.active option frag(strong(tr.display.name), br),
if ongoing(tr) then trans.playingRightNow() else tr.display.startsAt.map(momentFromNow(_))
)
)
)
Expand Down
2 changes: 1 addition & 1 deletion app/views/userTournament/created.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object created:
def apply(u: User, pager: Paginator[lila.tournament.Tournament])(using Context) =
bits.layout(
u = u,
title = s"${u.username} recent tournaments",
title = s"${u.username} created tournaments",
path = path,
moreJs = infiniteScrollTag
) {
Expand Down
3 changes: 2 additions & 1 deletion modules/common/src/main/MarkdownRender.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ object MarkdownRender:
"i.ibb.co",
"i.postimg.cc",
"xkcd.com",
"lichess1.org"
"lichess1.org",
"images.prismic.io"
)
private def whitelistedSrc(src: String): Option[String] = for
url <- Try(URL.parse(src)).toOption
Expand Down
37 changes: 21 additions & 16 deletions modules/relay/src/main/RelayApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import lila.memo.CacheApi
import lila.study.{ Settings, Study, StudyApi, StudyId, StudyMaker, StudyMultiBoard, StudyRepo }
import lila.security.Granter
import lila.user.User
import lila.relay.RelayTour.ActiveWithSomeRounds

final class RelayApi(
roundRepo: RelayRoundRepo,
Expand Down Expand Up @@ -100,11 +101,11 @@ final class RelayApi(
}
}

private var spotlightCache: List[RelayTour.ActiveWithNextRound] = Nil
private var spotlightCache: List[RelayTour.ActiveWithSomeRounds] = Nil

def spotlight = spotlightCache
def spotlight: List[ActiveWithSomeRounds] = spotlightCache

val officialActive = cacheApi.unit[List[RelayTour.ActiveWithNextRound]] {
val officialActive = cacheApi.unit[List[RelayTour.ActiveWithSomeRounds]] {
_.refreshAfterWrite(5 seconds)
.buildAsyncFuture { _ =>
tourRepo.coll
Expand All @@ -130,30 +131,34 @@ final class RelayApi(
Limit(40)
)
}
.map { docs =>
.map: docs =>
for
doc <- docs
tour <- doc.asOpt[RelayTour]
round <- doc.getAsOpt[RelayRound]("round")
yield RelayTour.ActiveWithNextRound(tour, round)
}
.map {
_.sortBy: t =>
yield (tour, round)
.map:
_.sortBy: (tour, round) =>
(
!t.ongoing, // ongoing tournaments first
0 - ~t.tour.tier, // then by tier
t.round.startsAt.fold(Long.MaxValue)(_.toMillis) // then by next round date
!round.startedAt.isDefined, // ongoing tournaments first
0 - ~tour.tier, // then by tier
round.startsAt.fold(Long.MaxValue)(_.toMillis) // then by next round date
)
}
.addEffect { trs =>
.flatMap:
_.map: (tour, round) =>
defaultRoundToShow
.get(tour.id)
.map: link =>
RelayTour.ActiveWithSomeRounds(tour, display = round, link = link | round)
.parallel
.addEffect: trs =>
spotlightCache = trs
.filter(_.tour.tier.has(RelayTour.Tier.BEST))
.filterNot(_.round.finished)
.filterNot(_.display.finished)
.filter { tr =>
tr.round.hasStarted || tr.round.startsAt.exists(_.isBefore(nowInstant.plusMinutes(30)))
tr.display.hasStarted || tr.display.startsAt.exists(_.isBefore(nowInstant.plusMinutes(30)))
}
.take(2)
}
}
}

Expand Down
1 change: 0 additions & 1 deletion modules/relay/src/main/RelayFetch.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ final private class RelayFetch(
result match
case result: SyncResult.Ok if result.nbMoves == 0 => continueRelay(rt)
case result: SyncResult.Ok =>
continueRelay(rt)
lila.mon.relay.moves(rt.tour.official, rt.round.slug).increment(result.nbMoves)
continueRelay(rt.round.ensureStarted.resume withTour rt.tour)
case _ => continueRelay(rt)
Expand Down
15 changes: 7 additions & 8 deletions modules/relay/src/main/RelayRound.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ case class RelayRound(
sync = sync.play
)

def ensureStarted =
copy(
startedAt = startedAt orElse nowInstant.some
)

def ensureStarted = copy(startedAt = startedAt orElse nowInstant.some)
def hasStarted = startedAt.isDefined
def hasStartedEarly = hasStarted && startsAt.exists(_ isAfter nowInstant)
def shouldHaveStarted = hasStarted || startsAt.exists(_ isBefore nowInstant)
Expand Down Expand Up @@ -129,14 +125,17 @@ object RelayRound:
case class UpstreamIds(ids: List[GameId]) extends Upstream

trait AndTour:
val round: RelayRound
val tour: RelayTour
def fullName = s"${tour.name}${round.name}"
def display: RelayRound
def link: RelayRound
def fullName = s"${tour.name}${display.name}"
def path: String =
s"/broadcast/${tour.slug}/${if (round.slug == tour.slug) "-" else round.slug}/${round.id}"
s"/broadcast/${tour.slug}/${if (link.slug == tour.slug) "-" else link.slug}/${link.id}"
def path(chapterId: StudyChapterId): String = s"$path/$chapterId"

case class WithTour(round: RelayRound, tour: RelayTour) extends AndTour:
def display = round
def link = round
def withStudy(study: Study) = WithTourAndStudy(round, tour, study)

case class WithTourAndStudy(relay: RelayRound, tour: RelayTour, study: Study):
Expand Down
9 changes: 6 additions & 3 deletions modules/relay/src/main/RelayTour.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ object RelayTour:

case class WithRounds(tour: RelayTour, rounds: List[RelayRound])

case class ActiveWithNextRound(tour: RelayTour, round: RelayRound) extends RelayRound.AndTour:
def ongoing = round.startedAt.isDefined
case class ActiveWithSomeRounds(tour: RelayTour, display: RelayRound, link: RelayRound)
extends RelayRound.AndTour:
def ongoing = display.startedAt.isDefined

case class WithLastRound(tour: RelayTour, round: RelayRound) extends RelayRound.AndTour
case class WithLastRound(tour: RelayTour, round: RelayRound) extends RelayRound.AndTour:
def link = round
def display = round

def makeId = Id(ThreadLocalRandom nextString 8)
4 changes: 4 additions & 0 deletions ui/analyse/css/study/relay/_tour.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ main.has-relay-tour {
@extend %roboto;
font-size: 1.2em;
}
&.ongoing {
background: mix($c-accent, $c-bg-box, 10%);
color: $c-accent;
}
}

.study__multiboard {
Expand Down
3 changes: 2 additions & 1 deletion ui/analyse/src/study/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import GamebookPlayCtrl from './gamebook/gamebookPlayCtrl';
import { GamebookOverride } from './gamebook/interfaces';
import { GlyphCtrl } from './studyGlyph';
import { CommentForm } from './commentForm';
import { TopicsCtrl } from './topics';
import TopicsCtrl from './topics';
import RelayCtrl from './relay/relayCtrl';
import ServerEval from './serverEval';
import { MultiBoardCtrl } from './multiBoard';
Expand All @@ -27,6 +27,7 @@ export interface StudyCtrl {
currentChapter(): StudyChapterMeta;
socketHandler(t: string, d: any): boolean;
vm: StudyVm;
setTab(tab: Tab): void;
relay?: RelayCtrl;
multiBoard: MultiBoardCtrl;
form: StudyFormCtrl;
Expand Down
46 changes: 24 additions & 22 deletions ui/analyse/src/study/relay/relayTourView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ export default function (ctrl: AnalyseCtrl): VNode | undefined {
{
class: { active: relay.tab() === key },
attrs: { role: 'tab' },
hook: bind(
'mousedown',
() => {
relay.tab(key);
},
relay.redraw
),
hook: bind('mousedown', () => relay.tab(key), relay.redraw),
},
name
);
Expand Down Expand Up @@ -84,21 +78,29 @@ const overview = (relay: RelayCtrl, study: StudyCtrl) => {
return [
h('div.relay-tour__text', [
h('h1', relay.data.tour.name),
h('div.relay-tour__round', [
h('strong', round.name),
' ',
round.ongoing
? study.trans.noarg('playingRightNow')
: round.startsAt
? h(
'time.timeago',
{
hook: onInsert(el => el.setAttribute('datetime', '' + round.startsAt)),
},
lichess.timeago(round.startsAt)
)
: null,
]),
h(
'a.relay-tour__round',
{
class: { ongoing: !!round.ongoing },
attrs: { tabindex: 0 },
hook: bind('click', () => $('span.chapters[role="tab"]').trigger('mousedown')),
},
[
h('strong', round.name),
' ',
round.ongoing
? study.trans.noarg('playingRightNow')
: round.startsAt
? h(
'time.timeago',
{
hook: onInsert(el => el.setAttribute('datetime', '' + round.startsAt)),
},
lichess.timeago(round.startsAt)
)
: null,
]
),
relay.data.tour.markup
? h('div', {
hook: innerHTML(relay.data.tour.markup, () => relay.data.tour.markup!),
Expand Down
13 changes: 10 additions & 3 deletions ui/analyse/src/study/studyCtrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { StudyPracticeData, StudyPracticeCtrl } from './practice/interfaces';
import { ctrl as commentFormCtrl, CommentForm } from './commentForm';
import { ctrl as glyphFormCtrl, GlyphCtrl } from './studyGlyph';
import { ctrl as studyFormCtrl } from './studyForm';
import { ctrl as topicsCtrl, TopicsCtrl } from './topics';
import TopicsCtrl from './topics';
import { ctrl as notifCtrl } from './notif';
import { ctrl as shareCtrl } from './studyShare';
import { ctrl as tagsCtrl } from './studyTags';
Expand Down Expand Up @@ -115,6 +115,12 @@ export default function (

const startTour = () => tours.study(ctrl);

const setTab = (tab: Tab) => {
relay?.tourShow.disable();
vm.tab(tab);
redraw();
};

const members = memberCtrl({
initDict: data.members,
myId: practiceData ? undefined : ctrl.opts.userId,
Expand All @@ -134,7 +140,7 @@ export default function (
const chapters = new StudyChaptersCtrl(
data.chapters,
send,
() => vm.tab('chapters'),
() => setTab('chapters'),
chapterId => xhr.chapterConfig(data.id, chapterId),
ctrl
);
Expand Down Expand Up @@ -199,7 +205,7 @@ export default function (

const search = new SearchCtrl(relay?.fullRoundName() || data.name, chapters.list, setChapter, redraw);

const topics: TopicsCtrl = topicsCtrl(
const topics: TopicsCtrl = new TopicsCtrl(
topics => send('setTopics', topics),
() => data.topics || [],
ctrl.trans,
Expand Down Expand Up @@ -608,6 +614,7 @@ export default function (
return {
data,
form,
setTab,
members,
chapters,
notif,
Expand Down
8 changes: 6 additions & 2 deletions ui/analyse/src/study/studyShare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async function writePgnClipboard(url: string): Promise<void> {
return navigator.clipboard.writeText(pgn);
} else {
const clipboardItem = new ClipboardItem({
'text/plain': xhrText(url).then(pgn => new Blob([pgn])),
'text/plain': xhrText(url).then(pgn => new Blob([pgn], { type: 'text/plain' })),
});
return navigator.clipboard.write([clipboardItem]);
}
Expand Down Expand Up @@ -161,6 +161,7 @@ export function view(ctrl: StudyShareCtrl): VNode {
attrs: {
'data-icon': '',
title: ctrl.trans.noarg('copyChapterPgnDescription'),
tabindex: '0',
},
hook: bind('click', async event => {
const iconFeedback = (success: boolean) => {
Expand All @@ -169,7 +170,10 @@ export function view(ctrl: StudyShareCtrl): VNode {
};
writePgnClipboard(`/study/${studyId}/${ctrl.chapter().id}.pgn`).then(
() => iconFeedback(true),
() => iconFeedback(false)
err => {
console.log(err);
iconFeedback(false);
}
);
}),
},
Expand Down
11 changes: 2 additions & 9 deletions ui/analyse/src/study/studyView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,18 +170,11 @@ export function side(ctrl: StudyCtrl): VNode {

const makeTab = (key: Tab, name: string) =>
h(
'span.' + key,
`span.${key}`,
{
class: { active: !tourShow?.active && activeTab === key },
attrs: { role: 'tab' },
hook: bind(
'mousedown',
() => {
tourShow?.disable();
ctrl.vm.tab(key);
},
ctrl.redraw
),
hook: bind('mousedown', () => ctrl.setTab(key)),
},
name
);
Expand Down
Loading

0 comments on commit fa8edd4

Please sign in to comment.