homepage UI

es2016
Thibault Duplessis 2019-02-27 09:44:43 +07:00
parent f854cb0c0f
commit 05eb7bb30f
21 changed files with 230 additions and 102 deletions

View File

@ -29,13 +29,15 @@ object captcha {
),
dataCheckUrl := routes.Main.captchaCheck(captcha.gameId)
)(
div(
cls := "mini-board cg-board-wrap parse-fen is2d",
dataPlayable := "1",
dataX := encodeFen(safeJsonValue(Json.toJson(captcha.moves))),
dataY := encodeFen(if (captcha.white) { "white" } else { "black" }),
dataZ := encodeFen(captcha.fen)
)(div(cls := "cg-board")),
div(cls := "challenge")(
div(
cls := "mini-board cg-board-wrap parse-fen is2d",
dataPlayable := "1",
dataX := encodeFen(safeJsonValue(Json.toJson(captcha.moves))),
dataY := encodeFen(if (captcha.white) { "white" } else { "black" }),
dataZ := encodeFen(captcha.fen)
)(div(cls := "cg-board"))
),
div(cls := "captcha-explanation")(
label(cls := "form-label")(trans.colorPlaysCheckmateInOne.frag(
(if (captcha.white) trans.white else trans.black).frag()

View File

@ -8,6 +8,11 @@ import controllers.routes
object bits {
val lobbyApp = div(cls := "lobby__app")(
div(cls := "lobby__app__tabs")(span(i(cls := "ddloader"))),
div(cls := "lobby__app__content")
)
def underboards(
tours: List[lila.tournament.Tournament],
simuls: List[lila.simul.Simul],
@ -89,6 +94,33 @@ object bits {
)
)
def playbanInfo(ban: lila.playban.TempBan)(implicit ctx: Context) =
div(cls := "lobby__playban")(
h2("Sorry :("),
p("We had to time you out for a ", (ban.remainingSeconds < 3600) ?? "little ", "while."),
br,
p("The timeout expires ", strong(secondsFromNow(ban.remainingSeconds)), "."),
h2("Why?"),
p(
"We aim to provide a pleasant chess experience for everyone.", br,
"To that effect, we must ensure that all players follow good practice.", br,
"When a potential problem is detected, we display this message."
),
h2("How to avoid this?"),
ul(
li("Play every game you start"),
li("Try to win (or at least draw) every game you play"),
li("Resign lost games (don't let the clock run down)")
),
br,
br,
p(
"We apologize for the temporary inconvenience,", br,
"and wish you great games on lichess.org.", br,
"Thank you for reading!"
)
)
def currentGameInfo(current: lila.app.mashup.Preload.CurrentGame)(implicit ctx: Context) =
div(id := "lobby_current_game")(
h2("Hang on!"),

View File

@ -56,18 +56,16 @@ object home {
main(cls := "lobby")(
div(cls := "lobby__side")(
ctx.noKid option st.section(id := "streams_on_air")(views.html.streamer.bits liveStreams streams),
events map { bits.spotlight(_) },
events.map(bits.spotlight),
!ctx.isBot option frag(
lila.tournament.Spotlight.select(tours, ctx.me, 3) map { views.html.tournament.homepageSpotlight(_) },
simuls.find(_.spotlightable) take 2 map { views.html.simul.bits.homepageSpotlight(_) } toList
),
ctx.me map { u =>
div(id := "timeline", dataHref := routes.Timeline.home)(
div(cls := "timeline", dataHref := routes.Timeline.home)(
views.html.timeline entries userTimeline,
div(cls := "links")(
userTimeline.size >= 8 option
a(cls := "more", href := routes.Timeline.home)(trans.more.frag(), " »")
)
// userTimeline.size >= 8 option
a(cls := "more", href := routes.Timeline.home)(trans.more.frag(), " »")
)
} getOrElse {
div(cls := "about-side")(
@ -77,15 +75,9 @@ object home {
)
}
),
div(cls := List(
"lobby__app" -> true,
"playban" -> playban.isDefined,
"current-game" -> currentGame.isDefined
))(
currentGame map { bits.currentGameInfo(_) },
div(id := "hooks_wrap"),
playban.map(ban => playbanInfo(ban.remainingSeconds))
),
currentGame.map(bits.currentGameInfo) orElse
playban.map(bits.playbanInfo) getOrElse
bits.lobbyApp,
div(cls := "lobby__table")(
div(cls := "lobby__start")(
a(href := routes.Setup.hookForm, cls := List(

View File

@ -1,26 +0,0 @@
@(seconds: Int)(implicit ctx: Context)
<div id="lobby_playban">
<h2>Sorry :(</h2>
<p>We had to time you out for a @if(seconds < 3600){little }while.</h2>
<br />
<p>The timeout expires <strong>@secondsFromNow(seconds)</strong>.</p>
<h2>Why?</h2>
<p>
We aim to provide a pleasant chess experience for everyone.<br />
To that effect, we must ensure that all players follow good practices.<br />
When a potential problem is detected, we display this message.
</p>
<h2>How to avoid this?</h2>
<ul>
<li>Play every game you start</li>
<li>Try to win (or at least draw) every game you play</li>
<li>Resign lost games (don't let the clock run down)</li>
</ul>
<br />
<br />
<p>
We apologize for the temporary inconvenience,<br />
and wish you great games on lichess.org.<br />
Thank you for reading!
</p>
</div>

View File

@ -27,7 +27,7 @@ object bits {
}
def homepageSpotlight(s: lila.simul.Simul)(implicit ctx: Context) =
a(href := routes.Simul.show(s.id), cls := "tour_spotlight little id_@s.id")(
a(href := routes.Simul.show(s.id), cls := "tour-spotlight little id_@s.id")(
img(cls := "img icon", src := staticUrl("images/fire-silhouette.svg")),
span(cls := "content")(
span(cls := "name")(s.name, " simul"),

View File

@ -14,7 +14,7 @@ object homepageSpotlight {
val distant = (tour.isDistant) ?? " distant little"
s"${sched.freq} ${sched.speed} ${sched.variant.key}$invert$distant"
}
val tourClass = s"tour_spotlight id_${tour.id} $schedClass"
val tourClass = s"tour-spotlight id_${tour.id} $schedClass"
tour.spotlight map { spot =>
a(href := routes.Tournament.show(tour.id), cls := tourClass)(
frag(

View File

@ -9,8 +9,9 @@
border: 1px solid $c-error;
background: mix($c-error, $c-bg-high, 10%);
}
.mini_board {
flex: 0 0 calc(224px + 2rem);
.challenge {
flex: 0 0 250px;
margin-right: 2rem;
}
.captcha-explanation {
flex: 1 1 auto;

View File

@ -76,7 +76,7 @@ $c-border: hsl(0, 0%, 25%);
$border: $border-width $border-style $c-border;
$c-font-shadow: #000;
$text-shadow: 0 1px 1px $c-font-shadow;
$text-shadow: none;
@mixin metal {
background: linear-gradient(to bottom, hsl(0, 0, 22), hsl(0, 0, 19) 100%);

View File

@ -1,6 +1,9 @@
$mq-col2: $mq-medium;
$mq-col3: $mq-x-large;
$col2-app-height: minmax(500px, 70vh);
$app-tabs-height: 30px;
.lobby {
grid-area: main;
display: grid;
@ -26,7 +29,7 @@ $mq-col3: $mq-x-large;
grid-template-columns: repeat(3, minmax(150px, 350px));
grid-template-rows: min-content minmax(500px, calc(75vh - #{$site-header-height} - 200px));
grid-template-rows: min-content $col2-app-height;
grid-template-areas:
'table app app '
@ -42,9 +45,13 @@ $mq-col3: $mq-x-large;
@include breakpoint($mq-col3) {
grid-template-columns: repeat(4, minmax(150px, 350px));
grid-template-columns:
minmax(150px, 350px)
minmax(150px, 300px)
minmax(150px, 300px)
minmax(150px, 350px);
grid-template-rows: minmax(500px, calc(75vh - #{$site-header-height}));
grid-template-rows: $col2-app-height;
grid-template-areas:
'side app app table '

View File

@ -1,4 +1,7 @@
@import 'layout';
@import 'app/app';
@import 'puzzle';
@import 'side';
@import 'table';
@import 'spotlight';
@import 'timeline';

View File

@ -0,0 +1,4 @@
.lobby__side {
@extend %flex-column;
padding-top: $app-tabs-height;
}

View File

@ -0,0 +1,63 @@
.tour-spotlight {
@extend %flex-center, %box-radius, %nowrap-hidden;
flex: 0 0 auto;
padding: .3em;
opacity: 0.8;
@include transition();
background: $c-bg-low;
text-shadow: $text-shadow;
color: $c-font;
&.invert,
&.event-spotlight,
&:hover {
background: $c-primary;
color: $c-primary-over;
text-shadow: none;
}
&:hover {
opacity: 1;
}
.img {
flex: 0 0 40px;
margin: 0 10px 0 5px;
}
img.img {
width: 40px;
filter: brightness(9);
filter: brightness(9);
}
i.img,
.img.icon {
margin: 0 5px 0 0;
}
i.img::before {
color: #fff;
font-size: 40px;
text-shadow: 1px 1px 3px rgba(0,0,0,0.3);
}
.name {
margin-top: 1px;
line-height: 13px;
display: block;
}
.headline {
display: block;
font-size: .85em;
margin-bottom: -3px;
}
.more {
font-size: .85em;
time {
margin-left: 3px;
}
}
&.little {
.img {
flex: 0 0 2.2em;
margin: 0 .5em 0 .3em;
&::before {
font-size: 2.2em;
}
}
}
}

View File

@ -1,15 +1,29 @@
.lobby__start {
display: flex;
flex-flow: column nowrap;
justify-content: center;
a {
margin: 1.2em 0;
font-size: 1.3em;
padding: 1em;
text-align: center;
letter-spacing: -1px;
&.disabled {
opacity: 0.2;
.lobby {
&__table {
@extend %flex-column;
position: relative;
}
&__start {
@extend %flex-column;
justify-content: center;
flex: 1 1 auto;
a {
margin: 1.2em 0;
font-size: 1.3em;
padding: 1em;
text-align: center;
letter-spacing: -1px;
&.disabled {
opacity: 0.2;
}
}
}
&__counters {
position: absolute;
bottom: 0;
@extend %flex-column;
a {
color: $c-font;
}
}
}

View File

@ -0,0 +1,32 @@
.timeline {
flex: 1 1 auto;
margin-top: 1em;
overflow: hidden;
&:hover {
overflow-y: auto;
}
.entry {
@extend %roboto;
a {
@extend %base-font;
color: $c-font;
}
&:hover a {
color: $c-link;
}
&::after {
content: '';
display: block;
width: 100%;
height: 1px;
background: linear-gradient(to left, $c-border 20%, $c-bg-page);
margin: .7em 0;
}
}
.more {
font-size: .9em;
margin: .5em;
display: block;
text-align: right;
}
}

View File

@ -1,15 +1,17 @@
@import 'tab';
@import 'pool';
.lobby__app__content {
@extend %box-neat;
position: relative;
min-height: 500px;
background: $c-bg-box;
@if $theme-light {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMy41MjkgMzMuNTA0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNS4yNS02LjI0NikiIG9wYWNpdHk9Ii4xIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiPjxnIGZpbGw9IiNmZmYiPjxwYXRoIGQ9Im0yMiAxMGMxMC41IDEgMTYuNSA4IDE2IDI5aC0yM2MwLTkgMTAtNi41IDgtMjEiLz48cGF0aCBkPSJtMjQgMThjLjM4IDIuOTEtNS41NSA3LjM3LTggOS0zIDItMi44MiA0LjM0LTUgNC0xLjA0Mi0uOTQgMS40MS0zLjA0IDAtMy0xIDAgLjE5IDEuMjMtMSAyLTEgMC00IDEtNC00IDAtMiA2LTEyIDYtMTIgMCAwIDEuODktMS45IDItMy41LS43My0uOTk0LS41LTItLjUtMyAxLTEgMyAyLjUgMyAyLjVoMmMwIDAgLjc4LTEuOTkyIDIuNS0zIDEgMCAxIDMgMSAzIi8+PC9nPjxnIGZpbGw9IiMwMDAiPjxwYXRoIGQ9Im05LjUgMjUuNWEuNSAuNSAwIDEgMSAtMSAwIC41IC41IDAgMSAxIDEgMHoiLz48cGF0aCBkPSJtMTUgMTUuNWEuNSAxLjUgMCAxIDEgLTEgMCAuNSAxLjUgMCAxIDEgMSAweiIgdHJhbnNmb3JtPSJtYXRyaXgoLjg2Ni41LS41Ljg2NiA5LjY5My01LjE3MykiLz48L2c+PC9nPjwvc3ZnPg==');
} @else {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMy41MjkgMzMuNTA0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNS4yNS02LjI0NikiIG9wYWNpdHk9Ii4xIiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiPjxnIGZpbGw9IiMwMDAiPjxwYXRoIGQ9Im0yMiAxMGMxMC41IDEgMTYuNSA4IDE2IDI5aC0yM2MwLTkgMTAtNi41IDgtMjEiLz48cGF0aCBkPSJtMjQgMThjLjM4IDIuOTEtNS41NSA3LjM3LTggOS0zIDItMi44MiA0LjM0LTUgNC0xLjA0Mi0uOTQgMS40MS0zLjA0IDAtMy0xIDAgLjE5IDEuMjMtMSAyLTEgMC00IDEtNC00IDAtMiA2LTEyIDYtMTIgMCAwIDEuODktMS45IDItMy41LS43My0uOTk0LS41LTItLjUtMyAxLTEgMyAyLjUgMyAyLjVoMmMwIDAgLjc4LTEuOTkyIDIuNS0zIDEgMCAxIDMgMSAzIi8+PC9nPjxnIGZpbGw9IiNmZmYiPjxwYXRoIGQ9Im05LjUgMjUuNWEuNSAuNSAwIDEgMSAtMSAwIC41IC41IDAgMSAxIDEgMHoiLz48cGF0aCBkPSJtMTUgMTUuNWEuNSAxLjUgMCAxIDEgLTEgMCAuNSAxLjUgMCAxIDEgMSAweiIgdHJhbnNmb3JtPSJtYXRyaXgoLjg2Ni41LS41Ljg2NiA5LjY5My01LjE3MykiLz48L2c+PC9nPjwvc3ZnPg==');
.lobby__app {
@extend %flex-column;
user-select: none;
&__content {
flex: 1 1 100%;
@extend %box-neat;
@if $theme-light {
background: $c-bg-zebra url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMy41MjkgMzMuNTA0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNS4yNS02LjI0NikiIG9wYWNpdHk9Ii4xIiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiPjxnIGZpbGw9IiNmZmYiPjxwYXRoIGQ9Im0yMiAxMGMxMC41IDEgMTYuNSA4IDE2IDI5aC0yM2MwLTkgMTAtNi41IDgtMjEiLz48cGF0aCBkPSJtMjQgMThjLjM4IDIuOTEtNS41NSA3LjM3LTggOS0zIDItMi44MiA0LjM0LTUgNC0xLjA0Mi0uOTQgMS40MS0zLjA0IDAtMy0xIDAgLjE5IDEuMjMtMSAyLTEgMC00IDEtNC00IDAtMiA2LTEyIDYtMTIgMCAwIDEuODktMS45IDItMy41LS43My0uOTk0LS41LTItLjUtMyAxLTEgMyAyLjUgMyAyLjVoMmMwIDAgLjc4LTEuOTkyIDIuNS0zIDEgMCAxIDMgMSAzIi8+PC9nPjxnIGZpbGw9IiMwMDAiPjxwYXRoIGQ9Im05LjUgMjUuNWEuNSAuNSAwIDEgMSAtMSAwIC41IC41IDAgMSAxIDEgMHoiLz48cGF0aCBkPSJtMTUgMTUuNWEuNSAxLjUgMCAxIDEgLTEgMCAuNSAxLjUgMCAxIDEgMSAweiIgdHJhbnNmb3JtPSJtYXRyaXgoLjg2Ni41LS41Ljg2NiA5LjY5My01LjE3MykiLz48L2c+PC9nPjwvc3ZnPg==');
} @else {
background: $c-bg-zebra url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMy41MjkgMzMuNTA0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNS4yNS02LjI0NikiIG9wYWNpdHk9Ii4xIiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiPjxnIGZpbGw9IiMwMDAiPjxwYXRoIGQ9Im0yMiAxMGMxMC41IDEgMTYuNSA4IDE2IDI5aC0yM2MwLTkgMTAtNi41IDgtMjEiLz48cGF0aCBkPSJtMjQgMThjLjM4IDIuOTEtNS41NSA3LjM3LTggOS0zIDItMi44MiA0LjM0LTUgNC0xLjA0Mi0uOTQgMS40MS0zLjA0IDAtMy0xIDAgLjE5IDEuMjMtMSAyLTEgMC00IDEtNC00IDAtMiA2LTEyIDYtMTIgMCAwIDEuODktMS45IDItMy41LS43My0uOTk0LS41LTItLjUtMyAxLTEgMyAyLjUgMyAyLjVoMmMwIDAgLjc4LTEuOTkyIDIuNS0zIDEgMCAxIDMgMSAzIi8+PC9nPjxnIGZpbGw9IiNmZmYiPjxwYXRoIGQ9Im05LjUgMjUuNWEuNSAuNSAwIDEgMSAtMSAwIC41IC41IDAgMSAxIDEgMHoiLz48cGF0aCBkPSJtMTUgMTUuNWEuNSAxLjUgMCAxIDEgLTEgMCAuNSAxLjUgMCAxIDEgMSAweiIgdHJhbnNmb3JtPSJtYXRyaXgoLjg2Ni41LS41Ljg2NiA5LjY5My01LjE3MykiLz48L2c+PC9nPjwvc3ZnPg==');
}
background-size: 100% 100%;
}
background-size: 100% 100%;
}

View File

@ -1,30 +1,31 @@
.lpools {
@extend %square;
padding: 12px 12px 0 12px;
height: 60vh;
min-height: 500px;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
font-family: Roboto;
-webkit-user-select: none;
@extend %roboto;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 9px;
// padding: 12px 12px 0 12px;
// display: flex;
// flex-flow: row wrap;
// justify-content: space-between;
> div {
@extend %box-radius, %box-shadow, %flex-column;
@extend %flex-column, %box-radius;
// @extend %box-radius, %box-shadow, %flex-column;
justify-content: center;
align-items: center;
margin-bottom: 12px;
flex: 0 0 31%;
height: 31%;
// margin-bottom: 12px;
// flex: 0 0 31%;
// height: 31%;
cursor: pointer;
background: fade-out($c-bg-box, .3);
background: fade-out($c-bg-box, .5);
transition: background .15s, opacity 0.7s;
&:hover {
background: fade-out($c-accent, .8);
}
}
.active {
@extend %box-shadow;
background: #fff;
&.active {
@extend %box-shadow;
background: #fff;
}
}
.transp {
opacity: 0.5;

View File

@ -1,6 +1,6 @@
.lobby__app__tabs {
@extend %flex-center-nowrap;
flex: 0 0 $app-tabs-height;
justify-content: center;
align-items: flex-start;
border-bottom: 2px solid $c-border;
@ -9,7 +9,8 @@
flex: 1 1 0;
text-align: center;
font-size: .9em;
padding: .4em .1em;
line-height: #{$app-tabs-height - 2px};
padding: 0 .1em;
cursor: pointer;
position: relative;
@include transition(color, .25s);

View File

@ -31,7 +31,7 @@ module.exports = function(cfg, element) {
return l.slice(0, 2).toLowerCase();
});
langs.push($('html').attr('lang'));
$('#streams_on_air a, .event_spotlight').each(function() {
$('#streams_on_air a, .event-spotlight').each(function() {
var match = $(this).text().match(/\[(\w{2})\]/mi);
if (match && langs.indexOf(match[1].toLowerCase()) === -1) $(this).hide();
});

View File

@ -45,5 +45,5 @@ export function start(opts: LobbyOpts) {
window.Chessground = Chessground;
window.onload = function() {
boot(window['lichess_lobby'], document.getElementById('hooks_wrap'));
boot(window['lichess_lobby'], document.querySelector('.lobby__app'));
};

View File

@ -27,7 +27,7 @@ export default function(ctrl: LobbyController) {
body = renderPlaying(ctrl);
break;
}
return h('div#hooks_wrap', [
return h('div.lobby__app', [
h('div.lobby__app__tabs', renderTabs(ctrl)),
h('div.lobby__app__content.l' + (ctrl.redirecting ? 'redir' : ctrl.tab), data, body)
]);

View File

@ -855,7 +855,7 @@ lichess.topMenuIntent = function() {
$('.chat__members').watchers();
$('div.captcha').each(function() {
var $captcha = $(this);
var $board = $captcha.find('.mini_board');
var $board = $captcha.find('.mini-board');
var $input = $captcha.find('input').val('');
var cg = $board.data('chessground');
var dests = JSON.parse(lichess.readServerFen($board.data('x')));