add support for user social links - closes #3481
This commit is contained in:
parent
a1c90b7f76
commit
b3fdff969d
|
@ -40,6 +40,13 @@ evenMoreCss =cssTag("material.form.css")) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</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)
|
@errMsg(form)
|
||||||
@base.form.submit()
|
@base.form.submit()
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -169,9 +169,14 @@ case _ => {
|
||||||
<p>@trans.tpTimeSpentOnTV(showPeriod(tvPeriod))</p>
|
<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 =>
|
@info.teamIds.sorted.map { t =>
|
||||||
@teamLink(t)
|
@teamLink(t, withIcon = false)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,7 +20,8 @@ object DataForm {
|
||||||
"lastName" -> nameField,
|
"lastName" -> nameField,
|
||||||
"fideRating" -> optional(number(min = 600, max = 3000)),
|
"fideRating" -> optional(number(min = 600, max = 3000)),
|
||||||
"uscfRating" -> 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))
|
)(Profile.apply)(Profile.unapply))
|
||||||
|
|
||||||
def profileOf(user: User) = profile fill user.profileOrDefault
|
def profileOf(user: User) = profile fill user.profileOrDefault
|
||||||
|
|
45
modules/user/src/main/Links.scala
Normal file
45
modules/user/src/main/Links.scala
Normal 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,8 @@ case class Profile(
|
||||||
lastName: Option[String] = None,
|
lastName: Option[String] = None,
|
||||||
fideRating: Option[Int] = None,
|
fideRating: Option[Int] = None,
|
||||||
uscfRating: 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 {
|
def nonEmptyRealName = List(ne(firstName), ne(lastName)).flatten match {
|
||||||
|
@ -31,6 +32,8 @@ case class Profile(
|
||||||
100 * c.count(_.isDefined) / c.size
|
100 * c.count(_.isDefined) / c.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def actualLinks: List[Link] = links ?? Links.make
|
||||||
|
|
||||||
import Profile.OfficialRating
|
import Profile.OfficialRating
|
||||||
|
|
||||||
def officialRating: Option[OfficialRating] =
|
def officialRating: Option[OfficialRating] =
|
||||||
|
@ -47,5 +50,6 @@ object Profile {
|
||||||
|
|
||||||
val default = Profile()
|
val default = Profile()
|
||||||
|
|
||||||
private[user] val profileBSONHandler = reactivemongo.bson.Macros.handler[Profile]
|
import reactivemongo.bson.Macros
|
||||||
|
private[user] val profileBSONHandler = Macros.handler[Profile]
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,17 +299,23 @@ div.sub_ratings h3 {
|
||||||
.user_show .bio,
|
.user_show .bio,
|
||||||
.user_show .stats,
|
.user_show .stats,
|
||||||
.user_show .tournament_points,
|
.user_show .tournament_points,
|
||||||
|
.user_show .social_links,
|
||||||
.user_show .teams {
|
.user_show .teams {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 16px;
|
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 {
|
.user_show .bio {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.user_show .teams a {
|
|
||||||
display: block;
|
|
||||||
margin: 5px 0;
|
|
||||||
}
|
|
||||||
.user_show div.games {
|
.user_show div.games {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue