Merge branch 'master' of github.com:grafana/grafana

Conflicts:
	public/sass/.sass-lint.yml
	tasks/options/sasslint.js
This commit is contained in:
Torkel Ödegaard 2016-02-22 05:52:02 +01:00
commit 145c14ed57
74 changed files with 936 additions and 553 deletions

View File

@ -36,7 +36,7 @@
"grunt-sass": "^1.1.0", "grunt-sass": "^1.1.0",
"grunt-string-replace": "~1.2.1", "grunt-string-replace": "~1.2.1",
"grunt-systemjs-builder": "^0.2.5", "grunt-systemjs-builder": "^0.2.5",
"grunt-tslint": "^3.0.1", "grunt-tslint": "^3.0.2",
"grunt-typescript": "^0.8.0", "grunt-typescript": "^0.8.0",
"grunt-usemin": "3.0.0", "grunt-usemin": "3.0.0",
"jshint-stylish": "~0.1.5", "jshint-stylish": "~0.1.5",
@ -74,7 +74,9 @@
"lodash": "^2.4.1", "lodash": "^2.4.1",
"sinon": "1.16.1", "sinon": "1.16.1",
"systemjs-builder": "^0.15.7", "systemjs-builder": "^0.15.7",
"tslint": "^3.2.1", "tether": "^1.2.0",
"tether-drop": "^1.4.2",
"tslint": "^3.4.0",
"typescript": "^1.7.5" "typescript": "^1.7.5"
} }
} }

View File

@ -2,6 +2,7 @@ package api
import ( import (
"github.com/go-macaron/binding" "github.com/go-macaron/binding"
"github.com/grafana/grafana/pkg/api/avatar"
"github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
@ -224,6 +225,10 @@ func Register(r *macaron.Macaron) {
// rendering // rendering
r.Get("/render/*", reqSignedIn, RenderToPng) r.Get("/render/*", reqSignedIn, RenderToPng)
// Gravatar service.
avt := avatar.CacheServer()
r.Get("/avatar/:hash", avt.ServeHTTP)
InitAppPluginRoutes(r) InitAppPluginRoutes(r)
r.NotFound(NotFoundHandler) r.NotFound(NotFoundHandler)

253
pkg/api/avatar/avatar.go Normal file
View File

@ -0,0 +1,253 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Code from https://github.com/gogits/gogs/blob/v0.7.0/modules/avatar/avatar.go
package avatar
import (
"bufio"
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/setting"
)
var gravatarSource string
func UpdateGravatarSource() {
srcCfg := "//secure.gravatar.com/avatar/"
gravatarSource = srcCfg
if strings.HasPrefix(gravatarSource, "//") {
gravatarSource = "http:" + gravatarSource
} else if !strings.HasPrefix(gravatarSource, "http://") &&
!strings.HasPrefix(gravatarSource, "https://") {
gravatarSource = "http://" + gravatarSource
}
}
// hash email to md5 string
// keep this func in order to make this package independent
func HashEmail(email string) string {
// https://en.gravatar.com/site/implement/hash/
email = strings.TrimSpace(email)
email = strings.ToLower(email)
h := md5.New()
h.Write([]byte(email))
return hex.EncodeToString(h.Sum(nil))
}
// Avatar represents the avatar object.
type Avatar struct {
hash string
reqParams string
data *bytes.Buffer
notFound bool
timestamp time.Time
}
func New(hash string) *Avatar {
return &Avatar{
hash: hash,
reqParams: url.Values{
"d": {"404"},
"size": {"200"},
"r": {"pg"}}.Encode(),
}
}
func (this *Avatar) Expired() bool {
return time.Since(this.timestamp) > (time.Minute * 10)
}
func (this *Avatar) Encode(wr io.Writer) error {
_, err := wr.Write(this.data.Bytes())
return err
}
func (this *Avatar) Update() (err error) {
select {
case <-time.After(time.Second * 3):
err = fmt.Errorf("get gravatar image %s timeout", this.hash)
case err = <-thunder.GoFetch(gravatarSource+this.hash+"?"+this.reqParams, this):
}
return err
}
type service struct {
notFound *Avatar
cache map[string]*Avatar
}
func (this *service) mustInt(r *http.Request, defaultValue int, keys ...string) (v int) {
for _, k := range keys {
if _, err := fmt.Sscanf(r.FormValue(k), "%d", &v); err == nil {
defaultValue = v
}
}
return defaultValue
}
func (this *service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
hash := urlPath[strings.LastIndex(urlPath, "/")+1:]
var avatar *Avatar
if avatar, _ = this.cache[hash]; avatar == nil {
avatar = New(hash)
}
if avatar.Expired() {
if err := avatar.Update(); err != nil {
log.Trace("avatar update error: %v", err)
}
}
if avatar.notFound {
avatar = this.notFound
} else {
this.cache[hash] = avatar
}
w.Header().Set("Content-Type", "image/jpeg")
w.Header().Set("Content-Length", strconv.Itoa(len(avatar.data.Bytes())))
w.Header().Set("Cache-Control", "private, max-age=3600")
if err := avatar.Encode(w); err != nil {
log.Warn("avatar encode error: %v", err)
w.WriteHeader(500)
}
}
func CacheServer() http.Handler {
UpdateGravatarSource()
return &service{
notFound: newNotFound(),
cache: make(map[string]*Avatar),
}
}
func newNotFound() *Avatar {
avatar := &Avatar{}
// load transparent png into buffer
path := filepath.Join(setting.StaticRootPath, "img", "transparent.png")
if data, err := ioutil.ReadFile(path); err != nil {
log.Error(3, "Failed to read transparent.png, %v", path)
} else {
avatar.data = bytes.NewBuffer(data)
}
return avatar
}
// thunder downloader
var thunder = &Thunder{QueueSize: 10}
type Thunder struct {
QueueSize int // download queue size
q chan *thunderTask
once sync.Once
}
func (t *Thunder) init() {
if t.QueueSize < 1 {
t.QueueSize = 1
}
t.q = make(chan *thunderTask, t.QueueSize)
for i := 0; i < t.QueueSize; i++ {
go func() {
for {
task := <-t.q
task.Fetch()
}
}()
}
}
func (t *Thunder) Fetch(url string, avatar *Avatar) error {
t.once.Do(t.init)
task := &thunderTask{
Url: url,
Avatar: avatar,
}
task.Add(1)
t.q <- task
task.Wait()
return task.err
}
func (t *Thunder) GoFetch(url string, avatar *Avatar) chan error {
c := make(chan error)
go func() {
c <- t.Fetch(url, avatar)
}()
return c
}
// thunder download
type thunderTask struct {
Url string
Avatar *Avatar
sync.WaitGroup
err error
}
func (this *thunderTask) Fetch() {
this.err = this.fetch()
this.Done()
}
var client = &http.Client{}
func (this *thunderTask) fetch() error {
this.Avatar.timestamp = time.Now()
log.Debug("avatar.fetch(fetch new avatar): %s", this.Url)
req, _ := http.NewRequest("GET", this.Url, nil)
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/jpeg,image/png,*/*;q=0.8")
req.Header.Set("Accept-Encoding", "deflate,sdch")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36")
resp, err := client.Do(req)
if err != nil {
this.Avatar.notFound = true
return fmt.Errorf("gravatar unreachable, %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
this.Avatar.notFound = true
return fmt.Errorf("status code: %d", resp.StatusCode)
}
this.Avatar.data = &bytes.Buffer{}
writer := bufio.NewWriter(this.Avatar.data)
if _, err = io.Copy(writer, resp.Body); err != nil {
return err
}
return nil
}

View File

@ -7,6 +7,7 @@ import (
"time" "time"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
) )
type LoginCommand struct { type LoginCommand struct {
@ -89,5 +90,5 @@ func GetGravatarUrl(text string) string {
hasher := md5.New() hasher := md5.New()
hasher.Write([]byte(strings.ToLower(text))) hasher.Write([]byte(strings.ToLower(text)))
return fmt.Sprintf("https://secure.gravatar.com/avatar/%x?s=90&default=mm", hasher.Sum(nil)) return fmt.Sprintf(setting.AppSubUrl+"/avatar/%x", hasher.Sum(nil))
} }

View File

@ -36,7 +36,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
} }
if setting.DisableGravatar { if setting.DisableGravatar {
data.User.GravatarUrl = setting.AppSubUrl + "/public/img/user_profile.png" data.User.GravatarUrl = setting.AppSubUrl + "/public/img/transparent.png"
} }
if len(data.User.Name) == 0 { if len(data.User.Name) == 0 {
@ -105,6 +105,12 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
Text: "Admin", Text: "Admin",
Icon: "fa fa-fw fa-cogs", Icon: "fa fa-fw fa-cogs",
Url: setting.AppSubUrl + "/admin", Url: setting.AppSubUrl + "/admin",
Children: []*dtos.NavLink{
{Text: "Global Users", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/users"},
{Text: "Global Orgs", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/orgs"},
{Text: "Server Settings", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/settings"},
{Text: "Server Stats", Icon: "fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/stats"},
},
}) })
} }

View File

@ -47,6 +47,20 @@ export class GrafanaApp {
this.registerFunctions.factory = $provide.factory; this.registerFunctions.factory = $provide.factory;
this.registerFunctions.service = $provide.service; this.registerFunctions.service = $provide.service;
this.registerFunctions.filter = $filterProvider.register; this.registerFunctions.filter = $filterProvider.register;
$provide.decorator("$http", ["$delegate", "$templateCache", function($delegate, $templateCache) {
var get = $delegate.get;
$delegate.get = function(url, config) {
if (url.match(/\.html$/)) {
// some template's already exist in the cache
if (!$templateCache.get(url)) {
url += "?v=" + new Date().getTime();
}
}
return get(url, config);
};
return $delegate;
}]);
}); });
this.ngModuleDependencies = [ this.ngModuleDependencies = [

View File

@ -1,19 +1,16 @@
<div class="navbar-inner"> <div class="navbar-inner">
<div class="top-nav-btn top-nav-menu-btn"> <a class="navbar-brand-btn pointer" ng-click="ctrl.contextSrv.toggleSideMenu()">
<a class="pointer" ng-click="ctrl.contextSrv.toggleSideMenu()"> <span class="navbar-brand-btn-background">
<span class="top-nav-logo-background"> <img src="public/img/grafana_icon.svg"></img>
<img class="logo-icon" src="public/img/grafana_icon.svg"></img> </span>
</span> <i class="icon-gf icon-gf-grafana_wordmark"></i>
<i class="icon-gf icon-gf-grafana_wordmark"></i> <i class="fa fa-caret-down"></i>
<i class="fa fa-caret-down"></i> </a>
</a>
</div>
<a href="{{::ctrl.titleUrl}}" class="navbar-page-btn" ng-show="ctrl.title">
<div ng-if="ctrl.title"> <i class="{{::ctrl.icon}}"></i>
<nav-button title="{{ctrl.title}}" title-url="{{ctrl.titleUrl}}" icon="{{ctrl.icon}}"> {{::ctrl.title}}
</nav-button> </a>
</div>
<div ng-transclude></div> <div ng-transclude></div>
</div> </div>

View File

@ -30,28 +30,4 @@ export function navbarDirective() {
}; };
} }
var navButtonTemplate = `
<div class="top-nav-btn dashnav-dashboards-btn">
<a href="{{::titleUrl}}">
<i class="{{::icon}}"></i>
<span class="dashboard-title">{{::title}}</span>
</a>
</div>
`;
function navButton() {
return {
restrict: 'E',
template: navButtonTemplate,
scope: {
title: "@",
titleUrl: "@",
},
link: function(scope, elem, attrs, ctrl) {
scope.icon = attrs.icon;
}
};
}
coreModule.directive('navbar', navbarDirective); coreModule.directive('navbar', navbarDirective);
coreModule.directive('navButton', navButton);

View File

@ -3,7 +3,10 @@
<li class="sidemenu-org-section" ng-if="ctrl.isSignedIn" class="dropdown"> <li class="sidemenu-org-section" ng-if="ctrl.isSignedIn" class="dropdown">
<div class="sidemenu-org"> <div class="sidemenu-org">
<div class="sidemenu-org-avatar"> <div class="sidemenu-org-avatar">
<img ng-src="{{ctrl.user.gravatarUrl}}"> <img ng-if="ctrl.user.gravatarUrl" ng-src="{{ctrl.user.gravatarUrl}}">
<span class="sidemenu-org-avatar--missing">
<i class="fa fa-fw fa-user"></i>
</span>
</div> </div>
<div class="sidemenu-org-details"> <div class="sidemenu-org-details">
<span class="sidemenu-org-user sidemenu-item-text">{{ctrl.user.name}}</span> <span class="sidemenu-org-user sidemenu-item-text">{{ctrl.user.name}}</span>

View File

@ -186,7 +186,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
.when('/global-alerts', { .when('/global-alerts', {
templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html', templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html',
}) })
.when('/styleguide', { .when('/styleguide/:page?', {
controller: 'StyleGuideCtrl', controller: 'StyleGuideCtrl',
controllerAs: 'ctrl', controllerAs: 'ctrl',
templateUrl: 'public/app/features/styleguide/styleguide.html', templateUrl: 'public/app/features/styleguide/styleguide.html',

View File

@ -24,5 +24,9 @@
View Server Stats View Server Stats
</a> </a>
<a class="btn btn-inverse" href="styleguide">
Style guide
</a>
</div> </div>

View File

@ -2,14 +2,14 @@
</navbar> </navbar>
<div class="page-container"> <div class="page-container">
<div class="page-wide"> <div class="page-header">
<h1>Plugins</h1> <h1>Plugins</h1>
</div>
<div ng-if="!ctrl.apps">
<em>No apps defined</em>
</div>
<div ng-if="!ctrl.apps"> <ul class="filter-list">
<em>No apps defined</em>
</div>
<ul class="filter-list">
<li ng-repeat="app in ctrl.apps"> <li ng-repeat="app in ctrl.apps">
<ul class="filter-list-card"> <ul class="filter-list-card">
<li class="filter-list-card-image"> <li class="filter-list-card-image">
@ -43,6 +43,5 @@
</li> </li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div>
</div> </div>

View File

@ -1,14 +1,13 @@
<navbar icon="fa fa-fw fa-cubes" title="{{ctrl.appModel.name}}" title-url="apps/{{ctrl.appId}}/edit"> <navbar icon="icon-gf icon-gf-apps" title="{{ctrl.appModel.name}}" title-url="apps/{{ctrl.appId}}/edit">
</navbar> </navbar>
<div class="page-container"> <div class="page-container">
<div class="page-wide"> <div class="page-header">
<h1>{{ctrl.page.name}}</h1> <h1>{{ctrl.page.name}}</h1>
</div>
<div ng-if="ctrl.page"> <div ng-if="ctrl.page">
<plugin-component type="app-page"> <plugin-component type="app-page">
</plugin-component> </plugin-component>
</div>
</div> </div>
</div> </div>

View File

@ -1,22 +1,18 @@
<navbar> <navbar>
<div class="top-nav-btn dashnav-dashboards-btn" ng-if="!dashboardMeta.isSnapshot"> <a class="pointer navbar-page-btn" ng-show="!dashboardMeta.isSnapshot" ng-click="openSearch()">
<a class="pointer" ng-click="openSearch()"> <i class="icon-gf icon-gf-dashboard"></i>
<i class="icon-gf icon-gf-dashboard"></i> <span>{{dashboard.title}}</span>
<span class="dashboard-title">{{dashboard.title}}</span> <i class="fa fa-caret-down"></i>
<i class="fa fa-caret-down"></i> </a>
</a>
</div>
<div class="top-nav-btn dashnav-dashboards-btn" ng-if="dashboardMeta.isSnapshot"> <a class="pointer navbar-page-btn" ng-if="dashboardMeta.isSnapshot" bs-tooltip="titleTooltip" data-placement="bottom" ng-click="openSearch()">
<a class="pointer" bs-tooltip="titleTooltip" data-placement="bottom" ng-click="openSearch()"> <i class="icon-gf icon-gf-snapshot"></i>
<i class="icon-gf icon-gf-snapshot"></i> <span>
<span class="dashboard-title"> {{dashboard.title}}
{{dashboard.title}} <em class="small">&nbsp;&nbsp;(snapshot)</em>
<em class="small">&nbsp;&nbsp;(snapshot)</em> </span>
</span> </a>
</a>
</div>
<ul class="nav pull-left dashnav-action-icons"> <ul class="nav pull-left dashnav-action-icons">
<li ng-show="dashboardMeta.canStar"> <li ng-show="dashboardMeta.canStar">

View File

@ -4,7 +4,7 @@
<label class="small">From:</label> <label class="small">From:</label>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<input type="text" class="gf-form-input input-large" ng-model="ctrl.timeRaw.from" input-datetime> <input type="text" class="gf-form-input input-large" ng-model="ctrl.timeRaw.from" input-datetime>
</div> </div>
<div class="gf-form"> <div class="gf-form">
@ -21,7 +21,7 @@
<label class="small">To:</label> <label class="small">To:</label>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<input type="text" class="gf-form-input input-large" ng-model="ctrl.timeRaw.to" input-datetime> <input type="text" class="gf-form-input input-large" ng-model="ctrl.timeRaw.to" input-datetime>
</div> </div>
<div class="gf-form"> <div class="gf-form">
@ -35,15 +35,13 @@
<datepicker ng-model="ctrl.absolute.toJs" class="gf-timepicker-component" show-weeks="false" ng-change="ctrl.absoluteToChanged()"></datepicker> <datepicker ng-model="ctrl.absolute.toJs" class="gf-timepicker-component" show-weeks="false" ng-change="ctrl.absoluteToChanged()"></datepicker>
</div> </div>
<label class="small">Refreshing every:</label> <label class="small">Refreshing every:</label>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<select ng-model="ctrl.refresh.value" class="gf-form-input input-medium" ng-options="f.value as f.text for f in ctrl.refresh.options"></select> <select ng-model="ctrl.refresh.value" class="gf-form-input input-medium" ng-options="f.value as f.text for f in ctrl.refresh.options"></select>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<button type="submit" class="btn gf-form-btn btn-primary" ng-click="ctrl.applyCustom();" ng-disabled="!timeForm.$valid">Apply</button> <button type="submit" class="btn gf-form-btn btn-secondary" ng-click="ctrl.applyCustom();" ng-disabled="!timeForm.$valid">Apply</button>
</div> </div>
</div> </div>

View File

@ -13,14 +13,16 @@
<form name="editForm"> <form name="editForm">
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Name</span> <span class="gf-form-label width-7">Name</span>
<input class="gf-form-input gf-size-max-xxl" type="text" ng-model="current.name" placeholder="My data source name" required> <input class="gf-form-input max-width-21" type="text" ng-model="current.name" placeholder="My data source name" required>
<editor-checkbox text="Default" model="current.isDefault"></editor-checkbox> <editor-checkbox text="Default" model="current.isDefault"></editor-checkbox>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Type</span> <span class="gf-form-label width-7">Type</span>
<select class="gf-form-input gf-size-auto" ng-model="current.type" ng-options="k as v.name for (k, v) in types" ng-change="typeChanged()"></select> <div class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="current.type" ng-options="k as v.name for (k, v) in types" ng-change="typeChanged()"></select>
</div>
</div> </div>
</div> </div>
@ -41,7 +43,7 @@
<div class="gf-form-button-row"> <div class="gf-form-button-row">
<button type="submit" class="btn btn-success" ng-show="isNew" ng-click="saveChanges()">Add</button> <button type="submit" class="btn btn-success" ng-show="isNew" ng-click="saveChanges()">Add</button>
<button type="submit" class="btn btn-success" ng-show="!isNew" ng-click="saveChanges()">Save</button> <button type="submit" class="btn btn-success" ng-show="!isNew" ng-click="saveChanges()">Save</button>
<button type="submit" class="btn btn-primary" ng-show="!isNew" ng-click="saveChanges(true)"> <button type="submit" class="btn btn-secondary" ng-show="!isNew" ng-click="saveChanges(true)">
Test Connection Test Connection
</button> </button>
<a class="btn btn-link" href="datasources">Cancel</a> <a class="btn btn-link" href="datasources">Cancel</a>

View File

@ -4,19 +4,19 @@
<h3 class="page-heading">Http settings</h3> <h3 class="page-heading">Http settings</h3>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Url</span> <span class="gf-form-label width-7">Url</span>
<input class="gf-form-input gf-size-max-xxl" type="text" ng-model='current.url' placeholder="http://my.server.com:8080" ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" required></input> <input class="gf-form-input max-width-21" type="text" ng-model='current.url' placeholder="http://my.server.com:8080" ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" required></input>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm"> <span class="gf-form-label width-7">
Access <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</tip> Access <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</tip>
</span> </span>
<select class="gf-form-input gf-size-auto" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select> <select class="gf-form-input gf-size-auto" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm"> <span class="gf-form-label width-7">
Http Auth Http Auth
</span> </span>
<editor-checkbox text="Basic Auth" model="current.basicAuth"></editor-checkbox> <editor-checkbox text="Basic Auth" model="current.basicAuth"></editor-checkbox>
@ -24,17 +24,17 @@
</div> </div>
<div class="gf-form" ng-if="current.basicAuth"> <div class="gf-form" ng-if="current.basicAuth">
<span class="gf-form-label gf-size-sm"> <span class="gf-form-label width-7">
User User
</span> </span>
<input class="gf-form-input gf-size-max-xxl" type="text" ng-model='current.basicAuthUser' placeholder="user" required></input> <input class="gf-form-input max-width-21" type="text" ng-model='current.basicAuthUser' placeholder="user" required></input>
</div> </div>
<div class="gf-form" ng-if="current.basicAuth"> <div class="gf-form" ng-if="current.basicAuth">
<span class="gf-form-label gf-size-sm"> <span class="gf-form-label width-7">
Passord Passord
</span> </span>
<input class="gf-form-input gf-size-max-xxl" type="password" ng-model='current.basicAuthPassword' placeholder="password" required></input> <input class="gf-form-input max-width-21" type="password" ng-model='current.basicAuthPassword' placeholder="password" required></input>
</div> </div>
</div> </div>

View File

@ -33,7 +33,7 @@
<tr ng-repeat="ds in ctrl.datasources"> <tr ng-repeat="ds in ctrl.datasources">
<td> <td>
<a href="datasources/edit/{{ds.id}}"> <a href="datasources/edit/{{ds.id}}">
<i class="fa fa-database"></i> &nbsp; {{ds.name}} <i class="icon-gf inline-icon-gf icon-gf-datasources"></i> &nbsp; {{ds.name}}
</a> </a>
</td> </td>
<td> <td>
@ -41,7 +41,7 @@
</td> </td>
<td class="text-center"> <td class="text-center">
<span ng-if="ds.isDefault"> <span ng-if="ds.isDefault">
<span class="label label-info">default</span> <span class="btn btn-secondary btn-mini">default</span>
</span> </span>
</td> </td>
<td class="text-right"> <td class="text-right">

View File

@ -19,15 +19,15 @@
<form name="inviteForm"> <form name="inviteForm">
<div class="gf-form-inline" ng-repeat="invite in invites"> <div class="gf-form-inline" ng-repeat="invite in invites">
<div class="gf-form gf-size-max-xxl"> <div class="gf-form max-width-21">
<span class="gf-form-label">Email or Username</span> <span class="gf-form-label">Email or Username</span>
<input type="text" ng-model="invite.loginOrEmail" required class="gf-form-input" placeholder="email@test.com"> <input type="text" ng-model="invite.loginOrEmail" required class="gf-form-input" placeholder="email@test.com">
</div> </div>
<div class="gf-form gf-size-max-xl"> <div class="gf-form max-width-14">
<span class="gf-form-label">Name</span> <span class="gf-form-label">Name</span>
<input type="text" ng-model="invite.name" class="gf-form-input" placeholder="name (optional)"> <input type="text" ng-model="invite.name" class="gf-form-input" placeholder="name (optional)">
</div> </div>
<div class="gf-form gf-size-max-lg"> <div class="gf-form max-width-10">
<span class="gf-form-label">Role</span> <span class="gf-form-label">Role</span>
<select ng-model="invite.role" class="gf-form-input" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']"> <select ng-model="invite.role" class="gf-form-input" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']">
</select> </select>

View File

@ -1,4 +1,4 @@
<navbar icon="icon-gf icon-gf-users" title="Organization"> <navbar icon="icon-gf icon-gf-users" title="Organization" title-url="org">
</navbar> </navbar>
<div class="page-container"> <div class="page-container">
@ -9,7 +9,7 @@
<h3 class="page-heading">Add new</h3> <h3 class="page-heading">Add new</h3>
<form name="addTokenForm" class="gf-form-group"> <form name="addTokenForm" class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxl"> <div class="gf-form max-width-21">
<span class="gf-form-label">Add a key</span> <span class="gf-form-label">Add a key</span>
<input type="text" class="gf-form-input" ng-model='token.name' placeholder="Name"></input> <input type="text" class="gf-form-input" ng-model='token.name' placeholder="Name"></input>
</div> </div>

View File

@ -9,8 +9,8 @@
<h3 class="page-heading">General</h3> <h3 class="page-heading">General</h3>
<form name="orgForm" class="gf-form-group"> <form name="orgForm" class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-xs">Name</span> <span class="gf-form-label width-6">Name</span>
<input class="gf-form-input" type="text" required ng-model="org.name"> <input class="gf-form-input" type="text" required ng-model="org.name">
</div> </div>
<div class="gf-form"> <div class="gf-form">
@ -24,34 +24,34 @@
<form name="addressForm" class="gf-form-group"> <form name="addressForm" class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">Address1</span> <span class="gf-form-label width-7">Address1</span>
<input class="gf-form-input" type="text" ng-model="address.address1"> <input class="gf-form-input" type="text" ng-model="address.address1">
</div> </div>
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">Address2</span> <span class="gf-form-label width-7">Address2</span>
<input class="gf-form-input" type="text" ng-model="address.address2"> <input class="gf-form-input" type="text" ng-model="address.address2">
</div> </div>
</div> </div>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">City</span> <span class="gf-form-label width-7">City</span>
<input class="gf-form-input" type="text" ng-model="address.city"> <input class="gf-form-input" type="text" ng-model="address.city">
</div> </div>
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">Postal code</span> <span class="gf-form-label width-7">Postal code</span>
<input class="gf-form-input" type="text" ng-model="address.zipCode"> <input class="gf-form-input" type="text" ng-model="address.zipCode">
</div> </div>
</div> </div>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">State</span> <span class="gf-form-label width-7">State</span>
<input class="gf-form-input" type="text" ng-model="address.state"> <input class="gf-form-input" type="text" ng-model="address.state">
</div> </div>
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-sm">Country</span> <span class="gf-form-label width-7">Country</span>
<input class="gf-form-input" type="text" ng-model="address.country"> <input class="gf-form-input" type="text" ng-model="address.country">
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<navbar icon="icon-gf icon-gf-users" title="Organization Users"> <navbar icon="icon-gf icon-gf-users" title="Organization Users" title-url="org">
</navbar> </navbar>
<div class="page-container"> <div class="page-container">

View File

@ -2,8 +2,9 @@ define([
'angular', 'angular',
'jquery', 'jquery',
'lodash', 'lodash',
'tether',
], ],
function (angular, $, _) { function (angular, $, _, Tether) {
'use strict'; 'use strict';
angular angular
@ -79,6 +80,7 @@ function (angular, $, _) {
var ctrl = $scope.ctrl; var ctrl = $scope.ctrl;
var timeout = null; var timeout = null;
var $menu = null; var $menu = null;
var teather;
elem.append($link); elem.append($link);
@ -105,6 +107,7 @@ function (angular, $, _) {
} }
if (menuScope) { if (menuScope) {
teather.destroy();
$menu.unbind(); $menu.unbind();
$menu.remove(); $menu.remove();
menuScope.$destroy(); menuScope.$destroy();
@ -153,23 +156,19 @@ function (angular, $, _) {
$scope.$apply(function() { $scope.$apply(function() {
$compile($menu.contents())(menuScope); $compile($menu.contents())(menuScope);
var menuWidth = $menu[0].offsetWidth; teather = new Tether({
var menuHeight = $menu[0].offsetHeight; element: $menu,
target: $panelContainer,
var windowWidth = $(window).width(); attachment: 'bottom center',
var panelLeftPos = $(elem).offset().left; targetAttachment: 'top center',
var panelWidth = $(elem).width(); constraints: [
{
var menuLeftPos = (panelWidth / 2) - (menuWidth/2); to: 'window',
var stickingOut = panelLeftPos + menuLeftPos + menuWidth - windowWidth; attachment: 'together',
if (stickingOut > 0) { pin: true
menuLeftPos -= stickingOut + 10; }
} ]
if (panelLeftPos + menuLeftPos < 0) { });
menuLeftPos = 0;
}
$menu.css({'left': menuLeftPos, top: -menuHeight});
}); });
dismiss(2200); dismiss(2200);

View File

@ -9,17 +9,17 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Name</span> <span class="gf-form-label width-7">Name</span>
<input type="text" required ng-model="ctrl.playlist.name" class="gf-form-input gf-size-max-xxl"> <input type="text" required ng-model="ctrl.playlist.name" class="gf-form-input max-width-21">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Interval</span> <span class="gf-form-label width-7">Interval</span>
<input type="text" required ng-model="ctrl.playlist.interval" placeholder="5m" class="gf-form-input gf-size-max-xxl"> <input type="text" required ng-model="ctrl.playlist.interval" placeholder="5m" class="gf-form-input max-width-21">
</div> </div>
</div> </div>
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-size-max-xxxl"> <div class="max-width-28">
<h5 class="page-headering">Add dashboards</h5> <h5 class="page-headering">Add dashboards</h5>
<div style=""> <div style="">
<playlist-search class="playlist-search-container" search-started="ctrl.searchStarted(promise)"></playlist-search> <playlist-search class="playlist-search-container" search-started="ctrl.searchStarted(promise)"></playlist-search>

View File

@ -8,18 +8,18 @@
<form name="userForm" class="gf-form-group"> <form name="userForm" class="gf-form-group">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-lg">Old Password</span> <span class="gf-form-label width-10">Old Password</span>
<input class="gf-form-input gf-size-max-xxl" type="text" required ng-model="command.oldPassword"> <input class="gf-form-input max-width-21" type="text" required ng-model="command.oldPassword">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-lg">New Password</span> <span class="gf-form-label width-10">New Password</span>
<input class="gf-form-input gf-size-max-xxl" type="text" required ng-minlength="4" ng-model="command.newPassword"> <input class="gf-form-input max-width-21" type="text" required ng-minlength="4" ng-model="command.newPassword">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-lg">Confirm Password</span> <span class="gf-form-label width-10">Confirm Password</span>
<input class="gf-form-input gf-size-max-xxl" type="text" required ng-minlength="4" ng-model="command.confirmNew"> <input class="gf-form-input max-width-21" type="text" required ng-minlength="4" ng-model="command.confirmNew">
</div> </div>
<div class="gf-form-button-row"> <div class="gf-form-button-row">

View File

@ -10,19 +10,19 @@
<h3 class="page-heading">Preferences</h3> <h3 class="page-heading">Preferences</h3>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Name</span> <span class="gf-form-label width-7">Name</span>
<input class="gf-form-input gf-size-max-xxl" type="text" required ng-model="user.name" > <input class="gf-form-input max-width-21" type="text" required ng-model="user.name" >
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Email</span> <span class="gf-form-label width-7">Email</span>
<input class="gf-form-input gf-size-max-xxl" type="email" required ng-model="user.email"> <input class="gf-form-input max-width-21" type="email" required ng-model="user.email">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Username</span> <span class="gf-form-label width-7">Username</span>
<input class="gf-form-input gf-size-max-xxl" type="text" required ng-model="user.login"> <input class="gf-form-input max-width-21" type="text" required ng-model="user.login">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">UI Theme</span> <span class="gf-form-label width-7">UI Theme</span>
<select class="gf-form-input gf-size-auto" ng-model="user.theme" ng-options="f for f in ['dark', 'light']"></select> <select class="gf-form-input gf-size-auto" ng-model="user.theme" ng-options="f for f in ['dark', 'light']"></select>
</div> </div>

View File

@ -15,35 +15,34 @@
</a> </a>
</div> </div>
<tabset> <ul class="nav nav-tabs">
<tab heading="Colors"> <li ng-repeat="page in ctrl.pages" ng-class="{active: ctrl.page[page]}" class="tab">
<ul> <a href="styleguide/{{page}}">{{page}}</a>
<li class="style-guide-color-card" ng-repeat="color in ctrl.colors" style="background-color: {{color.value}}"> </li>
<strong>${{color.name}}</strong> </ul>
<em>{{color.value}}</em>
</li>
</ul>
</tab>
<tab heading="Buttons">
<div class="style-guide-button-list p-a-2"> <div class="tab-pane" ng-if="ctrl.page.colors">
<button class="btn btn-primary">btn-primary</button> <ul>
<button class="btn btn-info">btn-info</button> <li class="style-guide-color-card" ng-repeat="color in ctrl.colors" style="background-color: {{color.value}}">
<button class="btn btn-inverse">btn-inverse</button> <strong>${{color.name}}</strong>
<button class="btn btn-success">btn-success</button> <em>{{color.value}}</em>
<button class="btn btn-warning">btn-warning</button> </li>
<button class="btn btn-danger">btn-danger</button> </ul>
</div>
<div class="tab-pane" ng-if="ctrl.page.buttons">
<div ng-repeat="variant in ctrl.buttonVariants" class="row">
<div ng-repeat="btnSize in ctrl.buttonSizes" class="style-guide-button-list p-a-2 col-md-4">
<button ng-repeat="buttonName in ctrl.buttonNames" class="btn btn{{variant}}{{buttonName}} {{btnSize}}">
btn{{variant}}{{buttonName}}
</button>
</div> </div>
</div>
</div>
<div class="tab-pane" ng-if="ctrl.page.forms">
<div class="style-guide-button-list p-a-2"> forms
<button class="btn btn-primary btn-small">btn-small</button> </div>
<button class="btn btn-success btn-large">btn-large</button>
</div>
</tab>
<tab heading="Forms">
</tab>
</tabset>
</div> </div>

View File

@ -6,12 +6,30 @@ import _ from 'lodash';
class StyleGuideCtrl { class StyleGuideCtrl {
colors: any = []; colors: any = [];
theme: string; theme: string;
buttonNames = ['primary', 'secondary', 'inverse', 'success', 'warning', 'danger'];
buttonSizes = ['btn-small', '', 'btn-large'];
buttonVariants = ['-', '-outline-'];
page: any;
pages = ['colors', 'buttons', 'forms', 'dashboard', 'query-editors'];
/** @ngInject **/ /** @ngInject **/
constructor($http) { constructor(private $http, $routeParams) {
this.theme = config.bootData.user.lightTheme ? 'light': 'dark'; this.theme = config.bootData.user.lightTheme ? 'light': 'dark';
this.page = {};
$http.get('public/sass/styleguide.json').then(res => { if ($routeParams.page) {
this.page[$routeParams.page] = 1;
} else {
this.page.colors = true;
}
if (this.page.colors) {
this.loadColors();
}
}
loadColors() {
this.$http.get('public/sass/styleguide.json').then(res => {
this.colors = _.map(res.data[this.theme], (value, key) => { this.colors = _.map(res.data[this.theme], (value, key) => {
return {name: key, value: value}; return {name: key, value: value};
}); });
@ -20,7 +38,7 @@ class StyleGuideCtrl {
switchTheme() { switchTheme() {
var other = this.theme === 'dark' ? 'light' : 'dark'; var other = this.theme === 'dark' ? 'light' : 'dark';
window.location.href = config.appSubUrl + '/styleguide?theme=' + other; window.location.href = window.location.href + '?theme=' + other;
} }
} }

View File

@ -100,7 +100,7 @@
<div ng-show='dashboardMeta.canEdit' class="row-fluid add-row-panel-hint" ng-hide="dashboard.meta.fullscreen"> <div ng-show='dashboardMeta.canEdit' class="row-fluid add-row-panel-hint" ng-hide="dashboard.meta.fullscreen">
<div class="span12" style="text-align:right;"> <div class="span12" style="text-align:right;">
<span style="margin-right: 10px;" ng-click="addRowDefault()" class="pointer btn btn-info btn-small"> <span style="margin-right: 10px;" ng-click="addRowDefault()" class="pointer btn btn-secondary btn-small">
<span><i class="fa fa-plus"></i> ADD ROW</span> <span><i class="fa fa-plus"></i> ADD ROW</span>
</span> </span>
</div> </div>

View File

@ -1,4 +1,4 @@
<div class="container"> <div class="login-container container">
<div class="login-box"> <div class="login-box">
@ -19,17 +19,17 @@
<form name="loginForm" class="login-form gf-form-group"> <form name="loginForm" class="login-form gf-form-group">
<div class="gf-form" ng-if="loginMode"> <div class="gf-form" ng-if="loginMode">
<span class="gf-form-label gf-size-sm">User</span> <span class="gf-form-label width-7">User</span>
<input type="text" name="username" class="gf-form-input gf-size-max-xl" required ng-model='formModel.user' placeholder={{loginHint}}> <input type="text" name="username" class="gf-form-input max-width-14" required ng-model='formModel.user' placeholder={{loginHint}}>
</div> </div>
<div class="gf-form" ng-if="loginMode"> <div class="gf-form" ng-if="loginMode">
<span class="gf-form-label gf-size-sm">Password</span> <span class="gf-form-label width-7">Password</span>
<input type="password" name="password" class="gf-form-input gf-size-max-xl" required ng-model="formModel.password" id="inputPassword" placeholder="password"> <input type="password" name="password" class="gf-form-input max-width-14" required ng-model="formModel.password" id="inputPassword" placeholder="password">
</div> </div>
<div class="gf-form" ng-if="!loginMode"> <div class="gf-form" ng-if="!loginMode">
<span class="gf-form-label gf-size-sm">Email</span> <span class="gf-form-label width-7">Email</span>
<input type="email" class="gf-form-input gf-size-max-xl" required ng-model='formModel.email' placeholder="email"> <input type="email" class="gf-form-input max-width-14" required ng-model='formModel.email' placeholder="email">
</div> </div>
<div class="gf-form-button-row"> <div class="gf-form-button-row">

View File

@ -1,29 +1,29 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxl"> <div class="gf-form max-width-21">
<span class="gf-form-label gf-size-sm">Title</span> <span class="gf-form-label width-8">Title</span>
<input type="text" class="gf-form-input" ng-model='ctrl.panel.title'></input> <input type="text" class="gf-form-input" ng-model='ctrl.panel.title'></input>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-xs">Span</span> <span class="gf-form-label width-6">Span</span>
<select class="gf-form-input gf-size-auto" ng-model="ctrl.panel.span" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10,11,12]"></select> <select class="gf-form-input gf-size-auto" ng-model="ctrl.panel.span" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10,11,12]"></select>
</div> </div>
<div class="gf-form gf-size-max-xxl"> <div class="gf-form max-width-21">
<span class="gf-form-label gf-size-sm">Height</span> <span class="gf-form-label width-8">Height</span>
<input type="text" class="gf-form-input gf-size-max-xs" ng-model='ctrl.panel.height' placeholder="100px"></input> <input type="text" class="gf-form-input max-width-6" ng-model='ctrl.panel.height' placeholder="100px"></input>
<editor-checkbox text="Transparent" model="ctrl.panel.transparent"></editor-checkbox> <editor-checkbox text="Transparent" model="ctrl.panel.transparent"></editor-checkbox>
</div> </div>
</div> </div>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxl"> <div class="gf-form max-width-21">
<span class="gf-form-label gf-size-sm">Repeat Panel</span> <span class="gf-form-label width-8">Repeat Panel</span>
<select class="gf-form-input" ng-model="ctrl.panel.repeat" ng-options="f.name as f.name for f in ctrl.dashboard.templating.list"> <select class="gf-form-input" ng-model="ctrl.panel.repeat" ng-options="f.name as f.name for f in ctrl.dashboard.templating.list">
<option value=""></option> <option value=""></option>
</select> </select>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-xs">Min span</span> <span class="gf-form-label width-6">Min span</span>
<select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12]"> <select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12]">
<option value=""></option> <option value=""></option>
</select> </select>

View File

@ -21,20 +21,20 @@
<form name="inviteForm" class="login-form gf-form-group"> <form name="inviteForm" class="login-form gf-form-group">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Email</span> <span class="gf-form-label width-7">Email</span>
<input type="email" name="email" class="gf-form-input gf-size-max-xxl" required ng-model='formModel.email' placeholder="Email"> <input type="email" name="email" class="gf-form-input max-width-21" required ng-model='formModel.email' placeholder="Email">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Name</span> <span class="gf-form-label width-7">Name</span>
<input type="text" name="name" class="gf-form-input gf-size-max-xxl" ng-model='formModel.name' placeholder="Name (optional)"> <input type="text" name="name" class="gf-form-input max-width-21" ng-model='formModel.name' placeholder="Name (optional)">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Username</span> <span class="gf-form-label width-7">Username</span>
<input type="text" name="username" class="gf-form-input gf-size-max-xxl" required ng-model='formModel.username' placeholder="Username"> <input type="text" name="username" class="gf-form-input max-width-21" required ng-model='formModel.username' placeholder="Username">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-sm">Password</span> <span class="gf-form-label width-7">Password</span>
<input type="password" name="password" class="gf-form-input gf-size-max-xxl" required ng-model="formModel.password" id="inputPassword" placeholder="password"> <input type="password" name="password" class="gf-form-input max-width-21" required ng-model="formModel.password" id="inputPassword" placeholder="password">
</div> </div>
<div style="margin-left: 7.5rem; width: 254px;"> <div style="margin-left: 7.5rem; width: 254px;">

View File

@ -31,28 +31,28 @@
<form name="signUpForm" class="login-form gf-form-group"> <form name="signUpForm" class="login-form gf-form-group">
<div class="gf-form" ng-if="verifyEmailEnabled"> <div class="gf-form" ng-if="verifyEmailEnabled">
<span class="gf-form-label gf-size-md"> <span class="gf-form-label width-9">
Email code<tip>Email verification code (sent to your email)</tip> Email code<tip>Email verification code (sent to your email)</tip>
</span> </span>
<input type="text" class="gf-form-input gf-size-max-xl" ng-model="formModel.code" required></input> <input type="text" class="gf-form-input max-width-14" ng-model="formModel.code" required></input>
</div> </div>
<div class="gf-form" ng-if="!autoAssignOrg"> <div class="gf-form" ng-if="!autoAssignOrg">
<span class="gf-form-label gf-size-md">Org. name</span> <span class="gf-form-label width-9">Org. name</span>
<input type="text" name="orgName" class="gf-form-input gf-size-max-xl" ng-model='formModel.orgName' placeholder="Name your organization"> <input type="text" name="orgName" class="gf-form-input max-width-14" ng-model='formModel.orgName' placeholder="Name your organization">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-md">Your name</span> <span class="gf-form-label width-9">Your name</span>
<input type="text" name="name" class="gf-form-input gf-size-max-xl" ng-model='formModel.name' placeholder="(optional)"> <input type="text" name="name" class="gf-form-input max-width-14" ng-model='formModel.name' placeholder="(optional)">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-md">Username</span> <span class="gf-form-label width-9">Username</span>
<input type="text" class="gf-form-input gf-size-max-xl" required ng-model='formModel.username' placeholder="Username" autocomplete="off"> <input type="text" class="gf-form-input max-width-14" required ng-model='formModel.username' placeholder="Username" autocomplete="off">
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-md">Password</span> <span class="gf-form-label width-9">Password</span>
<input type="password" class="gf-form-input gf-size-max-xl" required ng-model="formModel.password" id="inputPassword" placeholder="password" autocomplete="off"> <input type="password" class="gf-form-input max-width-14" required ng-model="formModel.password" id="inputPassword" placeholder="password" autocomplete="off">
</div> </div>
<div style="margin-left: 7.5rem; width: 254px;"> <div style="margin-left: 7.5rem; width: 254px;">

View File

@ -1,44 +1,22 @@
<br> <h3 class="page-heading">CloudWatch details</h3>
<h5>CloudWatch details</h5>
<div class="editor-row"> <div class="gf-form-group">
<div class="section tight-form-container" style="margin-bottom: 20px"> <div class="gf-form">
<div class="tight-form"> <label class="gf-form-label width-14">
<ul class="tight-form-list"> Credentials profile name<tip>Credentials profile name, as specified in ~/.aws/credentials, leave blank for default</tip>
<li class="tight-form-item" style="width: 200px"> </label>
Credentials profile name<tip>Credentials profile name, as specified in ~/.aws/credentials, leave blank for default</tip> <input type="text" class="gf-form-input max-width-15" ng-model='ctrl.current.database' placeholder="default"></input>
</li> </div>
<li> <div class="gf-form">
<input type="text" class="tight-form-input input-large last" ng-model='ctrl.current.database' placeholder="default"></input> <label class="gf-form-label width-14">
</li> Default Region<tip>Specify the region, such as for US West (Oregon) use ` us-west-2 ` as the region.</tip>
</ul> </label>
<div class="clearfix"></div> <div class="gf-form-select-wrapper">
</div> <select class="gf-form-input max-width-15" ng-model="ctrl.current.jsonData.defaultRegion" ng-options="region for region in ['ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'cn-north-1', 'eu-central-1', 'eu-west-1', 'sa-east-1', 'us-east-1', 'us-west-1', 'us-west-2']"></select>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 200px">
Default Region<tip>Specify the region, such as for US West (Oregon) use ` us-west-2 ` as the region.</tip>
</li>
<!--
Whenever this list is updated, backend list should also be updated.
Please update the region list in pkg/api/cloudwatch/metric.go
-->
<li>
<select class="tight-form-input input-large last" ng-model="ctrl.current.jsonData.defaultRegion" ng-options="region for region in ['ap-northeast-1', 'ap-northeast-2', 'ap-southeast-1', 'ap-southeast-2', 'cn-north-1', 'eu-central-1', 'eu-west-1', 'sa-east-1', 'us-east-1', 'us-west-1', 'us-west-2']"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 200px">
Custom Metrics namespace<tip>Namespaces of Custom Metrics</tip>
</li>
<li>
<input type="text" class="tight-form-input input-large last" ng-model='ctrl.current.jsonData.customMetricsNamespaces' placeholder="Namespace1,Namespace2"></input>
</li>
</ul>
<div class="clearfix"></div>
</div> </div>
</div> </div>
<div class="gf-form">
<label class="gf-form-label width-14">Custom Metrics namespace<tip>Namespaces of Custom Metrics</tip></label>
<input type="text" class="gf-form-input max-width-15" ng-model='ctrl.current.jsonData.customMetricsNamespaces' placeholder="Namespace1,Namespace2"></input>
</div>
</div> </div>

View File

@ -5,24 +5,24 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-19">
<span class="gf-form-label gf-size-md">Index name</span> <span class="gf-form-label width-9">Index name</span>
<input class="gf-form-input" type="text" ng-model='ctrl.current.database' placeholder="" required></input> <input class="gf-form-input" type="text" ng-model='ctrl.current.database' placeholder="" required></input>
</div> </div>
<div class="gf-form gf-size-xl"> <div class="gf-form width-14">
<span class="gf-form-label gf-size-md">Pattern</span> <span class="gf-form-label width-9">Pattern</span>
<select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.interval" ng-options="f.value as f.name for f in ctrl.indexPatternTypes" ng-change="ctrl.indexPatternTypeChanged()" ></select> <select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.interval" ng-options="f.value as f.name for f in ctrl.indexPatternTypes" ng-change="ctrl.indexPatternTypeChanged()" ></select>
</div> </div>
</div> </div>
<div class="gf-form gf-size-max-xxxl"> <div class="gf-form max-width-28">
<span class="gf-form-label gf-size-md">Time field name</span> <span class="gf-form-label width-9">Time field name</span>
<input class="gf-form-input" type="text" ng-model='ctrl.current.jsonData.timeField' placeholder="" required ng-init=""></input> <input class="gf-form-input" type="text" ng-model='ctrl.current.jsonData.timeField' placeholder="" required ng-init=""></input>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label gf-size-md">Version</span> <span class="gf-form-label width-9">Version</span>
<select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.esVersion" ng-options="f.value as f.name for f in ctrl.esVersions"></select> <select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.esVersion" ng-options="f.value as f.name for f in ctrl.esVersions"></select>
</div> </div>
@ -32,6 +32,6 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label">Group by time interval</span> <span class="gf-form-label">Group by time interval</span>
<input class="gf-form-input gf-size-max-md" type="text" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="example: >10s"> <input class="gf-form-input max-width-9" type="text" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="example: >10s">
</div> </div>
</div> </div>

View File

@ -1,52 +1,33 @@
<datasource-http-settings current="ctrl.current"> <datasource-http-settings current="ctrl.current">
</datasource-http-settings> </datasource-http-settings>
<h4>InfluxDB Details</h4> <h3 class="page-heading">InfluxDB Details</h3>
<div class="tight-form"> <div class="gf-form-group">
<ul class="tight-form-list"> <div class="gf-form-inline">
<li class="tight-form-item" style="width: 80px"> <div class="gf-form max-width-30">
Database <span class="gf-form-label width-7">Database</span>
</li> <input type="text" class="gf-form-input" ng-model='ctrl.current.database' placeholder="" required></input>
<li> </div>
<input type="text" class="tight-form-input input-large" ng-model='ctrl.current.database' placeholder="" required></input> </div>
</li>
</ul> <div class="gf-form-inline">
<div class="clearfix"></div> <div class="gf-form max-width-15">
</div> <span class="gf-form-label width-7">User</span>
<div class="tight-form last"> <input type="text" class="gf-form-input" ng-model='ctrl.current.user' placeholder="" required></input>
<ul class="tight-form-list"> </div>
<li class="tight-form-item" style="width: 80px"> <div class="gf-form max-width-15">
User <span class="gf-form-label width-7">Password</span>
</li> <input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder="" required></input>
<li> </div>
<input type="text" class="tight-form-input input-large" ng-model='ctrl.current.user' placeholder="" required></input> </div>
</li>
<li class="tight-form-item">
Password
</li>
<li>
<input type="password" class="tight-form-input input-large" ng-model='ctrl.current.password' placeholder="" required></input>
</li>
</ul>
<div class="clearfix"></div>
</div> </div>
<div class="gf-form-group">
<br> <div class="gf-form max-width-21">
<h4>Default query settings</h4> <span class="gf-form-label">Default group by time</span>
<div class="tight-form last"> <input type="text" class="gf-form-input width-6" ng-model="ctrl.current.jsonData.timeInterval"
<ul class="tight-form-list"> spellcheck='false' placeholder="example: >10s"></input>
<li class="tight-form-item" style="width: 200px"> <i class="fa fa-question-circle" bs-tooltip="'Set a low limit by having a greater sign: example: >10s'" data-placement="right"></i>
Group by time interval </div>
</li>
<li>
<input type="text" class="input-medium tight-form-input input-xlarge" ng-model="ctrl.current.jsonData.timeInterval"
spellcheck='false' placeholder="example: >10s">
</li>
<li class="tight-form-item">
<i class="fa fa-question-circle" bs-tooltip="'Set a low limit by having a greater sign: example: >10s'" data-placement="right"></i>
</li>
</ul>
<div class="clearfix"></div>
</div> </div>

View File

@ -1,17 +1,26 @@
<div> <div class="gf-form-group">
<div class="row-fluid"> <div class="gf-form-inline">
<div class="span4"> <div class="gf-form">
<label class="small">Mode</label> <select class="input-medium" ng-model="ctrl.panel.mode" ng-options="f for f in ['html','markdown','text']"></select> <span class="gf-form-label">Mode</span>
</div> <span class="gf-form-select-wrapper">
<div class="span2" ng-show="ctrl.panel.mode == 'text'"> <select class="gf-form-input" ng-model="ctrl.panel.mode" ng-options="f for f in ['html','markdown','text']"></select>
<label class="small">Font Size</label> <select class="input-mini" ng-model="ctrl.panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select> </span>
</div> </div>
</div>
<label class=small>Content <div class="gf-form" ng-show="ctrl.panel.mode == 'text'">
<span ng-show="ctrl.panel.mode == 'markdown'">(This area uses <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>. HTML is not supported)</span> <span class="gf-form-label">Font Size</span>
</label> <span class="gf-form-select-wrapper">
<select class="gf-form-input" ng-model="ctrl.panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select>
<textarea ng-model="ctrl.panel.content" rows="20" style="width:95%" ng-change="ctrl.render()" ng-model-onblur> </span>
</textarea> </div>
</div>
</div> </div>
<h3 class="page-heading">Content</h3>
<span ng-show="ctrl.panel.mode == 'markdown'">
(This area uses <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>. HTML is not supported)
</span>
<textarea class="gf-form-input" ng-model="ctrl.panel.content" rows="20" style="width:95%" ng-change="ctrl.render()" ng-model-onblur>
</textarea>

View File

@ -1 +1,2 @@
<p ng-bind-html="ctrl.content" ng-show="ctrl.content"></p> <p class="panel-text-content" ng-bind-html="ctrl.content" ng-show="ctrl.content">
</p>

View File

@ -2,6 +2,7 @@ System.config({
defaultJSExtenions: true, defaultJSExtenions: true,
baseURL: 'public', baseURL: 'public',
paths: { paths: {
'tether': 'vendor/npm/tether/dist/js/tether.js',
'moment': 'vendor/moment.js', 'moment': 'vendor/moment.js',
"jquery": "vendor/jquery/dist/jquery.js", "jquery": "vendor/jquery/dist/jquery.js",
'lodash-src': 'vendor/lodash.js', 'lodash-src': 'vendor/lodash.js',

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 B

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
public/img/transparent.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

View File

@ -1,33 +1,87 @@
options:
formatter: stylish
files: files:
include: '**/*.s+(a|c)ss' include: '**/*.s+(a|c)ss'
ignore: ignore:
- './utils/*.scss'
rules: rules:
# Extends
extends-before-mixins: 0
extends-before-declarations: 0
placeholder-in-extend: 0
# Mixins
mixins-before-declarations: 0
# Line Spacing
one-declaration-per-line: 0
empty-line-between-blocks: 0 empty-line-between-blocks: 0
single-line-per-selector: 0
# Disallows
no-color-keywords: 0
no-color-literals: 0
no-css-comments: 0
no-debug: 0
no-duplicate-properties: 0
no-empty-rulesets: 1 no-empty-rulesets: 1
# Consistency Rules no-extends: 0
# extends-before-mixins: 1 no-ids: 0
# extends-before-declarations: 1 no-important: 0
# mixins-before-declarations: 1 no-invalid-hex: 0
# Require an empty line between blocks no-mergeable-selectors: 0
# final-newline: 1 no-misspelled-properties: 0
# no-ids: 1 no-qualifying-elements: 0
# indentation: 0 no-trailing-zero: 0
# leading-zero: 1 no-transition-all: 0
# name-format: 0 no-url-protocols: 0
# nesting-depth: 1 no-vendor-prefixes: 0
# placeholder-in-extend: 1 no-warn: 0
# property-sort-order: 1 property-units: 0
# property-spelling: 0
# shorthand: 1 # Nesting
# one-declaration-per-line: 1 force-attribute-nesting: 0
# single-line-per-selector: 1 force-element-nesting: 0
# space-after-comma: 1 force-pseudo-nesting: 0
# # Space surrounding colons
# space-before-colon: 1 # Name Formats
# space-after-colon: 1 class-name-format: 0
# function-name-format: 0
# space-before-brace: 1 id-name-format: 0
# mixin-name-format: 0
# space-between-parens: 1 placeholder-name-format: 0
# trailing-semicolon: 1 variable-name-format: 0
# Style Guide
bem-depth: 0
border-zero: 0
brace-style: 0
clean-import-paths: 0
empty-args: 0
hex-length: 0
hex-notation: 0
indentation: 0
leading-zero: 0
nesting-depth: 0
property-sort-order: 0
quotes: 0
shorthand-values: 0
url-quotes: 0
variable-for-property: 0
zero-unit: 0
# Inner Spacing
space-after-comma: 0
space-before-colon: 0
space-after-colon: 0
space-before-brace: 0
space-before-bang: 0
space-after-bang: 0
space-between-parens: 0
space-around-operator: 0
# Final Items
trailing-semicolon: 0
final-newline: 0

View File

@ -1,5 +1,6 @@
// MIXINS // MIXINS
@import "mixins/mixins"; @import "mixins/mixins";
@import "mixins/animations";
@import "mixins/buttons"; @import "mixins/buttons";
@import "mixins/breakpoints"; @import "mixins/breakpoints";
@import "mixins/grid"; @import "mixins/grid";
@ -21,6 +22,7 @@
@import "utils/validation"; @import "utils/validation";
@import "utils/angular"; @import "utils/angular";
@import "utils/spacings"; @import "utils/spacings";
@import "utils/widths";
// LAYOUTS // LAYOUTS
@import "layout/page"; @import "layout/page";
@ -37,6 +39,7 @@
@import "components/panel_dashlist"; @import "components/panel_dashlist";
@import "components/panel_singlestat"; @import "components/panel_singlestat";
@import "components/panel_table"; @import "components/panel_table";
@import "components/panel_text";
@import "components/tagsinput"; @import "components/tagsinput";
@import "components/tables_lists"; @import "components/tables_lists";
@import "components/search"; @import "components/search";

View File

@ -7,8 +7,8 @@
// --------------------- // ---------------------
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
div.panel { div.panel {
width: 100% !important; width: 100%;
padding: 0px !important; padding: 0px;
} }
.panel-margin { .panel-margin {
margin-right: 0; margin-right: 0;
@ -17,7 +17,7 @@
body { body {
padding: 0; padding: 0;
} }
.dashnav-dashboards-btn a { .page-dashboard .navbar-page-btn {
max-width: 200px; max-width: 200px;
} }
.gf-timepicker-nav-btn { .gf-timepicker-nav-btn {
@ -34,7 +34,7 @@
// form styles // form styles
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
.dashnav-dashboards-btn a { .page-dashboard .navbar-page-btn {
max-width: 180px; max-width: 180px;
} }
.gf-timepicker-nav-btn { .gf-timepicker-nav-btn {
@ -51,7 +51,7 @@
} }
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
.dashnav-dashboards-btn a { .page-dashboard .navbar-page-btn {
max-width: 290px; max-width: 290px;
} }
.gf-timepicker-nav-btn { .gf-timepicker-nav-btn {

View File

@ -8,17 +8,17 @@ $black: #000;
// ------------------------- // -------------------------
$black: #000; $black: #000;
$dark-1: #141414; // (body) $dark-1: #141414;
$dark-2: #1f1d1d; // ($gray-darker) $dark-2: #1f1d1d;
$dark-3: #262626; // ($gray-dark) $dark-3: #292929;
$dark-4: #333333; $dark-4: #333333;
$dark-5: #444444; $dark-5: #444444;
$gray-1: #555555; $gray-1: #555555;
$gray-2: #6e7580; $gray-2: #7B7B7B;
$gray-3: #b3b3b3; $gray-3: #b3b3b3;
$gray-4: #cfd4d9; $gray-4: #D8D9DA;
$gray-5: #e8edf0; $gray-5: #ECECEC;
$gray-6: #f7f9fa; $gray-6: #f4f5f8;
$gray-7: #fbfbfb; $gray-7: #fbfbfb;
$white: #fff; $white: #fff;
@ -92,8 +92,8 @@ $modal-background: $black;
$code-tag-bg: #444; $code-tag-bg: #444;
// Lists // Lists
$grafanaListBackground: $dark-3; $grafanaListBackground: $dark-3;
$grafanaListAccent: lighten($dark-2, 2%); $grafanaListAccent: lighten($dark-2, 2%);
$grafanaListBorderTop: $dark-3; $grafanaListBorderTop: $dark-3;
$grafanaListBorderBottom: $black; $grafanaListBorderBottom: $black;
$grafanaListHighlight: #333; $grafanaListHighlight: #333;
@ -117,20 +117,20 @@ $table-border: $dark-3; // table and cell border
$btn-primary-bg: $brand-primary; $btn-primary-bg: $brand-primary;
$btn-primary-bg-hl: lighten($brand-primary, 8%); $btn-primary-bg-hl: lighten($brand-primary, 8%);
$btn-info-bg: lighten($purple, 3%); $btn-secondary-bg: $blue-dark;
$btn-info-bg-hl: darken($purple, 3%); $btn-secondary-bg-hl: lighten($blue-dark, 3%);
$btn-success-bg-hl: darken($green, 3%); $btn-success-bg-hl: darken($green, 3%);
$btn-success-bg: lighten($green, 3%); $btn-success-bg: lighten($green, 3%);
$btn-warning-bg: $brand-warning; $btn-warning-bg: $brand-warning;
$btn-warning-bg-hl: lighten($brand-warning, 8%); $btn-warning-bg-hl: lighten($brand-warning, 8%);
$btn-danger-bg: lighten($red, 3%); $btn-danger-bg: lighten($red, 3%);
$btn-danger-bg-hl: darken($red, 3%); $btn-danger-bg-hl: darken($red, 3%);
$btn-inverse-bg: $dark-3; $btn-inverse-bg: $dark-3;
$btn-inverse-bg-hl: lighten($dark-3, 1%); $btn-inverse-bg-hl: lighten($dark-3, 1%);
$btn-inverse-text-color: $link-color; $btn-inverse-text-color: $link-color;
$btn-link-color: $gray-3; $btn-link-color: $gray-3;
@ -139,19 +139,19 @@ $iconContainerBackground: $black;
// Forms // Forms
// ------------------------- // -------------------------
$input-bg: lighten($dark-3,5%); $input-bg: $dark-4;
$input-bg-disabled: #555; $input-bg-disabled: $dark-3;
$input-color: $gray-4; $input-color: $gray-4;
$input-border-color: lighten($dark-2,5%); $input-border-color: $dark-4;
$input-box-shadow: inset 0 1px 1px rgba(0,0,0,.075) !default; $input-box-shadow: inset 1px 0px 0.5rem 0px rgba(200, 200, 200, 0.10);
$input-border-focus: $input-border-color !default; $input-border-focus: $input-border-color !default;
$input-box-shadow-focus: rgba(102,175,233,.6) !default; $input-box-shadow-focus: rgba(102,175,233,.6) !default;
$input-color-placeholder: #999 !default; $input-color-placeholder: $gray-1 !default;
$input-label-bg: $dark-3; $input-label-bg: $dark-3;
// Search // Search
$searchShadow: 0 0 35px 0 $body-bg; $search-shadow: 0 0 35px 0 $body-bg;
// Dropdowns // Dropdowns
// ------------------------- // -------------------------
@ -166,8 +166,8 @@ $dropdownLinkColor: $text-color;
$dropdownLinkColorHover: $white; $dropdownLinkColorHover: $white;
$dropdownLinkColorActive: $white; $dropdownLinkColorActive: $white;
$dropdownLinkBackgroundActive: $blue-dark; $dropdownLinkBackgroundActive: $dark-4;
$dropdownLinkBackgroundHover: $blue-dark; $dropdownLinkBackgroundHover: $dark-4;
// COMPONENT VARIABLES // COMPONENT VARIABLES
@ -206,7 +206,8 @@ $navbarButtonBackgroundHighlight: lighten($navbarBackground, 5%);
// Sidemenu // Sidemenu
// ------------------------- // -------------------------
$side-menu-bg: $body-bg; $side-menu-bg: $body-bg;
$side-menu-item-hover-bg: $dark-4; $side-menu-item-hover-bg: $dark-3;
$side-menu-opacity: 0.97;
// Pagination // Pagination
// ------------------------- // -------------------------
@ -226,7 +227,7 @@ $successText: #468847;
$successBackground: $btn-success-bg; $successBackground: $btn-success-bg;
$infoText: $blue-dark; $infoText: $blue-dark;
$infoBackground: $btn-info-bg; $infoBackground: $blue-dark;
// Tooltips and popovers // Tooltips and popovers
// ------------------------- // -------------------------

View File

@ -13,10 +13,10 @@ $black: #000;
// ------------------------- // -------------------------
$black: #000; $black: #000;
$dark-1: #141414; // (body) $dark-1: #141414;
$dark-2: #1f1d1d; // ($gray-darker) $dark-2: #1f1d1d;
$dark-3: #262626; // ($gray-dark) $dark-3: #292929;
$dark-4: #333333; $dark-4: #373737;
$dark-5: #444444; $dark-5: #444444;
$gray-1: #555555; $gray-1: #555555;
$gray-2: #7B7B7B; $gray-2: #7B7B7B;
@ -31,7 +31,7 @@ $white: #fff;
// Accent colors // Accent colors
// ------------------------- // -------------------------
$blue: #2AB2E4; $blue: #2AB2E4;
$blue-dark: #75CAEB; $blue-dark: #3CAAD6;
$green: #28B62C; $green: #28B62C;
$red: #FF4136; $red: #FF4136;
$yellow: #FF851B; $yellow: #FF851B;
@ -125,8 +125,8 @@ $scrollbarBorder: $gray-4;
$btn-primary-bg: $brand-primary; $btn-primary-bg: $brand-primary;
$btn-primary-bg-hl: lighten($brand-primary, 8%); $btn-primary-bg-hl: lighten($brand-primary, 8%);
$btn-info-bg: lighten($purple, 3%); $btn-secondary-bg: $blue-dark;
$btn-info-bg-hl: darken($purple, 3%); $btn-secondary-bg-hl: lighten($blue-dark, 4%);
$btn-success-bg: lighten($green, 3%); $btn-success-bg: lighten($green, 3%);
$btn-success-bg-hl: darken($green, 3%); $btn-success-bg-hl: darken($green, 3%);
@ -156,15 +156,16 @@ $input-box-shadow: none;
$input-border-focus: $blue !default; $input-border-focus: $blue !default;
$input-box-shadow-focus: $blue !default; $input-box-shadow-focus: $blue !default;
$input-color-placeholder: $gray-4 !default; $input-color-placeholder: $gray-4 !default;
$input-label-bg: $gray-5; $input-label-bg: $gray-6;
// Sidemenu // Sidemenu
// ------------------------- // -------------------------
$side-menu-bg: $body-bg; $side-menu-bg: $body-bg;
$side-menu-item-hover-bg: $gray-6; $side-menu-item-hover-bg: $gray-6;
$side-menu-opacity: 0.97;
// search // search
$searchShadow: 0 5px 30px 0 lighten($gray-2, 30%); $search-shadow: 0 5px 30px 0 lighten($gray-2, 30%);
// Dropdowns // Dropdowns
// ------------------------- // -------------------------
@ -176,11 +177,11 @@ $dropdownDivider: $dropdownDividerTop;
$dropdownTitle: $dark-5; $dropdownTitle: $dark-5;
$dropdownLinkColor: $dark-3; $dropdownLinkColor: $dark-3;
$dropdownLinkColorHover: $white; $dropdownLinkColorHover: $link-color;
$dropdownLinkColorActive: $white; $dropdownLinkColorActive: $link-color;
$dropdownLinkBackgroundActive: $blue; $dropdownLinkBackgroundActive: $gray-6;
$dropdownLinkBackgroundHover: $blue; $dropdownLinkBackgroundHover: $gray-6;
// COMPONENT VARIABLES // COMPONENT VARIABLES
@ -250,8 +251,8 @@ $successText: lighten($green, 10%);
$successBackground: $green; $successBackground: $green;
$successBorder: transparent; $successBorder: transparent;
$infoText: lighten($purple,10%); $infoText: $blue;
$infoBackground: $purple; $infoBackground: $blue-dark;
$infoBorder: transparent; $infoBorder: transparent;
@ -274,5 +275,3 @@ $popoverArrowOuterColor: rgba(0,0,0,.25);
// images // images
$checkboxImageUrl: '../img/checkbox_white.png'; $checkboxImageUrl: '../img/checkbox_white.png';

View File

@ -77,17 +77,6 @@ $grid-gutter-width: 30px !default;
$enable-flex: false; $enable-flex: false;
$form-sizes: (
xs: 5.7rem,
sm: 7rem,
md: 8.5rem,
lg: 10rem,
xl: 14rem,
xxl: 21rem,
xxxl: 28rem
) !default;
// Typography // Typography
// ------------------------- // -------------------------
@ -170,9 +159,13 @@ $input-padding-y: .6rem !default;
$input-line-height: 1.35rem !default; $input-line-height: 1.35rem !default;
$input-btn-border-width: 1px; $input-btn-border-width: 1px;
$input-border-radius: $border-radius !default; $input-border-radius: 0 $border-radius $border-radius 0 !default;
$input-border-radius-lg: $border-radius-lg !default; $input-border-radius-lg: 0 $border-radius-lg $border-radius-lg 0 !default;
$input-border-radius-sm: $border-radius-sm !default; $input-border-radius-sm: 0 $border-radius-sm $border-radius-sm 0 !default;
$label-border-radius: $border-radius 0 0 $border-radius !default;
$label-border-radius-lg: $border-radius-lg 0 0 $border-radius-lg !default;
$label-border-radius-sm: $border-radius-sm 0 0 $border-radius-sm !default;
$input-padding-x-sm: .5rem !default; $input-padding-x-sm: .5rem !default;
$input-padding-y-sm: .25rem !default; $input-padding-y-sm: .25rem !default;
@ -185,6 +178,7 @@ $input-height-lg: (($font-size-lg * $line-height-lg) + ($input-pa
$input-height-sm: (($font-size-sm * $line-height-sm) + ($input-padding-y-sm * 2)) !default; $input-height-sm: (($font-size-sm * $line-height-sm) + ($input-padding-y-sm * 2)) !default;
$form-group-margin-bottom: $spacer-y !default; $form-group-margin-bottom: $spacer-y !default;
$gf-form-margin: 0.2rem;
$cursor-disabled: not-allowed !default; $cursor-disabled: not-allowed !default;
@ -221,4 +215,4 @@ $btn-padding-y-lg: .75rem !default;
$btn-border-radius: 3px; $btn-border-radius: 3px;
// sidemenu // sidemenu
$side-menu-width: 15rem; $side-menu-width: 14rem;

View File

@ -24,6 +24,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.inline-icon-gf {
vertical-align: middle;
}
.icon-gf-raintank_wordmark:before { .icon-gf-raintank_wordmark:before {
content: "\e600"; content: "\e600";
} }

View File

@ -178,7 +178,7 @@ input[type="checkbox"].cr1 {
label.cr1 { label.cr1 {
display: inline-block; display: inline-block;
height: 19px; height: 18px;
position: relative; position: relative;
clear: none; clear: none;
text-indent: 2px; text-indent: 2px;
@ -190,7 +190,7 @@ label.cr1 {
} }
input[type="checkbox"]:checked+label { input[type="checkbox"]:checked+label {
background: url($checkboxImageUrl) 0px -21px no-repeat; background: url($checkboxImageUrl) 0px -18px no-repeat;
} }
.gf-fluid-input { .gf-fluid-input {

View File

@ -270,11 +270,9 @@ th {
// //
// Forms // Forms
// //
label { label {
// Allow labels to use `margin` for spacing. // Allow labels to use `margin` for spacing.
display: inline-block; display: inline-block;
margin-bottom: .5rem;
} }
// Work around a Firefox/IE bug where the transparent `button` background // Work around a Firefox/IE bug where the transparent `button` background

View File

@ -48,17 +48,17 @@
position: absolute; position: absolute;
top: -4px; top: -4px;
right: -2px; right: -2px;
width: 18px; width: 16px;
height: 18px; height: 16px;
padding: 0; padding: 0;
background: $white; background: $white;
border-radius: 50%; border-radius: 50%;
border: none; border: none;
font-size: 1.1rem; font-size: 1.1rem;
color: $gray-2; color: $dark-4;
.fa { .fa {
position: relative; position: relative;
top: -2px; top: -3px;
} }
} }

View File

@ -65,7 +65,7 @@
} }
.btn-link { .btn-link {
color: $btn-link-color; color: $btn-link-color;
} }
// Set the backgrounds // Set the backgrounds
@ -73,6 +73,9 @@
.btn-primary { .btn-primary {
@include buttonBackground($btn-primary-bg, $btn-primary-bg-hl); @include buttonBackground($btn-primary-bg, $btn-primary-bg-hl);
} }
.btn-secondary {
@include buttonBackground($btn-secondary-bg, $btn-secondary-bg-hl);
}
// Warning appears are orange // Warning appears are orange
.btn-warning { .btn-warning {
@include buttonBackground($btn-warning-bg, $btn-warning-bg-hl); @include buttonBackground($btn-warning-bg, $btn-warning-bg-hl);
@ -86,8 +89,8 @@
@include buttonBackground($btn-success-bg, $btn-success-bg-hl); @include buttonBackground($btn-success-bg, $btn-success-bg-hl);
} }
// Info appears as a neutral blue // Info appears as a neutral blue
.btn-info { .btn-secondary {
@include buttonBackground($btn-info-bg, $btn-info-bg-hl); @include buttonBackground($btn-secondary-bg, $btn-secondary-bg-hl);
} }
// Inverse appears as dark gray // Inverse appears as dark gray
.btn-inverse { .btn-inverse {
@ -100,10 +103,10 @@
@include button-outline-variant($btn-primary-bg); @include button-outline-variant($btn-primary-bg);
} }
.btn-outline-secondary { .btn-outline-secondary {
@include button-outline-variant($btn-inverse-bg); @include button-outline-variant($btn-secondary-bg);
} }
.btn-outline-info { .btn-outline-inverse {
@include button-outline-variant($btn-info-bg); @include button-outline-variant($btn-inverse-bg);
} }
.btn-outline-success { .btn-outline-success {
@include button-outline-variant($btn-success-bg); @include button-outline-variant($btn-success-bg);

View File

@ -58,7 +58,7 @@
.row-open { .row-open {
margin-top: 5px; margin-top: 5px;
left: -28px; left: -30px;
position: absolute; position: absolute;
z-index: 100; z-index: 100;
transition: .10s left; transition: .10s left;
@ -233,12 +233,12 @@ div.flot-text {
} }
.panel-highlight { .panel-highlight {
@include box-shadow("inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(82,168,236, 0.8)"); box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 5px rgba(82,168,236,10.8)
} }
.on-drag-hover { .on-drag-hover {
.panel-container { .panel-container {
@include box-shadow("inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(82,168,236, 0.8)"); box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 5px rgba(82,168,236,10.8)
} }
} }
@ -281,7 +281,7 @@ div.flot-text {
border-top: 0; border-top: 0;
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-bottom: 2px solid transparent; border-bottom: 1px solid transparent;
padding: 1.2rem .5rem .4rem .5rem; padding: 1.2rem .5rem .4rem .5rem;
} }
} }

View File

@ -1,4 +1,5 @@
$gf-form-margin: 0.4rem; $gf-form-margin: 0.25rem;
$gf-form-label-margin: 0.25rem;
.gf-form { .gf-form {
margin-bottom: $gf-form-margin; margin-bottom: $gf-form-margin;
@ -49,26 +50,16 @@ $gf-form-margin: 0.4rem;
background-color: $input-label-bg; background-color: $input-label-bg;
display: block; display: block;
font-size: $font-size-sm; font-size: $font-size-sm;
margin-right: $gf-form-margin; margin-right: $gf-form-label-margin;
border: $input-btn-border-width solid transparent; border: $input-btn-border-width solid transparent;
@include border-radius($label-border-radius-sm);
} }
.gf-form-checkbox { .gf-form-checkbox {
flex-shrink: 0; flex-shrink: 0;
} }
@each $size, $value in $form-sizes {
.gf-size-#{$size} { width: $value; }
.gf-size-max-#{$size} {
flex-grow: 1;
max-width: $value;
}
}
.gf-size-max { width: 100%; }
.gf-size-auto { width: auto; }
.gf-form-input { .gf-form-input {
display: block; display: block;
width: 100%; width: 100%;
@ -80,7 +71,7 @@ $gf-form-margin: 0.4rem;
background-image: none; background-image: none;
background-clip: padding-box; background-clip: padding-box;
border: $input-btn-border-width solid $input-border-color; border: $input-btn-border-width solid $input-border-color;
@include border-radius($input-border-radius); @include border-radius($input-border-radius-sm);
@include box-shadow($input-box-shadow); @include box-shadow($input-box-shadow);
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
@ -96,7 +87,6 @@ $gf-form-margin: 0.4rem;
// Placeholder // Placeholder
&::placeholder { &::placeholder {
color: $input-color-placeholder; color: $input-color-placeholder;
// Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
opacity: 1; opacity: 1;
} }
@ -114,6 +104,32 @@ $gf-form-margin: 0.4rem;
&.gf-size-auto { width: auto; } &.gf-size-auto { width: auto; }
} }
.gf-form-select-wrapper {
position: relative;
select.gf-form-input {
padding-right: $input-padding-x*2;
-webkit-appearance: none;
-moz-appearance: menulist-text; // was set to "window" and caused odd display on windos and linux.
appearance: none;
&:-moz-focusring {
color: transparent;
}
}
&:after {
position: absolute;
top: 35%;
right: $input-padding-x/2;
background-color: transparent;
color: $input-color;
font: normal normal normal $font-size-sm/1 FontAwesome;
content: '\f0d7';
pointer-events: none;
}
}
.gf-form-btn { .gf-form-btn {
padding: $input-padding-y $input-padding-x; padding: $input-padding-y $input-padding-x;
line-height: $input-line-height; line-height: $input-line-height;

View File

@ -56,52 +56,30 @@
background-color: $navbarLinkBackgroundActive; background-color: $navbarLinkBackgroundActive;
} }
.navbar-brand-btn {
.fa.top-nav-breadcrumb-icon {
margin: 18px 0 6px 5px;
float: left;
font-size: 120%;
color: $text-color;
}
.top-nav-btn {
display: block; display: block;
position: relative; position: relative;
float: left; float: left;
margin: 0; margin: 0;
font-size: 1.4em;
border-right: 1px solid $tight-form-border; border-right: 1px solid $tight-form-border;
background-color: $navbarButtonBackground;
padding: 0.6rem 1.0rem 0.5rem 1rem;
.fa-caret-down { .fa-caret-down {
font-size: 55%; font-size: 70%;
position: absolute;
right: 8px;
top: 23px;
margin-right: 2px;
} }
a { &:hover {
color: darken($link-color, 5%); background: $navbarButtonBackgroundHighlight;
background-color: $navbarButtonBackground;
display: inline-block;
&:hover {
background: $navbarButtonBackgroundHighlight;
color: $link-color;
// border-bottom: 1px solid $blue;
}
} }
}
.top-nav-menu-btn {
a {
padding: 7px 20px 6px 13px;
}
img { img {
width: 30px; width: 30px;
position: relative; position: relative;
top: -2px; top: -2px;
} }
.top-nav-logo-background {
.navbar-brand-btn-background {
display: inline-block; display: inline-block;
border: 1px solid $body-bg; border: 1px solid $body-bg;
padding: 4px; padding: 4px;
@ -110,6 +88,7 @@
width: 40px; width: 40px;
height: 40px; height: 40px;
} }
.icon-gf-grafana_wordmark { .icon-gf-grafana_wordmark {
font-size: 21px; font-size: 21px;
position: relative; position: relative;
@ -119,13 +98,28 @@
} }
} }
.dashnav-dashboards-btn { .navbar-page-btn {
a { text-overflow: ellipsis;
text-overflow: ellipsis; overflow: hidden;
overflow: hidden; white-space: nowrap;
white-space: nowrap; float: left;
display: block; display: block;
padding: 11px 17px 12px 13px; margin: 0;
font-size: 1.4em;
border-right: 1px solid $tight-form-border;
color: darken($link-color, 5%);
background-color: $navbarButtonBackground;
font-size: $font-size-lg;
padding: 1rem 0.8rem;
&:hover {
background: $navbarButtonBackgroundHighlight;
color: $link-color;
}
.fa-caret-down {
font-size: 60%;
padding-left: 0.2rem;
} }
.fa-th-large { .fa-th-large {
@ -141,32 +135,3 @@
} }
} }
.dashboard-title {
padding: 0 0.4rem 0 0.5rem;
font-size: $font-size-lg;
}
.top-nav-icon {
margin: 5px 0px 0 11px;
line-height: 41px;
float: left;
}
.top-nav-section {
display: block;
float: left;
padding: 19px 9px 8px 0;
font-weight: bold;
i {
padding-left: 8px;
}
}
.top-nav-title {
display: block;
float: left;
font-size: 17px;
padding: 18px 10px 10px 13px;
color: $link-color;
}

View File

@ -0,0 +1,6 @@
.panel-text-content {
ul {
margin: 0 0 $spacer $spacer * 1.5;
}
}

View File

@ -5,7 +5,7 @@
z-index: 1000; z-index: 1000;
position: absolute; position: absolute;
width: 700px; width: 700px;
box-shadow: $searchShadow; box-shadow: $search-shadow;
padding: 10px; padding: 10px;
background-color: $panel-bg; background-color: $panel-bg;
border: $panel-border; border: $panel-border;
@ -73,6 +73,7 @@
white-space: nowrap; white-space: nowrap;
background-color: $grafanaListBackground; background-color: $grafanaListBackground;
margin-bottom: 4px; margin-bottom: 4px;
.search-result-icon:before { .search-result-icon:before {
content: "\f009"; content: "\f009";
} }

View File

@ -7,7 +7,7 @@
top: 52px; top: 52px;
left: 0; left: 0;
width: $side-menu-width; width: $side-menu-width;
background-color: $side-menu-bg; background-color: rgba($side-menu-bg,$side-menu-opacity);
z-index: 101; z-index: 101;
transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0);
visibility: hidden; visibility: hidden;
@ -30,16 +30,15 @@
min-height: calc(100% - 54px); min-height: calc(100% - 54px);
} }
.dashboard-container { .dashboard-container {
padding-left: $side-menu-width; padding-left: $side-menu-width + 0.2rem;
} }
.page-container { .page-container {
margin-left: $side-menu-width; margin-left: $side-menu-width;
} }
.top-nav-menu-btn { .navbar-brand-btn {
a { background-color: $page-bg;
background-color: $page-bg; width: $side-menu-width;
width: $side-menu-width;
}
.icon-gf-grafana_wordmark { .icon-gf-grafana_wordmark {
display: inline-block; display: inline-block;
} }
@ -47,9 +46,6 @@
display: none; display: none;
} }
} }
.sidemenu-org {
box-shadow: none;
}
.search-container { .search-container {
left: auto; left: auto;
} }
@ -60,20 +56,43 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
li { > li {
position: relative; position: relative;
@include left-brand-border();
&:hover { &:hover {
background-color: $side-menu-item-hover-bg;
@include left-brand-border-gradient();
.dropdown-menu { .dropdown-menu {
display: block; display: block;
opacity: 0;
top: 0px; top: 0px;
left: $side-menu-width; left: $side-menu-width;
background-color: $side-menu-bg; background-color: rgba($side-menu-bg,$side-menu-opacity);
@include animation('dropdown-anim 100ms ease-in-out 100ms forwards');
z-index: -9999;
} }
} }
} }
} }
@include keyframes(dropdown-anim) {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
transform: translate3d(-5%,0,0);
}
100% {
opacity: 1;
transform: translate3d(0,0,0);
}
}
.sidemenu-main-link { .sidemenu-main-link {
font-size: 16px; font-size: 16px;
} }
@ -110,10 +129,8 @@
line-height: 47px; line-height: 47px;
padding: 0px 10px 0px 10px; padding: 0px 10px 0px 10px;
display: block; display: block;
border-left: 1px solid transparent;
&:hover {
background-color: $side-menu-item-hover-bg;
}
.sidemenu-item-text { .sidemenu-item-text {
padding-left: 11px; padding-left: 11px;
@ -165,9 +182,6 @@
padding: 17px 10px 15px 14px; padding: 17px 10px 15px 14px;
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
&:hover {
background-color: $side-menu-item-hover-bg;
}
display: table; display: table;
position: relative; position: relative;
width: 100%; width: 100%;
@ -176,7 +190,7 @@
.sidemenu .fa-caret-right { .sidemenu .fa-caret-right {
position: absolute; position: absolute;
top: 38%; top: 38%;
right: 25px; right: 6px;
font-size: 14px; font-size: 14px;
color: $link-color; color: $link-color;
} }
@ -188,14 +202,26 @@
} }
.sidemenu-org-avatar { .sidemenu-org-avatar {
width: 44px;
}
.sidemenu-org-avatar > img {
width: 40px; width: 40px;
height: 40px; height: 40px;
background-color: $gray-2;
border-radius: 50%; border-radius: 50%;
position: absolute; text-align: center;
>img {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
left: 14px;
}
}
.sidemenu-org-avatar--missing {
color: $gray-4;
text-shadow: 0 1px 0 $dark-1;
line-height: 40px;
font-size: $font-size-lg;
} }
.sidemenu-org-details { .sidemenu-org-details {

View File

@ -13,7 +13,7 @@
} }
.gf-timepicker-dropdown { .gf-timepicker-dropdown {
margin: -5px -10px 10px 5px; margin: -8px -10px 10px 5px;
padding: 10px 20px; padding: 10px 20px;
float: right; float: right;
background-color: $panel-bg; background-color: $panel-bg;
@ -107,13 +107,11 @@
} }
.glyphicon-chevron-right { .glyphicon-chevron-right {
@extend .fa; @extend .fa;
@extend .fa-chevron-right; @extend .fa-chevron-right;
} }
.glyphicon-chevron-left { .glyphicon-chevron-left {
@extend .fa; @extend .fa;
@extend .fa-chevron-left; @extend .fa-chevron-left;
} }

View File

@ -20,17 +20,15 @@
.page-container { .page-container {
background-color: $page-bg; background-color: $page-bg;
position: relative;
padding: ($spacer * 2) ($spacer * 4); padding: ($spacer * 2) ($spacer * 4);
max-width: 1060px; max-width: 1060px;
margin-left: 0;
min-height: calc(100% - 54px); min-height: calc(100% - 54px);
padding-bottom: $spacer * 5; padding-bottom: $spacer * 5;
background-image: linear-gradient(60deg, transparent 70%, darken($page-bg, 4%) 98%)
} }
.page-header { .page-header {
padding: $spacer 0 $spacer/2 0; padding: $spacer 0 $spacer/2 0;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: flex-end; align-items: flex-end;
@ -40,7 +38,7 @@
border-top: 0; border-top: 0;
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-bottom: 4px solid transparent; border-bottom: 1px solid transparent;
h1 { h1 {
font-style: italic; font-style: italic;

View File

@ -0,0 +1,25 @@
@mixin keyframes($animation-name) {
@-webkit-keyframes #{$animation-name} {
@content;
}
@-moz-keyframes #{$animation-name} {
@content;
}
@-ms-keyframes #{$animation-name} {
@content;
}
@-o-keyframes #{$animation-name} {
@content;
}
@keyframes #{$animation-name} {
@content;
}
}
@mixin animation($str) {
-webkit-animation: #{$str};
-moz-animation: #{$str};
-ms-animation: #{$str};
-o-animation: #{$str};
animation: #{$str};
}

View File

@ -331,4 +331,15 @@
background-image: linear-gradient($angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent); background-image: linear-gradient($angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
} }
@mixin left-brand-border() {
border-left: 2px solid transparent;
}
@mixin left-brand-border-gradient() {
border-image: linear-gradient(rgba(255,213,0,1) 0%, rgba(255,68,0,1) 99%, rgba(255,68,0,1) 100%);
border-image-slice: 1;
border-top: 0;
border-right: 0;
border-bottom: 0;
border-left: 2px solid transparent;
}

View File

@ -1,3 +1,12 @@
.login-container {
background-position: left;
background-size: 60%;
background-repeat: no-repeat;
min-width: 100%;
margin-left: 0;
margin-top: -26px; /* BAD HACK - experiement to see how it looks */
padding-top: $spacer * 5; /* BAD HACK - experiement to see how it looks */
}
.login-form { .login-form {
display: inline-block; display: inline-block;
@ -6,11 +15,12 @@
.login-box { .login-box {
max-width: 700px; max-width: 700px;
margin: $spacer * 2 auto 0 auto; margin: 0 auto; /* was $spacer * 2 auto 0 auto; */
} }
.login-box-logo { .login-box-logo {
text-align: center; text-align: center;
margin-bottom: $spacer * 2;
img { img {
width: 6rem; width: 6rem;
} }
@ -173,7 +183,7 @@
width: 125px; width: 125px;
} }
.icon-gf-grafana_wordmark { .icon-gf-grafana_wordmark {
top: -90px; top: -5px;
font-size: 3rem; font-size: 3rem;
} }
} }

View File

@ -16,6 +16,7 @@
.style-guide-button-list { .style-guide-button-list {
padding: $spacer; padding: $spacer;
button { button {
display: block;
margin: 0 $spacer $spacer 0; margin: 0 $spacer $spacer 0;
} }
} }

View File

@ -28,6 +28,7 @@
} }
} }
// Positioning // Positioning
.pos-f-t { .pos-f-t {

View File

@ -9,13 +9,15 @@
// Close icons // Close icons
// -------------------------------------------------- // --------------------------------------------------
.close { .close {
@include opacity(20);
float: right; float: right;
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
line-height: $line-height-base; line-height: $line-height-base;
color: $black; color: $black;
text-shadow: 0 1px 0 rgba(255,255,255,1); text-shadow: 0 1px 0 rgba(255,255,255,1);
@include opacity(20);
&:hover, &:hover,
&:focus { &:focus {
color: $black; color: $black;

View File

@ -0,0 +1,19 @@
.max-width { width: 100%; }
.width-auto { width: auto; }
// widths
@for $i from 1 through 30 {
.width-#{$i} {
width: ($spacer * $i) - $gf-form-margin;
}
}
@for $i from 1 through 30 {
.max-width-#{$i} {
max-width: ($spacer * $i) - $gf-form-margin;
flex-grow: 1;
}
}

View File

@ -30458,4 +30458,4 @@ $provide.value("$locale", {
})(window, document); })(window, document);
!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); !window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');

View File

@ -2,7 +2,7 @@
module.exports = function(grunt) { module.exports = function(grunt) {
'use strict'; 'use strict';
grunt.registerTask('css', ['sass', 'concat:cssDark', 'concat:cssLight', 'styleguide']); grunt.registerTask('css', ['sass', 'concat:cssDark', 'concat:cssLight', 'styleguide', 'sasslint']);
grunt.registerTask('default', [ grunt.registerTask('default', [
'jscs', 'jscs',
'jshint', 'jshint',

View File

@ -31,6 +31,8 @@ module.exports = function(config) {
'reflect-metadata/*.ts', 'reflect-metadata/*.ts',
'reflect-metadata/*.d.ts', 'reflect-metadata/*.d.ts',
'rxjs/**/*', 'rxjs/**/*',
'tether/**/*',
'tether-drop/**/*',
], ],
dest: '<%= srcDir %>/vendor/npm' dest: '<%= srcDir %>/vendor/npm'
} }

View File

@ -1,10 +1,12 @@
module.exports = function(config) { module.exports = function(config) {
'use strict'; 'use strict';
return { return {
options: { options: {
configFile: 'public/sass/.sass-lint.yml', configFile: 'public/sass/.sass-lint.yml',
}, },
target: ['public/sass/**/*.scss', '!public/sass/base/_normalize.scss'] target: [
'public/sass/*.scss',
'public/sass/components/*.scss',
]
}; };
}; };

View File

@ -29,7 +29,6 @@
"no-shadowed-variable": false, "no-shadowed-variable": false,
"no-string-literal": false, "no-string-literal": false,
"no-switch-case-fall-through": false, "no-switch-case-fall-through": false,
"no-trailing-comma": true,
"no-trailing-whitespace": true, "no-trailing-whitespace": true,
"no-unused-expression": false, "no-unused-expression": false,
"no-unused-variable": false, "no-unused-variable": false,