Merge branch 'master' into v4.2.x

This commit is contained in:
Daniel Lee 2017-03-08 17:09:33 +01:00
commit 61844cb0da
6 changed files with 88 additions and 8 deletions

View File

@ -1,15 +1,28 @@
# 4.3.0 (unreleased)
## Minor Enchancements
* **Threema**: Add emoji to Threema alert notifications [#7676](https://github.com/grafana/grafana/pull/7676) thx [@dbrgn](https://github.com/dbrgn)
* **Panels**: Support dm3 unit [#7695](https://github.com/grafana/grafana/issues/7695) thx [@mitjaziv](https://github.com/mitjaziv)
# 4.2.0-beta2 (unreleased)
## Minor Enhancements
* **Templates**: Prevent use of the prefix `__` for templates in web UI [#7678](https://github.com/grafana/grafana/issues/7678)
* **Threema**: Add emoji to Threema alert notifications [#7676](https://github.com/grafana/grafana/pull/7676) thx [@dbrgn](https://github.com/dbrgn)
* **Panels**: Support dm3 unit [#7695](https://github.com/grafana/grafana/issues/7695) thx [@mitjaziv](https://github.com/mitjaziv)
* **Docs**: Added some details about Sessions in Postgres [#7694](https://github.com/grafana/grafana/pull/7694) thx [@rickard-von-essen](https://github.com/rickard-von-essen)
* **Influxdb**: Allow commas in template variables [#7681](https://github.com/grafana/grafana/issues/7681) thx [@thuck](https://github.com/thuck)
* **Cloudwatch**: stop using deprecated session.New() [#7736](https://github.com/grafana/grafana/issues/7736) thx [@mtanda](https://github.com/mtanda)
* **OpenTSDB**: Pass dropcounter rate option if no max counter and no reset value or reset value as 0 is specified [#7743](https://github.com/grafana/grafana/pull/7743) thx [@r4um](https://github.com/r4um)
* **Templating**: support full resolution for $interval variable [#7696](https://github.com/grafana/grafana/pull/7696) thx [@mtanda](https://github.com/mtanda)
* **Elasticsearch**: Unique Count on string fields in ElasticSearch [#3536](https://github.com/grafana/grafana/issues/3536), thx [@pyro2927](https://github.com/pyro2927)
* **Templating**: Data source template variable that refers to other variable in regex filter [#6365](https://github.com/grafana/grafana/issues/6365) thx [@rlodge](https://github.com/rlodge)
* **Admin**: Global User List: add search and pagination [#7469](https://github.com/grafana/grafana/issues/7469)
## Bugfixes
* **Webhook**: Use proxy settings from environment variables [#7710](https://github.com/grafana/grafana/issues/7710)
* **Panels**: Deleting a dashboard with unsaved changes raises an error message [#7591](https://github.com/grafana/grafana/issues/7591) thx [@thuck](https://github.com/thuck)
* **Influxdb**: Query builder detects regex to easily for measurement [#7276](https://github.com/grafana/grafana/issues/7276) thx [@thuck](https://github.com/thuck)
* **Docs**: router_logging not documented [#7723](https://github.com/grafana/grafana/issues/7723)
* **Alerting**: Spelling mistake [#7739](https://github.com/grafana/grafana/pull/7739) thx [@woutersmit](https://github.com/woutersmit)
* **Alerting**: Graph legend scrolls to top when an alias is toggled/clicked [#7680](https://github.com/grafana/grafana/issues/7680) thx [@p4ddy1](https://github.com/p4ddy1)
# 4.2.0-beta1 (2017-02-27)

View File

@ -239,7 +239,9 @@ func searchUser(c *middleware.Context) (*m.SearchUsersQuery, error) {
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 {
return nil, err
}

View File

@ -363,8 +363,12 @@ func SearchUsers(query *m.SearchUsersQuery) error {
query.Result = m.SearchUserQueryResult{
Users: make([]*m.UserSearchHitDTO, 0),
}
queryWithWildcards := "%" + query.Query + "%"
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)
sess.Limit(query.Limit, offset)
sess.Cols("id", "email", "name", "login", "is_admin")
@ -373,7 +377,12 @@ func SearchUsers(query *m.SearchUsersQuery) error {
}
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
return err
}

View File

@ -19,7 +19,7 @@ func TestUserDataAccess(t *testing.T) {
err = CreateUser(&models.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
})
So(err, ShouldBeNil)
}
@ -41,5 +41,53 @@ func TestUserDataAccess(t *testing.T) {
So(len(query.Result.Users), ShouldEqual, 2)
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)
})
})
}

View File

@ -3,18 +3,20 @@
export default class AdminListUsersCtrl {
users: any;
pages = [];
perPage = 1000;
perPage = 50;
page = 1;
totalPages: number;
showPaging = false;
query: any;
/** @ngInject */
constructor(private $scope, private backendSrv) {
this.query = '';
this.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.page = result.page;
this.perPage = result.perPage;

View File

@ -14,6 +14,12 @@
Add new user
</a>
</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">
<table class="filter-table form-inline">
<thead>