improve all user autocompletes, add online status

pull/3736/head
Thibault Duplessis 2017-10-22 11:51:13 -05:00
parent 176e520c1e
commit 02a3e33f0a
6 changed files with 31 additions and 60 deletions

View File

@ -9,6 +9,7 @@ import lila.app._
import lila.app.mashup.{ GameFilterMenu, GameFilter }
import lila.common.paginator.Paginator
import lila.common.{ IpAddress, HTTPRequest }
import lila.common.PimpedJson._
import lila.game.{ GameRepo, Game => GameModel }
import lila.rating.PerfType
import lila.socket.UserLagCache
@ -311,16 +312,25 @@ object User extends LilaController {
def autocomplete = Open { implicit ctx =>
get("term", ctx.req).filter(_.nonEmpty) match {
case None => BadRequest("No search term provided").fuccess
case Some(term) if getBool("exists") => UserRepo nameExists term map { r => Ok(JsBoolean(r)) }
case Some(term) => {
ctx.me.ifTrue(getBool("friend")) match {
case None if getBool("exists") => UserRepo nameExists term map { JsBoolean(_) }
case None => UserRepo usernamesLike term map { Json.toJson(_) }
case None => UserRepo userIdsLike term
case Some(follower) =>
Env.relation.api.searchFollowedBy(follower, term, 10) flatMap {
case Nil => UserRepo usernamesLike term
case userIds => UserRepo usernamesByIds userIds
} map { Json.toJson(_) }
case Nil => UserRepo userIdsLike term
case userIds => fuccess(userIds)
}
}
} flatMap { userIds =>
if (getBool("object")) Env.user.lightUserApi.asyncMany(userIds) map { users =>
Json.obj(
"result" -> JsArray(users.flatten.map { u =>
lila.common.LightUser.lightUserWrites.writes(u).add("online" -> Env.user.isOnline(u.id))
})
)
}
else fuccess(Json toJson userIds)
} map { Ok(_) as JSON }
}
}

View File

@ -141,7 +141,7 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
@if(isGranted(_.SeeReport)) {
<a class="link text data-count" href="@routes.Report.list" data-count="@reportNbUnprocessed" data-icon=""></a>
}
<div id="clinput"><a class="link"><span data-icon="y"></span></a><input /></div>
<div id="clinput"><a class="link"><span data-icon="y"></span></a><input spellcheck="false" placeholder="@trans.search()"/></div>
}
<a id="reconnecting" class="link text" onclick="window.location.reload()" data-icon="B">@trans.reconnecting()</a>
</div>

View File

@ -31,7 +31,7 @@
@side = {
<div class="side">
<form class="search public">
<input placeholder="@trans.search()" class="search_user user-autocomplete-jump" autofocus />
<input placeholder="@trans.search()" class="search_user user-autocomplete" autofocus />
</form>
@if(isGranted(_.UserSearch)) {
<form class="search" action="@routes.Mod.search" method="GET">

View File

@ -249,20 +249,20 @@ object UserRepo {
* @param usernames Usernames to filter out the non-existent usernames from, and return the IDs for
* @return A list of IDs for the usernames that were given that were valid
*/
def existingUsernameIds(usernames: Set[String]): Fu[List[String]] =
coll.primitive[String]($inIds(usernames.map(normalize)), "_id")
def existingUsernameIds(usernames: Set[String]): Fu[List[User.ID]] =
coll.primitive[String]($inIds(usernames.map(normalize)), F.id)
def usernamesLike(text: String, max: Int = 10): Fu[List[String]] = {
def userIdsLike(text: String, max: Int = 10): Fu[List[User.ID]] = {
val id = normalize(text)
if (!User.idPattern.matcher(id).matches) fuccess(Nil)
else coll.find(
$doc("_id".$regex("^" + id + ".*$", "")) ++ enabledSelect,
$doc(F.username -> true)
$doc(F.id.$regex("^" + id + ".*$", "")) ++ enabledSelect,
$doc(F.id -> true)
)
.sort($doc("len" -> 1))
.cursor[Bdoc](ReadPreference.secondaryPreferred).gather[List](max)
.map {
_ flatMap { _.getAs[String](F.username) }
_ flatMap { _.getAs[String](F.id) }
}
}

View File

@ -1,45 +1,5 @@
$(function() {
var setupAutocomplete = function() {
var go = function(name) {
location.href = '/@/' + name;
}
var $input = $(this);
lichess.loadCss('/assets/stylesheets/autocomplete.css');
lichess.loadScript('/assets/javascripts/vendor/typeahead.jquery.min.js').done(function() {
$input.typeahead(null, {
minLength: 2,
hint: true,
highlight: true,
source: function(query, sync, async) {
$.ajax({
url: '/player/autocomplete?term=' + query,
cache: true,
success: function(res) {
// hack to fix typeahead limit bug
if (res.length === 10) res.push(null);
async(res);
}
});
},
limit: 10,
templates: {
empty: '<div class="empty">No player found</div>',
pending: lichess.spinnerHtml,
suggestion: function(a) {
return '<span class="ulpt" data-href="/@/' + a + '">' + a + '</span>';
}
}
}).on('typeahead:select', function(ev, sel) {
go(sel);
}).keypress(function(e) {
if (e.which == 10 || e.which == 13) go($(this).val());
}).focus();
});
};
$('input.user-autocomplete-jump').each(setupAutocomplete);
$('div.user_show .mod_zone_toggle').each(function() {
$(this).click(function() {
var $zone = $('div.user_show .mod_zone');

View File

@ -172,31 +172,32 @@ lichess.topMenuIntent = function() {
minLength: 3,
hint: true,
highlight: false,
source: function(query, sync, runAsync) {
source: function(query, _, runAsync) {
$.ajax({
method: 'get',
url: '/player/autocomplete',
cache: true,
data: {
term: query,
friend: opts.friend ? 1 : 0,
object: 1
},
success: function(res) {
res = res.result;
// hack to fix typeahead limit bug
if (res.length === 10) {
res.push(null);
}
if (res.length === 10) res.push(null);
runAsync(res);
}
});
},
limit: 10,
displayKey: 'name',
templates: {
empty: '<div class="empty">No player found</div>',
pending: lichess.spinnerHtml,
suggestion: function(o) {
console.log(o);
return '<a class="ulpt" href="/@/' + a + '">' + a + '</a>';
return '<a class="ulpt user_link' + (o.online ? ' online' : '') + '" href="/@/' + o.name + '">' +
'<i class="line' + (o.patron ? ' patron' : '') + '"></i>' + (o.title ? o.title + ' ' : '') + o.name +
'</a>';
}
}
}).on('typeahead:render', function() {