diff --git a/CHANGELOG.md b/CHANGELOG.md index 989dab3bb99..514a457e5db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - [Issue #1241](https://github.com/grafana/grafana/issues/1242). Timepicker: New option in timepicker (under dashboard settings), to change ``now`` to be for example ``now-1m``, usefull when you want to ignore last minute because it contains incomplete data - [Issue #171](https://github.com/grafana/grafana/issues/171). Panel: Different time periods, panels can override dashboard relative time and/or add a time shift - [Issue #1488](https://github.com/grafana/grafana/issues/1488). Dashboard: Clone dashboard / Save as +- [Issue #1458](https://github.com/grafana/grafana/issues/1458). User: persisted user option for dark or light theme (no longer an option on a dashboard) **Enhancements** - [Issue #1366](https://github.com/grafana/grafana/issues/1366). Graph & Singlestat: Support for additional units, Fahrenheit (°F) and Celsius (°C), Humidity (%H), kW, watt-hour (Wh), kilowatt-hour (kWh), velocities (m/s, km/h, mpg, knot) diff --git a/pkg/api/admin_users.go b/pkg/api/admin_users.go index 1b0c11543f5..d3fa111d333 100644 --- a/pkg/api/admin_users.go +++ b/pkg/api/admin_users.go @@ -28,7 +28,7 @@ func AdminGetUser(c *middleware.Context) { return } - result := m.UserDTO{ + result := dtos.AdminUserListItem{ Name: query.Result.Name, Email: query.Result.Email, Login: query.Result.Login, diff --git a/pkg/api/dataproxy_test.go b/pkg/api/dataproxy_test.go index 2ec7b868038..842730891ae 100644 --- a/pkg/api/dataproxy_test.go +++ b/pkg/api/dataproxy_test.go @@ -29,7 +29,7 @@ func TestDataSourceProxy(t *testing.T) { Convey("When getting influxdb datasource proxy", t, func() { ds := m.DataSource{ - Type: m.DS_INFLUXDB, + Type: m.DS_INFLUXDB_08, Url: "http://influxdb:8083", Database: "site", User: "user", diff --git a/pkg/api/dtos/models.go b/pkg/api/dtos/models.go index be985866458..d7c6c955882 100644 --- a/pkg/api/dtos/models.go +++ b/pkg/api/dtos/models.go @@ -19,6 +19,7 @@ type CurrentUser struct { Login string `json:"login"` Email string `json:"email"` Name string `json:"name"` + LightTheme bool `json:"lightTheme"` OrgRole m.RoleType `json:"orgRole"` OrgName string `json:"orgName"` IsGrafanaAdmin bool `json:"isGrafanaAdmin"` diff --git a/pkg/api/dtos/user.go b/pkg/api/dtos/user.go index 0047b3c5a98..0224ced599d 100644 --- a/pkg/api/dtos/user.go +++ b/pkg/api/dtos/user.go @@ -20,3 +20,10 @@ type AdminUpdateUserPasswordForm struct { type AdminUpdateUserPermissionsForm struct { IsGrafanaAdmin bool `json:"IsGrafanaAdmin" binding:"Required"` } + +type AdminUserListItem struct { + Email string `json:"email"` + Name string `json:"name"` + Login string `json:"login"` + IsGrafanaAdmin bool `json:"isGrafanaAdmin"` +} diff --git a/pkg/api/index.go b/pkg/api/index.go index 5cd161bb3d2..3006c54e8ab 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -17,6 +17,7 @@ func setIndexViewData(c *middleware.Context) error { Login: c.Login, Email: c.Email, Name: c.Name, + LightTheme: c.Theme == "light", OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), diff --git a/pkg/api/user.go b/pkg/api/user.go index f6fb0e41034..9d870a10a1b 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -8,7 +8,7 @@ import ( ) func GetUser(c *middleware.Context) { - query := m.GetUserInfoQuery{UserId: c.UserId} + query := m.GetUserProfileQuery{UserId: c.UserId} if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(500, "Failed to get user", err) diff --git a/pkg/models/user.go b/pkg/models/user.go index d5a3dbfacb6..cdc688d4c1f 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -48,6 +48,7 @@ type UpdateUserCommand struct { Name string `json:"name"` Email string `json:"email"` Login string `json:"login"` + Theme string `json:"theme"` UserId int64 `json:"-"` } @@ -91,9 +92,9 @@ type GetSignedInUserQuery struct { Result *SignedInUser } -type GetUserInfoQuery struct { +type GetUserProfileQuery struct { UserId int64 - Result UserDTO + Result UserProfileDTO } type SearchUsersQuery struct { @@ -120,14 +121,16 @@ type SignedInUser struct { Login string Name string Email string + Theme string ApiKeyId int64 IsGrafanaAdmin bool } -type UserDTO struct { +type UserProfileDTO struct { Email string `json:"email"` Name string `json:"name"` Login string `json:"login"` + Theme string `json:"theme"` IsGrafanaAdmin bool `json:"isGrafanaAdmin"` } diff --git a/pkg/plugins/plugins_test.go b/pkg/plugins/plugins_test.go index 5d3e10f17b4..d6a138ac76e 100644 --- a/pkg/plugins/plugins_test.go +++ b/pkg/plugins/plugins_test.go @@ -14,6 +14,6 @@ func TestPluginScans(t *testing.T) { err := scan(path) So(err, ShouldBeNil) - So(len(DataSources), ShouldEqual, 1) + So(len(DataSources), ShouldBeGreaterThan, 1) }) } diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index f839d554c34..293947c2001 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -53,8 +53,8 @@ func TestAccountDataAccess(t *testing.T) { ac2 := ac2cmd.Result Convey("Should be able to read user info projection", func() { - query := m.GetUserInfoQuery{UserId: ac1.Id} - err = GetUserInfo(&query) + query := m.GetUserProfileQuery{UserId: ac1.Id} + err = GetUserProfile(&query) So(err, ShouldBeNil) So(query.Result.Email, ShouldEqual, "ac1@test.com") diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index 5c3b69a2bb0..63977a21540 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -21,7 +21,7 @@ func init() { bus.AddHandler("sql", ChangeUserPassword) bus.AddHandler("sql", GetUserByLogin) bus.AddHandler("sql", SetUsingOrg) - bus.AddHandler("sql", GetUserInfo) + bus.AddHandler("sql", GetUserProfile) bus.AddHandler("sql", GetSignedInUser) bus.AddHandler("sql", SearchUsers) bus.AddHandler("sql", GetUserOrgList) @@ -165,6 +165,7 @@ func UpdateUser(cmd *m.UpdateUserCommand) error { Name: cmd.Name, Email: cmd.Email, Login: cmd.Login, + Theme: cmd.Theme, Updated: time.Now(), } @@ -211,7 +212,7 @@ func SetUsingOrg(cmd *m.SetUsingOrgCommand) error { }) } -func GetUserInfo(query *m.GetUserInfoQuery) error { +func GetUserProfile(query *m.GetUserProfileQuery) error { var user m.User has, err := x.Id(query.UserId).Get(&user) @@ -221,10 +222,11 @@ func GetUserInfo(query *m.GetUserInfoQuery) error { return m.ErrUserNotFound } - query.Result = m.UserDTO{ + query.Result = m.UserProfileDTO{ Name: user.Name, Email: user.Email, Login: user.Login, + Theme: user.Theme, } return err @@ -247,6 +249,7 @@ func GetSignedInUser(query *m.GetSignedInUserQuery) error { u.email as email, u.login as login, u.name as name, + u.theme as theme, org.name as org_name, org_user.role as org_role, org.id as org_id diff --git a/src/app/features/dashboard/dashboardCtrl.js b/src/app/features/dashboard/dashboardCtrl.js index 8ec13b24f2d..c9a5f119e09 100644 --- a/src/app/features/dashboard/dashboardCtrl.js +++ b/src/app/features/dashboard/dashboardCtrl.js @@ -65,11 +65,6 @@ function (angular, $, config) { $scope.setWindowTitleAndTheme = function() { window.document.title = config.window_title_prefix + $scope.dashboard.title; - $scope.contextSrv.lightTheme = $scope.dashboard.style === 'light'; - }; - - $scope.styleUpdated = function() { - $scope.contextSrv.lightTheme = $scope.dashboard.style === 'light'; }; $scope.broadcastRefresh = function() { diff --git a/src/app/features/org/partials/datasourceEdit.html b/src/app/features/org/partials/datasourceEdit.html index b0f30c214b3..542f6b742e4 100644 --- a/src/app/features/org/partials/datasourceEdit.html +++ b/src/app/features/org/partials/datasourceEdit.html @@ -9,39 +9,63 @@