Use Semantic UI's Search component for user and repo search (#2636)

* Use search component on org invitation user input.

* Search component for collaboration and members.

* Search component for repo search.

* minCharacters for search input

* Display full_name for user search.

* Fixed missing uid query parameter for repo search.

* Removed unused comment.
release/v1.15
harry 2017-10-02 22:27:48 -05:00 committed by Lauris BH
parent a04718a2a6
commit b3cfa5a77e
7 changed files with 49 additions and 109 deletions

File diff suppressed because one or more lines are too long

View File

@ -1230,104 +1230,53 @@ function hideWhenLostFocus(body, parent) {
} }
function searchUsers() { function searchUsers() {
if (!$('#search-user-box .results').length) {
return;
}
var $searchUserBox = $('#search-user-box'); var $searchUserBox = $('#search-user-box');
var $results = $searchUserBox.find('.results'); $searchUserBox.search({
$searchUserBox.keyup(function () { minCharacters: 2,
var $this = $(this); apiSettings: {
var keyword = $this.find('input').val(); url: suburl + '/api/v1/users/search?q={query}',
if (keyword.length < 2) { onResponse: function(response) {
$results.hide(); var items = [];
return; $.each(response.data, function (i, item) {
} var title = item.login;
if (item.full_name && item.full_name.length > 0) {
title += ' (' + item.full_name + ')';
}
items.push({
title: title,
image: item.avatar_url
})
});
$.ajax({ return { results: items }
url: suburl + '/api/v1/users/search?q=' + keyword,
dataType: "json",
success: function (response) {
var notEmpty = function (str) {
return str && str.length > 0;
};
$results.html('');
if (response.ok && response.data.length) {
var html = '';
$.each(response.data, function (i, item) {
html += '<div class="item"><img class="ui avatar image" src="' + item.avatar_url + '"><span class="username">' + item.login + '</span>';
if (notEmpty(item.full_name)) {
html += ' (' + item.full_name + ')';
}
html += '</div>';
});
$results.html(html);
$this.find('.results .item').click(function () {
$this.find('input').val($(this).find('.username').text());
$results.hide();
});
$results.show();
} else {
$results.hide();
}
} }
}); },
searchFields: ['login', 'full_name'],
showNoResults: false
}); });
$searchUserBox.find('input').focus(function () {
$searchUserBox.keyup();
});
hideWhenLostFocus('#search-user-box .results', '#search-user-box');
} }
// FIXME: merge common parts in two functions
function searchRepositories() { function searchRepositories() {
if (!$('#search-repo-box .results').length) {
return;
}
var $searchRepoBox = $('#search-repo-box'); var $searchRepoBox = $('#search-repo-box');
var $results = $searchRepoBox.find('.results'); $searchRepoBox.search({
$searchRepoBox.keyup(function () { minCharacters: 2,
var $this = $(this); apiSettings: {
var keyword = $this.find('input').val(); url: suburl + '/api/v1/repos/search?q={query}&uid=' + $searchRepoBox.data('uid'),
if (keyword.length < 2) { onResponse: function(response) {
$results.hide(); var items = [];
return; $.each(response.data, function (i, item) {
} items.push({
title: item.full_name.split("/")[1],
description: item.full_name
})
});
$.ajax({ return { results: items }
url: suburl + '/api/v1/repos/search?q=' + keyword + "&uid=" + $searchRepoBox.data('uid'),
dataType: "json",
success: function (response) {
var notEmpty = function (str) {
return str && str.length > 0;
};
$results.html('');
if (response.ok && response.data.length) {
var html = '';
$.each(response.data, function (i, item) {
html += '<div class="item"><i class="icon octicon octicon-repo"></i> <span class="fullname">' + item.full_name + '</span></div>';
});
$results.html(html);
$this.find('.results .item').click(function () {
$this.find('input').val($(this).find('.fullname').text().split("/")[1]);
$results.hide();
});
$results.show();
} else {
$results.hide();
}
} }
}); },
searchFields: ['full_name'],
showNoResults: false
}); });
$searchRepoBox.find('input').focus(function () {
$searchRepoBox.keyup();
});
hideWhenLostFocus('#search-repo-box .results', '#search-repo-box');
} }
function initCodeView() { function initCodeView() {

View File

@ -1345,20 +1345,15 @@
#search-repo-box, #search-repo-box,
#search-user-box { #search-user-box {
.results { .results {
padding: 0; .result {
position: absolute; .image {
float: left;
.item {
padding: 10px 15px;
border-bottom: 1px solid #DDD;
cursor: pointer;
&:hover {
background: rgba(0,0,0,.05)!important;
color: rgba(0,0,0,.95)!important;
}
img {
margin-right: 8px; margin-right: 8px;
width: 2em;
height: 2em;
}
.content {
margin: 6px 0;
} }
} }
} }

View File

@ -8,11 +8,10 @@
<form class="ui form" action="{{.Link}}" method="post"> <form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="inline field ui left"> <div class="inline field ui left">
<div id="search-user-box"> <div id="search-user-box" class="ui search">
<div class="ui input"> <div class="ui input">
<input class="prompt" name="uname" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" autofocus required> <input class="prompt" name="uname" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" autofocus required>
</div> </div>
<div class="ui segment results hide"></div>
</div> </div>
</div> </div>
<button class="ui blue button">{{.i18n.Tr "org.members.invite_now"}}</button> <button class="ui blue button">{{.i18n.Tr "org.members.invite_now"}}</button>

View File

@ -28,11 +28,10 @@
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" name="uid" value="{{.SignedUser.ID}}"> <input type="hidden" name="uid" value="{{.SignedUser.ID}}">
<div class="inline field ui left"> <div class="inline field ui left">
<div id="search-user-box"> <div id="search-user-box" class="ui search">
<div class="ui input"> <div class="ui input">
<input class="prompt" name="uname" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" required> <input class="prompt" name="uname" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" required>
</div> </div>
<div class="ui segment results hide"></div>
</div> </div>
</div> </div>
<button class="ui green button">{{.i18n.Tr "org.teams.add_team_member"}}</button> <button class="ui green button">{{.i18n.Tr "org.teams.add_team_member"}}</button>

View File

@ -28,11 +28,10 @@
<form class="ui form" id="add-repo-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/add" method="post"> <form class="ui form" id="add-repo-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/add" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="inline field ui left"> <div class="inline field ui left">
<div id="search-repo-box" data-uid="{{.Org.ID}}"> <div id="search-repo-box" data-uid="{{.Org.ID}}" class="ui search">
<div class="ui input"> <div class="ui input">
<input class="prompt" name="repo_name" placeholder="{{.i18n.Tr "org.teams.search_repo_placeholder"}}" autocomplete="off" required> <input class="prompt" name="repo_name" placeholder="{{.i18n.Tr "org.teams.search_repo_placeholder"}}" autocomplete="off" required>
</div> </div>
<div class="ui segment results hide"></div>
</div> </div>
</div> </div>
<button class="ui green button">{{.i18n.Tr "org.teams.add_team_repository"}}</button> <button class="ui green button">{{.i18n.Tr "org.teams.add_team_repository"}}</button>

View File

@ -42,11 +42,10 @@
<form class="ui form" id="repo-collab-form" action="{{.Link}}" method="post"> <form class="ui form" id="repo-collab-form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="inline field ui left"> <div class="inline field ui left">
<div id="search-user-box"> <div id="search-user-box" class="ui search">
<div class="ui input"> <div class="ui input">
<input class="prompt" name="collaborator" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" autofocus required> <input class="prompt" name="collaborator" placeholder="{{.i18n.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" autofocus required>
</div> </div>
<div class="ui segment results hide"></div>
</div> </div>
</div> </div>
<button class="ui green button">{{.i18n.Tr "repo.settings.add_collaborator"}}</button> <button class="ui green button">{{.i18n.Tr "repo.settings.add_collaborator"}}</button>