add support for user social links - closes #3481

This commit is contained in:
Thibault Duplessis 2017-09-17 19:28:40 -05:00
parent a1c90b7f76
commit b3fdff969d
6 changed files with 77 additions and 9 deletions

View file

@ -40,6 +40,13 @@ evenMoreCss =cssTag("material.form.css")) {
}
}
</div>
@base.form.group(form("links"), Html("Social media links ")) {
<textarea name="@form("links").name" id="@form("links").id" rows=5 maxlength=600>@form("links").value</textarea>
<p class="form-help">
Such as Twitter, Facebook, Github, Chess.com, ...<br />
One URL per line.
</p>
}
@errMsg(form)
@base.form.submit()
</form>

View file

@ -169,9 +169,14 @@ case _ => {
<p>@trans.tpTimeSpentOnTV(showPeriod(tvPeriod))</p>
}
}
<div class="teams">
<div class="social_links col2">
@profile.actualLinks.map { link =>
<a href="@link.url" rel="no-follow">@link.site.name</a>
}
</div>
<div class="teams col2">
@info.teamIds.sorted.map { t =>
@teamLink(t)
@teamLink(t, withIcon = false)
}
</div>
</div>

View file

@ -20,7 +20,8 @@ object DataForm {
"lastName" -> nameField,
"fideRating" -> optional(number(min = 600, max = 3000)),
"uscfRating" -> optional(number(min = 600, max = 3000)),
"ecfRating" -> optional(number(min = 0, max = 300))
"ecfRating" -> optional(number(min = 0, max = 300)),
"links" -> optional(nonEmptyText(maxLength = 3000))
)(Profile.apply)(Profile.unapply))
def profileOf(user: User) = profile fill user.profileOrDefault

View file

@ -0,0 +1,45 @@
package lila.user
object Links {
def make(text: String): List[Link] = text.lines.toList.map(_.trim) flatMap toLink
private val UrlRegex = """^(?:http[s]?:\/\/)?(.+)/.+""".r
private def toLink(line: String): Option[Link] = line match {
case UrlRegex(domain) => Link(
site = Link.Site.allKnown find { site =>
site.domains.contains(domain)
} getOrElse Link.Site.Other(domain),
url =
if (line startsWith "http") line
else s"https://$line"
).some
case _ => none
}
}
case class Link(site: Link.Site, url: String)
object Link {
sealed abstract class Site(val name: String, val domains: List[String])
object Site {
case object Twitter extends Site("Twitter", List("twitter.com"))
case object Facebook extends Site("Facebook", List("facebook.com"))
case object YouTube extends Site("YouTube", List("youtube.com"))
case object Twitch extends Site("Twitch", List("twitch.com"))
case object Github extends Site("Github", List("github.com"))
case object ChessCom extends Site("Chess.com", List("chess.com"))
case object Chess24 extends Site("Chess24", List("chess24.com"))
case object GameKnot extends Site("GameKnot", List("gameknot.com"))
case object ChessTempo extends Site("ChessTempo", List("chesstempo.com"))
case object ChessCube extends Site("ChessCube", List("chesscube.com"))
case class Other(domain: String) extends Site(domain, List(domain))
val allKnown: List[Site] = List(
Twitter, Facebook, YouTube, Twitch, Github,
ChessCom, Chess24, GameKnot, ChessTempo, ChessCube
)
}
}

View file

@ -8,7 +8,8 @@ case class Profile(
lastName: Option[String] = None,
fideRating: Option[Int] = None,
uscfRating: Option[Int] = None,
ecfRating: Option[Int] = None
ecfRating: Option[Int] = None,
links: Option[String] = None
) {
def nonEmptyRealName = List(ne(firstName), ne(lastName)).flatten match {
@ -31,6 +32,8 @@ case class Profile(
100 * c.count(_.isDefined) / c.size
}
def actualLinks: List[Link] = links ?? Links.make
import Profile.OfficialRating
def officialRating: Option[OfficialRating] =
@ -47,5 +50,6 @@ object Profile {
val default = Profile()
private[user] val profileBSONHandler = reactivemongo.bson.Macros.handler[Profile]
import reactivemongo.bson.Macros
private[user] val profileBSONHandler = Macros.handler[Profile]
}

View file

@ -299,17 +299,23 @@ div.sub_ratings h3 {
.user_show .bio,
.user_show .stats,
.user_show .tournament_points,
.user_show .social_links,
.user_show .teams {
display: block;
margin-top: 16px;
}
.user_show .col2 {
display: flex;
flex-flow: row wrap;
line-height: 1.7em;
}
.user_show .col2 > a {
flex: 0 0 50%;
color: #3893E8!important;
}
.user_show .bio {
font-style: italic;
}
.user_show .teams a {
display: block;
margin: 5px 0;
}
.user_show div.games {
padding-top: 10px;
}