Commit 9efb6e76 by Daniel Lee Committed by Torkel Ödegaard

users: adds search and pagination (#7753)

ref #7469. Follow up change that adds proper paging with 50 results
per page as well as a search box to search by name, login or email.
parent 8e3f22d3
...@@ -239,7 +239,9 @@ func searchUser(c *middleware.Context) (*m.SearchUsersQuery, error) { ...@@ -239,7 +239,9 @@ func searchUser(c *middleware.Context) (*m.SearchUsersQuery, error) {
page = 1 page = 1
} }
query := &m.SearchUsersQuery{Query: "", Page: page, Limit: perPage} searchQuery := c.Query("query")
query := &m.SearchUsersQuery{Query: searchQuery, Page: page, Limit: perPage}
if err := bus.Dispatch(query); err != nil { if err := bus.Dispatch(query); err != nil {
return nil, err return nil, err
} }
......
...@@ -363,8 +363,12 @@ func SearchUsers(query *m.SearchUsersQuery) error { ...@@ -363,8 +363,12 @@ func SearchUsers(query *m.SearchUsersQuery) error {
query.Result = m.SearchUserQueryResult{ query.Result = m.SearchUserQueryResult{
Users: make([]*m.UserSearchHitDTO, 0), Users: make([]*m.UserSearchHitDTO, 0),
} }
queryWithWildcards := "%" + query.Query + "%"
sess := x.Table("user") sess := x.Table("user")
sess.Where("email LIKE ?", query.Query+"%") if query.Query != "" {
sess.Where("email LIKE ? OR name LIKE ? OR login like ?", queryWithWildcards, queryWithWildcards, queryWithWildcards)
}
offset := query.Limit * (query.Page - 1) offset := query.Limit * (query.Page - 1)
sess.Limit(query.Limit, offset) sess.Limit(query.Limit, offset)
sess.Cols("id", "email", "name", "login", "is_admin") sess.Cols("id", "email", "name", "login", "is_admin")
...@@ -373,7 +377,12 @@ func SearchUsers(query *m.SearchUsersQuery) error { ...@@ -373,7 +377,12 @@ func SearchUsers(query *m.SearchUsersQuery) error {
} }
user := m.User{} user := m.User{}
count, err := x.Count(&user)
countSess := x.Table("user")
if query.Query != "" {
countSess.Where("email LIKE ? OR name LIKE ? OR login like ?", queryWithWildcards, queryWithWildcards, queryWithWildcards)
}
count, err := countSess.Count(&user)
query.Result.TotalCount = count query.Result.TotalCount = count
return err return err
} }
......
...@@ -19,7 +19,7 @@ func TestUserDataAccess(t *testing.T) { ...@@ -19,7 +19,7 @@ func TestUserDataAccess(t *testing.T) {
err = CreateUser(&models.CreateUserCommand{ err = CreateUser(&models.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("user", i), Login: fmt.Sprint("loginuser", i),
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
} }
...@@ -41,5 +41,53 @@ func TestUserDataAccess(t *testing.T) { ...@@ -41,5 +41,53 @@ func TestUserDataAccess(t *testing.T) {
So(len(query.Result.Users), ShouldEqual, 2) So(len(query.Result.Users), ShouldEqual, 2)
So(query.Result.TotalCount, ShouldEqual, 5) So(query.Result.TotalCount, ShouldEqual, 5)
}) })
Convey("Can return list of users matching query on user name", func() {
query := models.SearchUsersQuery{Query: "use", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 3)
So(query.Result.TotalCount, ShouldEqual, 5)
query = models.SearchUsersQuery{Query: "ser1", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 1)
So(query.Result.TotalCount, ShouldEqual, 1)
query = models.SearchUsersQuery{Query: "USER1", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 1)
So(query.Result.TotalCount, ShouldEqual, 1)
query = models.SearchUsersQuery{Query: "idontexist", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 0)
So(query.Result.TotalCount, ShouldEqual, 0)
})
Convey("Can return list of users matching query on email", func() {
query := models.SearchUsersQuery{Query: "ser1@test.com", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 1)
So(query.Result.TotalCount, ShouldEqual, 1)
})
Convey("Can return list of users matching query on login name", func() {
query := models.SearchUsersQuery{Query: "loginuser1", Page: 1, Limit: 3}
err = SearchUsers(&query)
So(err, ShouldBeNil)
So(len(query.Result.Users), ShouldEqual, 1)
So(query.Result.TotalCount, ShouldEqual, 1)
})
}) })
} }
...@@ -3,18 +3,20 @@ ...@@ -3,18 +3,20 @@
export default class AdminListUsersCtrl { export default class AdminListUsersCtrl {
users: any; users: any;
pages = []; pages = [];
perPage = 1000; perPage = 50;
page = 1; page = 1;
totalPages: number; totalPages: number;
showPaging = false; showPaging = false;
query: any;
/** @ngInject */ /** @ngInject */
constructor(private $scope, private backendSrv) { constructor(private $scope, private backendSrv) {
this.query = '';
this.getUsers(); this.getUsers();
} }
getUsers() { getUsers() {
this.backendSrv.get(`/api/users/search?perpage=${this.perPage}&page=${this.page}`).then((result) => { this.backendSrv.get(`/api/users/search?perpage=${this.perPage}&page=${this.page}&query=${this.query}`).then((result) => {
this.users = result.users; this.users = result.users;
this.page = result.page; this.page = result.page;
this.perPage = result.perPage; this.perPage = result.perPage;
......
...@@ -14,6 +14,12 @@ ...@@ -14,6 +14,12 @@
Add new user Add new user
</a> </a>
</div> </div>
<div class="search-field-wrapper pull-right width-18">
<span style="position: relative;">
<input type="text" placeholder="Find user by name/login/email" tabindex="1" give-focus="true"
ng-model="ctrl.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.getUsers()" />
</span>
</div>
<div class="admin-list-table"> <div class="admin-list-table">
<table class="filter-table form-inline"> <table class="filter-table form-inline">
<thead> <thead>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment