mirror of
https://github.com/grafana/grafana.git
synced 2024-11-23 09:26:43 -06:00
Merge branch 'develop' into css-tweaks
This commit is contained in:
commit
0f3bf488f2
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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"`
|
||||
|
@ -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"`
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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"`
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -9,39 +9,63 @@
|
||||
<div class="page-container">
|
||||
<div class="page">
|
||||
<h2 ng-show="isNew">Add data source</h2>
|
||||
<h2 ng-show="!isNew">Edit {{current.name}}</h2>
|
||||
<h2 ng-show="!isNew">Edit data source</h2>
|
||||
|
||||
<form name="editForm">
|
||||
<div class="editor-row">
|
||||
<div class="editor-option">
|
||||
<label class="small">Data source name</label>
|
||||
<input type="text" class="input-large" ng-model='current.name' placeholder="production" required></input>
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Name
|
||||
</li>
|
||||
<li>
|
||||
<li>
|
||||
<input type="text" class="input-xlarge tight-form-input" ng-model="current.name" placeholder="my data source name" required>
|
||||
</li>
|
||||
</li>
|
||||
<li class="tight-form-item">
|
||||
Default
|
||||
<input class="cr1" id="current.isDefault" type="checkbox" ng-model="current.isDefault" ng-checked="current.isDefault">
|
||||
<label for="current.isDefault" class="cr1"></label>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Type</label>
|
||||
<select class="input-large" ng-model="current.type" ng-options="k as v.name for (k, v) in types" ng-change="typeChanged()"></select>
|
||||
</div>
|
||||
<editor-opt-bool text="Mark as default" model="current.isDefault" change="render()"></editor-opt-bool>
|
||||
</div>
|
||||
|
||||
<div class="editor-row">
|
||||
<div class="editor-option">
|
||||
<label class="small">Url</label>
|
||||
<input type="text" style="width: 450px" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Access method <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
|
||||
<select class="input-medium" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Type
|
||||
</li>
|
||||
<li>
|
||||
<select class="input-xlarge tight-form-input" ng-model="current.type" ng-options="k as v.name for (k, v) in types" ng-change="typeChanged()"></select>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form last">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Url
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="tight-form-input input-xlarge" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input>
|
||||
</li>
|
||||
<li class="tight-form-item">
|
||||
Access <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
|
||||
</li>
|
||||
<li>
|
||||
<select class="input-medium tight-form-input" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div ng-include="datasourceMeta.partials.config" ng-if="datasourceMeta.partials.config"></div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="pull-right">
|
||||
<button type="submit" class="btn btn-success" ng-show="isNew" ng-click="add()">Add</button>
|
||||
<button type="submit" class="btn btn-success" ng-show="!isNew" ng-click="update()">Update</button>
|
||||
<a class="btn btn-inverse" ng-show="!isNew" href="account/datasources">Cancel</a>
|
||||
<a class="btn btn-inverse" ng-show="!isNew" href="datasources">Cancel</a>
|
||||
</div>
|
||||
<br>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -24,7 +24,6 @@ function (angular, $) {
|
||||
|
||||
$scope.initPanelScope = function(dashboard) {
|
||||
$scope.dashboard = dashboardSrv.create(dashboard.model);
|
||||
$scope.contextSrv.lightTheme = $scope.dashboard.style === 'light';
|
||||
|
||||
$scope.row = {
|
||||
height: $(window).height() + 'px',
|
||||
|
@ -1,4 +1,4 @@
|
||||
<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fw fa-user" subnav="true">
|
||||
<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fa-fw fa-user" subnav="true">
|
||||
<ul class="nav">
|
||||
<li class="active"><a href="profile">Overview</a></li>
|
||||
<li><a href="profile/password">Change password</a></li>
|
||||
@ -8,14 +8,14 @@
|
||||
<div class="page-container">
|
||||
<div class="page">
|
||||
|
||||
<h2>Personal information</h2>
|
||||
<h2>Profile details</h2>
|
||||
|
||||
<form name="userForm">
|
||||
<div>
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 100px">
|
||||
<strong>Name</strong>
|
||||
Name
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" required ng-model="user.name" class="input-xxlarge tight-form-input last" >
|
||||
@ -23,10 +23,10 @@
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form" style="margin-top: 5px">
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 100px">
|
||||
<strong>Email</strong>
|
||||
Email
|
||||
</li>
|
||||
<li>
|
||||
<input type="email" required ng-model="user.email" class="input-xxlarge tight-form-input last" >
|
||||
@ -34,10 +34,10 @@
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form" style="margin-top: 5px">
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 100px">
|
||||
<strong>Username</strong>
|
||||
Username
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" required ng-model="user.login" class="input-xxlarge tight-form-input last" >
|
||||
@ -45,23 +45,36 @@
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 100px">
|
||||
UI Theme
|
||||
</li>
|
||||
<li>
|
||||
<select class="input-small tight-form-input" ng-model="user.theme" ng-options="f for f in ['dark', 'light']" ng-change="themeChanged()"></select>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<button type="submit" class="pull-right btn btn-success" ng-click="update()">Update</button>
|
||||
</form>
|
||||
|
||||
<h2>Your Organizations</h2>
|
||||
<h2>Organizations</h2>
|
||||
|
||||
<table class="grafana-options-table">
|
||||
<tr ng-repeat="org in orgs">
|
||||
<td style="width: 98%"><strong>Name: </strong> {{org.name}}</td>
|
||||
<td><strong>Role: </strong> {{org.role}}</td>
|
||||
<td class="nobg max-width-btns">
|
||||
<span class="btn btn-primary" ng-show="org.isUsing">
|
||||
<span class="btn btn-primary btn-mini" ng-show="org.isUsing">
|
||||
Current
|
||||
</span>
|
||||
<a ng-click="setUsingOrg(org)" class="btn btn-inverse" ng-show="!org.isUsing">
|
||||
<a ng-click="setUsingOrg(org)" class="btn btn-inverse btn-mini" ng-show="!org.isUsing">
|
||||
Select
|
||||
</a>
|
||||
</td>
|
||||
|
@ -17,6 +17,7 @@ function (angular, config) {
|
||||
$scope.getUser = function() {
|
||||
backendSrv.get('/api/user').then(function(user) {
|
||||
$scope.user = user;
|
||||
$scope.user.theme = user.theme || 'dark';
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -142,7 +142,7 @@
|
||||
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<div class="tight-form">
|
||||
<div class="tight-form last">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
<strong>Legend</strong>
|
||||
@ -176,7 +176,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="tight-form">
|
||||
<div class="tight-form last">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 100px">
|
||||
<strong>Legend values</strong>
|
||||
|
@ -25,9 +25,6 @@
|
||||
<div class="editor-option">
|
||||
<label class="small">Title</label><input type="text" class="input-large" ng-model='dashboard.title'></input>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Theme</label><select class="input-small" ng-model="dashboard.style" ng-options="f for f in ['dark','light']" ng-change="styleUpdated()"></select>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Time correction</label>
|
||||
<select ng-model="dashboard.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
|
||||
|
@ -1,11 +1,15 @@
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<h5>Elastic search details</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Index name</label>
|
||||
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Elastic search details</h2>
|
||||
|
||||
<div class="tight-form last">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Index name
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="tight-form-input input-xxlarge last" ng-model='current.database' placeholder="" required></input>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ function (angular, _, $) {
|
||||
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('influxdbFuncEditor', function($compile) {
|
||||
.directive('influxdbFuncEditor08', function($compile) {
|
||||
|
||||
var funcSpanTemplate = '<a gf-dropdown="functionMenu" class="dropdown-toggle" ' +
|
||||
'data-toggle="dropdown">{{target.function}}</a><span>(</span>';
|
||||
|
@ -1,19 +1,37 @@
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<h5>InfluxDB Details</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Database name</label>
|
||||
<input type="text" class="input-medium" required ng-model='current.database' placeholder=""></input>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">User</label>
|
||||
<input type="text" class="input-medium" ng-model='current.user' placeholder=""></input>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Password</label>
|
||||
<input type="password" class="input-medium" ng-model='current.password' placeholder=""></input>
|
||||
<h2>InfluxDB Details</h2>
|
||||
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Database
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="tight-form-input input-xxlarge last" ng-model='current.database' placeholder="" required></input>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
User
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="tight-form-input input-xxlarge last" ng-model='current.user' placeholder="" required></input>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form last">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 80px">
|
||||
Password
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="tight-form-input input-xxlarge last" ng-model='current.password' placeholder="" required></input>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -117,7 +117,7 @@
|
||||
select
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<span influxdb-func-editor class="tight-form-item tight-form-func">
|
||||
<span influxdb-func-editor08 class="tight-form-item tight-form-func">
|
||||
</span>
|
||||
</li>
|
||||
|
||||
|
@ -19,7 +19,7 @@ function (angular, _, kbn) {
|
||||
}
|
||||
|
||||
if (!$scope.target.downsampleAggregator) {
|
||||
$scope.target.downsampleAggregator = 'sum';
|
||||
$scope.target.downsampleAggregator = 'avg';
|
||||
}
|
||||
|
||||
$scope.$on('typeahead-updated', function() {
|
||||
|
@ -19,6 +19,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.spaced-form {
|
||||
.tight-form {
|
||||
margin: 7px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.borderless {
|
||||
.tight-form-item,
|
||||
.tight-form-input {
|
||||
@ -140,13 +146,13 @@ input[type=text].tight-form-clear-input {
|
||||
[type=email],
|
||||
[type=number],
|
||||
[type=password] {
|
||||
|
||||
&.tight-form-input {
|
||||
border: none;
|
||||
border-right: 1px solid @grafanaTargetSegmentBorder;
|
||||
margin: 0px;
|
||||
border-radius: 0;
|
||||
padding: 8px 4px;
|
||||
padding: 18px 6px;
|
||||
box-sizing: border-box;
|
||||
&.last {
|
||||
border-right: none;
|
||||
}
|
||||
@ -163,7 +169,7 @@ select.tight-form-input {
|
||||
margin: 0px;
|
||||
border-radius: 0;
|
||||
height: 36px;
|
||||
padding: 8px 5px;
|
||||
padding: 8px 3px;
|
||||
&.last {
|
||||
border-right: none;
|
||||
}
|
||||
|
@ -7,7 +7,12 @@
|
||||
|
||||
<title>Grafana</title>
|
||||
|
||||
<link rel="stylesheet" href="[[.AppSubUrl]]/css/grafana.dark.min.css" title="Dark">
|
||||
[[if .User.LightTheme]]
|
||||
<link rel="stylesheet" href="[[.AppSubUrl]]/css/grafana.light.min.css">
|
||||
[[else]]
|
||||
<link rel="stylesheet" href="[[.AppSubUrl]]/css/grafana.dark.min.css">
|
||||
[[end]]
|
||||
|
||||
<link rel="icon" type="image/png" href="[[.AppSubUrl]]/img/fav32.png">
|
||||
<base href="[[.AppSubUrl]]/" />
|
||||
|
||||
@ -19,14 +24,9 @@
|
||||
<script src="[[.AppSubUrl]]/public/vendor/require/require.js"></script>
|
||||
<script src="[[.AppSubUrl]]/public/app/components/require.backend.js"></script>
|
||||
<!-- endbuild -->
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body ng-cloak ng-controller="GrafanaCtrl" ng-class="{'sidemenu-open': contextSrv.sidemenu}">
|
||||
|
||||
<link rel="stylesheet" href="[[.AppSubUrl]]/css/grafana.light.min.css" ng-if="contextSrv.lightTheme">
|
||||
|
||||
<div class="sidemenu-canvas">
|
||||
|
||||
<aside class="sidemenu-wrapper" ng-if="contextSrv.sidemenu">
|
||||
|
Loading…
Reference in New Issue
Block a user