mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'develop-new-page-header' into develop
This commit is contained in:
commit
e348ec8c3b
@ -24,11 +24,13 @@ type NavLink struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
SubTitle string `json:"subTitle,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Img string `json:"img,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
Divider bool `json:"divider,omitempty"`
|
||||
HideFromMenu bool `json:"hideFromMenu,omitempty"`
|
||||
HideFromTabs bool `json:"hideFromTabs,omitempty"`
|
||||
Children []*NavLink `json:"children,omitempty"`
|
||||
}
|
||||
|
112
pkg/api/index.go
112
pkg/api/index.go
@ -101,38 +101,41 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
}
|
||||
|
||||
dashboardChildNavs := []*dtos.NavLink{
|
||||
{Text: "Home", Url: setting.AppSubUrl + "/", Icon: "fa fa-fw fa-home"},
|
||||
{Text: "Home", Url: setting.AppSubUrl + "/", Icon: "fa fa-fw fa-home", HideFromTabs: true},
|
||||
{Divider: true},
|
||||
{Text: "Manage", Id: "dashboards", Url: setting.AppSubUrl + "/dashboards", Icon: "fa fa-fw fa-sitemap"},
|
||||
{Text: "Playlists", Id: "playlists", Url: setting.AppSubUrl + "/playlists", Icon: "fa fa-fw fa-film"},
|
||||
{Text: "Snapshots", Id: "snapshots", Url: setting.AppSubUrl + "/dashboard/snapshots", Icon: "icon-gf icon-gf-fw icon-gf-snapshot"},
|
||||
{Text: "Dashboard List", Description: "Manage Dashboards And Folders", Id: "dashboards", Url: setting.AppSubUrl + "/dashboards", Icon: "fa fa-fw fa-bars"},
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||
Text: "Dashboards",
|
||||
Id: "dashboards",
|
||||
SubTitle: "Manage dashboards & folders",
|
||||
Icon: "gicon gicon-dashboard",
|
||||
Url: setting.AppSubUrl + "/",
|
||||
Url: setting.AppSubUrl + "/dashboards",
|
||||
Children: dashboardChildNavs,
|
||||
})
|
||||
|
||||
if c.IsSignedIn {
|
||||
profileNode := &dtos.NavLink{
|
||||
Text: c.SignedInUser.Login,
|
||||
Text: c.SignedInUser.Name,
|
||||
SubTitle: c.SignedInUser.Login,
|
||||
Id: "profile",
|
||||
Img: data.User.GravatarUrl,
|
||||
Url: setting.AppSubUrl + "/profile",
|
||||
HideFromMenu: true,
|
||||
Children: []*dtos.NavLink{
|
||||
{Text: "Your profile", Url: setting.AppSubUrl + "/profile", Icon: "fa fa-fw fa-sliders"},
|
||||
{Text: "Preferences", Id: "profile-settings", Url: setting.AppSubUrl + "/profile", Icon: "fa fa-fw fa-sliders"},
|
||||
{Text: "Change Password", Id: "change-password", Url: setting.AppSubUrl + "/profile/password", Icon: "fa fa-fw fa-lock", HideFromMenu: true},
|
||||
},
|
||||
}
|
||||
|
||||
if !setting.DisableSignoutMenu {
|
||||
// add sign out first
|
||||
profileNode.Children = append([]*dtos.NavLink{
|
||||
{Text: "Sign out", Url: setting.AppSubUrl + "/logout", Icon: "fa fa-fw fa-sign-out", Target: "_self"},
|
||||
}, profileNode.Children...)
|
||||
profileNode.Children = append(profileNode.Children, &dtos.NavLink{
|
||||
Text: "Sign out", Id: "sign-out", Url: setting.AppSubUrl + "/logout", Icon: "fa fa-fw fa-sign-out", Target: "_self",
|
||||
})
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, profileNode)
|
||||
@ -140,12 +143,13 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
|
||||
if setting.AlertingEnabled && (c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR) {
|
||||
alertChildNavs := []*dtos.NavLink{
|
||||
{Text: "Alert List", Id: "alert-list", Url: setting.AppSubUrl + "/alerting/list", Icon: "fa fa-fw fa-list-ul"},
|
||||
{Text: "Notification channels", Id: "channels", Url: setting.AppSubUrl + "/alerting/notifications", Icon: "fa fa-fw fa-bell-o"},
|
||||
{Text: "Alert Rules", Id: "alert-list", Url: setting.AppSubUrl + "/alerting/list", Icon: "fa fa-fw fa-list-ul"},
|
||||
{Text: "Notification channels", Id: "channels", Url: setting.AppSubUrl + "/alerting/notifications", Icon: "gicon gicon-alert-notification-channel"},
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||
Text: "Alerting",
|
||||
SubTitle: "Alert rules & notifications",
|
||||
Id: "alerting",
|
||||
Icon: "gicon gicon-alert",
|
||||
Url: setting.AppSubUrl + "/alerting/list",
|
||||
@ -202,10 +206,11 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
|
||||
if c.OrgRole == m.ROLE_ADMIN {
|
||||
cfgNode := &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
Icon: "fa fa-fw fa-cogs",
|
||||
Url: setting.AppSubUrl + "/configuration",
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "fa fa-fw fa-cog",
|
||||
Url: setting.AppSubUrl + "/datasources",
|
||||
Children: []*dtos.NavLink{
|
||||
{
|
||||
Text: "Data Sources",
|
||||
@ -213,29 +218,6 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
Description: "Add and configure data sources",
|
||||
Id: "datasources",
|
||||
Url: setting.AppSubUrl + "/datasources",
|
||||
Children: []*dtos.NavLink{
|
||||
{Text: "List", Url: setting.AppSubUrl + "/datasources", Icon: "gicon gicon-datasources"},
|
||||
{Text: "New", Url: setting.AppSubUrl + "/datasources", Icon: "fa fa-fw fa-plus"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Text: "Preferences",
|
||||
Id: "org",
|
||||
Description: "Organization preferences",
|
||||
Icon: "fa fa-fw fa-sliders",
|
||||
Url: setting.AppSubUrl + "/org",
|
||||
},
|
||||
{
|
||||
Text: "Plugins",
|
||||
Id: "plugins",
|
||||
Description: "View and configure plugins",
|
||||
Icon: "icon-gf icon-gf-fw icon-gf-apps",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
Children: []*dtos.NavLink{
|
||||
{Text: "Panels", Url: setting.AppSubUrl + "/plugins?type=panel", Icon: "fa fa-fw fa-stop"},
|
||||
{Text: "Data sources", Url: setting.AppSubUrl + "/plugins?type=datasource", Icon: "icon-gf icon-gf-datasources"},
|
||||
{Text: "Apps", Url: setting.AppSubUrl + "/plugins?type=app", Icon: "icon-gf icon-gf-apps"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Text: "Members",
|
||||
@ -245,12 +227,32 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
Url: setting.AppSubUrl + "/org/users",
|
||||
},
|
||||
{
|
||||
Text: "Groups",
|
||||
Id: "users",
|
||||
Text: "Teams",
|
||||
Id: "teams",
|
||||
Description: "Manage org groups",
|
||||
Icon: "fa fa-fw fa-users",
|
||||
Icon: "gicon gicon-user-group",
|
||||
Url: setting.AppSubUrl + "/org/user-groups",
|
||||
},
|
||||
{
|
||||
Text: "Plugins",
|
||||
Id: "plugins",
|
||||
Description: "View and configure plugins",
|
||||
Icon: "icon-gf icon-gf-fw icon-gf-apps",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
// Children: []*dtos.NavLink{
|
||||
// {Text: "Panels", Url: setting.AppSubUrl + "/plugins?type=panel", Icon: "fa fa-fw fa-stop"},
|
||||
// {Text: "Data sources", Url: setting.AppSubUrl + "/plugins?type=datasource", Icon: "icon-gf icon-gf-datasources"},
|
||||
// {Text: "Apps", Url: setting.AppSubUrl + "/plugins?type=app", Icon: "icon-gf icon-gf-apps"},
|
||||
// },
|
||||
},
|
||||
{
|
||||
Text: "Preferences",
|
||||
Id: "org-settings",
|
||||
Description: "Organization preferences",
|
||||
Icon: "fa fa-fw fa-sliders",
|
||||
Url: setting.AppSubUrl + "/org",
|
||||
},
|
||||
|
||||
{
|
||||
Text: "API Keys",
|
||||
Id: "apikeys",
|
||||
@ -261,21 +263,21 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
},
|
||||
}
|
||||
|
||||
if c.IsGrafanaAdmin {
|
||||
cfgNode.Children = append(cfgNode.Children, &dtos.NavLink{
|
||||
Text: "Server Admin",
|
||||
Id: "admin",
|
||||
Icon: "fa fa-fw fa-shield",
|
||||
Url: setting.AppSubUrl + "/admin",
|
||||
Children: []*dtos.NavLink{
|
||||
{Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users"},
|
||||
{Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs"},
|
||||
{Text: "Server Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings"},
|
||||
{Text: "Server Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats"},
|
||||
{Text: "Style Guide", Id: "styleguide", Url: setting.AppSubUrl + "/styleguide"},
|
||||
},
|
||||
})
|
||||
}
|
||||
// if c.IsGrafanaAdmin {
|
||||
// cfgNode.Children = append(cfgNode.Children, &dtos.NavLink{
|
||||
// Text: "Server Admin",
|
||||
// Id: "admin",
|
||||
// Icon: "fa fa-fw fa-shield",
|
||||
// Url: setting.AppSubUrl + "/admin",
|
||||
// Children: []*dtos.NavLink{
|
||||
// {Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users"},
|
||||
// {Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs"},
|
||||
// {Text: "Server Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings"},
|
||||
// {Text: "Server Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats"},
|
||||
// {Text: "Style Guide", Id: "styleguide", Url: setting.AppSubUrl + "/styleguide"},
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
|
||||
data.NavTree = append(data.NavTree, cfgNode)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { react2AngularDirective } from 'app/core/utils/react2angular';
|
||||
import { PasswordStrength } from './components/PasswordStrength';
|
||||
import PageHeader from './components/PageHeader';
|
||||
|
||||
export function registerAngularDirectives() {
|
||||
|
||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||
react2AngularDirective('pageHeader', PageHeader, ['model', "noTabs"]);
|
||||
|
||||
}
|
||||
|
94
public/app/core/components/PageHeader.tsx
Normal file
94
public/app/core/components/PageHeader.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import { NavModel, NavModelItem } from '../nav_model_srv';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export interface IProps {
|
||||
model: NavModel;
|
||||
}
|
||||
|
||||
// function BreadcrumbItem(item: NavModelItem) {
|
||||
// return (
|
||||
// <a className="breadcrumb-item" href={item.url} key={item.id}>
|
||||
// {item.text}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// function Breadcrumb(model: NavModel) {
|
||||
// return (
|
||||
// <div className="page-nav">
|
||||
// <div className="page-breadcrumbs">
|
||||
// <a className="breadcrumb-item active" href="/">
|
||||
// <i className="fa fa-home" />
|
||||
// </a>
|
||||
// {model.breadcrumbs.map(BreadcrumbItem)}
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
function TabItem(tab: NavModelItem) {
|
||||
if (tab.hideFromTabs || tab.divider) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
let tabClasses = classNames({
|
||||
'gf-tabs-link': true,
|
||||
active: tab.active,
|
||||
});
|
||||
|
||||
return (
|
||||
<li className="gf-tabs-item" key={tab.url}>
|
||||
<a className={tabClasses} href={tab.url}>
|
||||
<i className={tab.icon} />
|
||||
{tab.text}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function Tabs({main}: {main: NavModelItem}) {
|
||||
return <ul className="gf-tabs">{main.children.map(TabItem)}</ul>;
|
||||
}
|
||||
|
||||
export default class PageHeader extends React.Component<IProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderHeaderTitle(main) {
|
||||
return (
|
||||
<div className="page-header__inner">
|
||||
<span className="page-header__logo">
|
||||
{main.icon && <i className={`page-header__icon ${main.icon}`} />}
|
||||
{main.img && <img className="page-header__img" src={main.img} />}
|
||||
</span>
|
||||
|
||||
<div className="page-header__info-block">
|
||||
<h1 className="page-header__title">{main.text}</h1>
|
||||
{main.subTitle && <div className="page-header__sub-title">{main.subTitle}</div>}
|
||||
{main.subType && (
|
||||
<div className="page-header__stamps">
|
||||
<i className={main.subType.icon} />
|
||||
{main.subType.text}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="page-header-canvas">
|
||||
<div className="page-container">
|
||||
<div className="page-header">
|
||||
{this.renderHeaderTitle(this.props.model.main)}
|
||||
|
||||
{this.props.model.main.children && <Tabs main={this.props.model.main} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,13 +1,11 @@
|
||||
<div class="page-nav">
|
||||
<div class="container">
|
||||
<div class="page-breadcrumbs">
|
||||
<a class="breadcrumb-item active" href="/">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
<a class="breadcrumb-item" ng-href="{{::item.url}}" ng-repeat="item in ctrl.model.breadcrumbs">
|
||||
{{::item.text}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="page-breadcrumbs">
|
||||
<a class="breadcrumb-item active" href="/">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
<a class="breadcrumb-item" ng-href="{{::item.url}}" ng-repeat="item in ctrl.model.breadcrumbs">
|
||||
{{::item.text}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -39,10 +39,10 @@ export function pageH1() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: `
|
||||
<h1>
|
||||
<i class="{{::model.node.icon}}" ng-if="::model.node.icon"></i>
|
||||
<img ng-src="{{::model.node.img}}" ng-if="::model.node.img"></i>
|
||||
{{model.node.text}}
|
||||
<h1 class="page-header__title">
|
||||
<i class="page-header__icon {{::model.header.icon}}" ng-if="::model.header.icon"></i>
|
||||
<img class="page-header__img" ng-src="{{::model.header.img}}" ng-if="::model.header.img"></i>
|
||||
{{model.header.text}}
|
||||
</h1>
|
||||
`,
|
||||
scope: {
|
||||
|
@ -1,19 +1,27 @@
|
||||
///<reference path="../headers/common.d.ts" />
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
import config from 'app/core/config';
|
||||
import _ from 'lodash';
|
||||
|
||||
export interface NavModelItem {
|
||||
title: string;
|
||||
text: string;
|
||||
url: string;
|
||||
icon?: string;
|
||||
iconUrl?: string;
|
||||
img?: string;
|
||||
id: string;
|
||||
active?: boolean;
|
||||
hideFromTabs?: boolean;
|
||||
divider?: boolean;
|
||||
children: NavModelItem[];
|
||||
}
|
||||
|
||||
export interface NavModel {
|
||||
section: NavModelItem;
|
||||
menu: NavModelItem[];
|
||||
export class NavModel {
|
||||
breadcrumbs: NavModelItem[];
|
||||
main: NavModelItem;
|
||||
node: NavModelItem;
|
||||
|
||||
constructor() {
|
||||
this.breadcrumbs = [];
|
||||
}
|
||||
}
|
||||
|
||||
export class NavModelSrv {
|
||||
@ -31,15 +39,32 @@ export class NavModelSrv {
|
||||
|
||||
getNav(...args) {
|
||||
var children = this.navItems;
|
||||
var nav = {breadcrumbs: [], node: null};
|
||||
var nav = new NavModel();
|
||||
|
||||
for (let id of args) {
|
||||
// if its a number then it's the index to use for main
|
||||
if (_.isNumber(id)) {
|
||||
nav.main = nav.breadcrumbs[id];
|
||||
break;
|
||||
}
|
||||
|
||||
let node = _.find(children, {id: id});
|
||||
nav.breadcrumbs.push(node);
|
||||
nav.node = node;
|
||||
nav.main = node;
|
||||
children = node.children;
|
||||
}
|
||||
|
||||
if (nav.main.children) {
|
||||
for (let item of nav.main.children) {
|
||||
item.active = false;
|
||||
|
||||
if (item.url === nav.node.url) {
|
||||
item.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nav;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
</div>
|
||||
<page-header model="ctrl.navModel" no-tabs="true"></page-header>
|
||||
|
||||
<div class="page-container page-body">
|
||||
<section class="card-section card-list-layout-grid">
|
||||
<ol class="card-list">
|
||||
<li class="card-item-wrapper" ng-repeat="navItem in ctrl.navModel.node.children">
|
||||
@ -29,4 +26,4 @@
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@ export class AlertListCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, private $location, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('alerting');
|
||||
this.navModel = navModelSrv.getNav('alerting', 'alert-list', 0);
|
||||
|
||||
var params = $location.search();
|
||||
this.filters.state = params.state || null;
|
||||
|
@ -9,7 +9,7 @@ export class AlertNotificationEditCtrl {
|
||||
testSeverity = "critical";
|
||||
notifiers: any;
|
||||
notifierTemplateId: string;
|
||||
|
||||
isNew: boolean;
|
||||
model: any;
|
||||
defaults: any = {
|
||||
type: 'email',
|
||||
@ -23,7 +23,8 @@ export class AlertNotificationEditCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $routeParams, private backendSrv, private $location, private $templateCache, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('alerting', 'channels');
|
||||
this.navModel = navModelSrv.getNav('alerting', 'channels', 0);
|
||||
this.isNew = !this.$routeParams.id;
|
||||
|
||||
this.backendSrv.get(`/api/alert-notifiers`).then(notifiers => {
|
||||
this.notifiers = notifiers;
|
||||
|
@ -9,7 +9,7 @@ export class AlertNotificationsListCtrl {
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, navModelSrv) {
|
||||
this.loadNotifications();
|
||||
this.navModel = navModelSrv.getNav('alerting', 'channels');
|
||||
this.navModel = navModelSrv.getNav('alerting', 'channels', 0);
|
||||
}
|
||||
|
||||
loadNotifications() {
|
||||
|
@ -1,29 +1,23 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container" >
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<div class="page-container page-body">
|
||||
|
||||
<a class="btn btn-secondary" ng-click="ctrl.openHowTo()">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
How to add an alert
|
||||
</a>
|
||||
<a class="btn btn-inverse" href="alerting/notifications" >
|
||||
<i class="fa fa-bell"></i>
|
||||
Notification channels
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">Filter by state</label>
|
||||
<div class="gf-form-select-wrapper width-13">
|
||||
<select class="gf-form-input" ng-model="ctrl.filters.state" ng-options="f.value as f.text for f in ctrl.stateFilters" ng-change="ctrl.filtersChanged()">
|
||||
</select>
|
||||
</div>
|
||||
<div class="page-action-bar">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">Filter by state</label>
|
||||
<div class="gf-form-select-wrapper width-13">
|
||||
<select class="gf-form-input" ng-model="ctrl.filters.state" ng-options="f.value as f.text for f in ctrl.stateFilters" ng-change="ctrl.filtersChanged()">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-action-bar__spacer">
|
||||
</div>
|
||||
|
||||
<a class="btn btn-secondary" ng-click="ctrl.openHowTo()">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
How to add an alert
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<section class="card-section card-list-layout-list">
|
||||
|
@ -1,9 +1,9 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
</div>
|
||||
<div class="page-container page-body">
|
||||
|
||||
<h3 class="page-sub-heading" ng-hide="ctrl.isNew">Edit Notification Channel</h3>
|
||||
<h3 class="page-sub-heading" ng-show="ctrl.isNew">New Notification Channel</h3>
|
||||
|
||||
<form name="ctrl.theForm" ng-if="ctrl.notifiers">
|
||||
<div class="gf-form-group">
|
||||
|
@ -1,10 +1,12 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container" >
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="page-action-bar__spacer">
|
||||
</div>
|
||||
|
||||
<a href="alerting/notification/new" class="btn btn-success pull-right">
|
||||
<a href="alerting/notification/new" class="btn btn-success">
|
||||
<i class="fa fa-plus"></i>
|
||||
New Channel
|
||||
</a>
|
||||
</div>
|
||||
|
@ -17,7 +17,7 @@ export class DashboardListCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, navModelSrv, private $q, private searchSrv: SearchSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'dashboards');
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'dashboards', 0);
|
||||
this.query = {query: '', mode: 'tree', tag: [], starred: false};
|
||||
this.selectedStarredFilter = this.starredFilterOptions[0];
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<div class="page-container" style="height: 95%">
|
||||
<div class="page-header">
|
||||
<h1>Dashboards</h1>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="gf-form width-15">
|
||||
<label class="gf-form-label">Search</label>
|
||||
<input type="text" class="gf-form-input" placeholder="Find Dashboard by name" tabindex="1" give-focus="true" ng-model="ctrl.query.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.onQueryChange()" />
|
||||
</div>
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<a class="btn btn-inverse" href="/dashboard/new">
|
||||
<i class="gicon gicon-dashboard-new"></i>
|
||||
Dashboard
|
||||
@ -12,14 +16,6 @@
|
||||
Folder
|
||||
</a>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form width-15">
|
||||
<span style="position: relative;">
|
||||
<input type="text" class="gf-form-input" placeholder="Find Dashboard by name" tabindex="1" give-focus="true"
|
||||
ng-model="ctrl.query.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.onQueryChange()" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-if="ctrl.query.tag.length">
|
||||
Filters:
|
||||
|
@ -5,6 +5,7 @@ import './select_org_ctrl';
|
||||
import './change_password_ctrl';
|
||||
import './new_org_ctrl';
|
||||
import './user_invite_ctrl';
|
||||
import './user_groups_ctrl';
|
||||
import './org_api_keys_ctrl';
|
||||
import './org_details_ctrl';
|
||||
import './prefs_control';
|
||||
|
@ -4,7 +4,7 @@ export class OrgApiKeysCtrl {
|
||||
|
||||
/** @ngInject **/
|
||||
constructor ($scope, $http, backendSrv, navModelSrv) {
|
||||
$scope.navModel = navModelSrv.getNav('cfg', 'apikeys');
|
||||
$scope.navModel = navModelSrv.getNav('cfg', 'apikeys', 0);
|
||||
|
||||
$scope.roleTypes = ['Viewer', 'Editor', 'Admin'];
|
||||
$scope.token = { role: 'Viewer' };
|
||||
|
@ -6,7 +6,7 @@ export class OrgDetailsCtrl {
|
||||
constructor($scope, $http, backendSrv, contextSrv, navModelSrv) {
|
||||
$scope.init = function() {
|
||||
$scope.getOrgInfo();
|
||||
$scope.navModel = navModelSrv.getNav('cfg', 'org');
|
||||
$scope.navModel = navModelSrv.getNav('cfg', 'org-settings', 0);
|
||||
};
|
||||
|
||||
$scope.getOrgInfo = function() {
|
||||
|
@ -23,7 +23,7 @@ export class OrgUsersCtrl {
|
||||
role: 'Viewer',
|
||||
};
|
||||
|
||||
this.navModel = navModelSrv.getNav('cfg', 'users');
|
||||
this.navModel = navModelSrv.getNav('cfg', 'users', 0);
|
||||
|
||||
this.get();
|
||||
this.editor = { index: 0 };
|
||||
@ -44,8 +44,7 @@ export class OrgUsersCtrl {
|
||||
if (this.externalUserMngLinkName) {
|
||||
return this.externalUserMngLinkName;
|
||||
}
|
||||
|
||||
return "Add Members";
|
||||
return "Add Member";
|
||||
}
|
||||
|
||||
get() {
|
||||
|
@ -1,11 +1,9 @@
|
||||
<navbar model="navModel"></navbar>
|
||||
<page-header model="navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="navModel"></page-h1>
|
||||
</div>
|
||||
<div class="page-container page-body">
|
||||
|
||||
<h3 class="section-heading">Add new</h3>
|
||||
|
||||
<h3 class="page-heading">Add new</h3>
|
||||
<form name="addTokenForm" class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-21">
|
||||
@ -22,7 +20,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h3 class="page-heading">Existing Keys</h3>
|
||||
<h3 class="section-heading">Existing Keys</h3>
|
||||
<table class="filter-table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -1,26 +1,52 @@
|
||||
<navbar model="navModel"></navbar>
|
||||
<!-- <div class="page-header-canvas"> -->
|
||||
<!-- <div class="page-container" > -->
|
||||
<!-- <navbar model="navModel"></navbar> -->
|
||||
<!-- -->
|
||||
<!-- <div class="page-header"> -->
|
||||
<!-- <page-h1 model="navModel"></page-h1> -->
|
||||
<!-- -->
|
||||
<!-- <ul class="gf-tabs"> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link active" href="org"> -->
|
||||
<!-- <i class="fa fa-fw fa-sliders"></i> -->
|
||||
<!-- Preferences -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" href="org/users"> -->
|
||||
<!-- <i class="icon-gf icon-gf-fw icon-gf-users"></i> -->
|
||||
<!-- Members -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" href="org/user-groups"> -->
|
||||
<!-- <i class="gicon gicon-user-group"></i> -->
|
||||
<!-- Teams -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- </ul> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="navModel"></page-h1>
|
||||
</div>
|
||||
<page-header model="navModel"></page-header>
|
||||
|
||||
<h3 class="page-heading">General</h3>
|
||||
<form name="orgForm" class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-28">
|
||||
<span class="gf-form-label">Organization name</span>
|
||||
<input class="gf-form-input" type="text" required ng-model="org.name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-container page-body">
|
||||
<h3 class="page-sub-heading">Organization profile</h3>
|
||||
|
||||
<form name="orgForm" class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-28">
|
||||
<span class="gf-form-label">Organization name</span>
|
||||
<input class="gf-form-input" type="text" required ng-model="org.name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<button type="submit" class="btn btn-success" ng-click="update()">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<prefs-control mode="org"></prefs-control>
|
||||
|
||||
</form>
|
||||
<prefs-control mode="org"></prefs-control>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -1,34 +1,52 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<!-- <navbar model="ctrl.navModel"></navbar> -->
|
||||
<!-- -->
|
||||
<!-- <div class="page-container"> -->
|
||||
<!-- <div class="page-header"> -->
|
||||
<!-- <page-h1 model="ctrl.navModel"></page-h1> -->
|
||||
<!-- -->
|
||||
<!-- <button class="btn btn-success" ng-click="ctrl.openAddUsersView()" ng-hide="ctrl.externalUserMngLinkUrl"> -->
|
||||
<!-- <span>{{ctrl.addUsersBtnName}}</span> -->
|
||||
<!-- </button> -->
|
||||
<!-- -->
|
||||
<!-- <div class="page-header-tabs"> -->
|
||||
<!-- -->
|
||||
<!-- <a class="btn btn-inverse" ng-href="{{ctrl.externalUserMngLinkUrl}}" target="_blank" ng-if="ctrl.externalUserMngLinkUrl"> -->
|
||||
<!-- <i class="fa fa-external-link-square"></i> -->
|
||||
<!-- {{ctrl.addUsersBtnName}} -->
|
||||
<!-- </a> -->
|
||||
<!-- -->
|
||||
<!-- <ul class="gf-tabs"> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" ng-click="ctrl.editor.index = 0" ng-class="{active: ctrl.editor.index === 0}"> -->
|
||||
<!-- Users ({{ctrl.users.length}}) -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- <li class="gf-tabs-item" ng-show="ctrl.pendingInvites.length"> -->
|
||||
<!-- <a class="gf-tabs-link" ng-click="ctrl.editor.index = 1" ng-class="{active: ctrl.editor.index === 1}"> -->
|
||||
<!-- Pending Invites ({{ctrl.pendingInvites.length}}) -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- </ul> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<button class="btn btn-inverse" ng-show="ctrl.pendingInvites.length" ng-click="ctrl.editor.index = 1">
|
||||
Pending Invites ({{ctrl.pendingInvites.length}})
|
||||
</button>
|
||||
<button class="btn btn-success" ng-click="ctrl.openAddUsersView()" ng-hide="ctrl.externalUserMngLinkUrl">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span>{{ctrl.addUsersBtnName}}</span>
|
||||
</button>
|
||||
|
||||
<div class="page-header-tabs">
|
||||
|
||||
<a class="btn btn-inverse" ng-href="{{ctrl.externalUserMngLinkUrl}}" target="_blank" ng-if="ctrl.externalUserMngLinkUrl">
|
||||
<i class="fa fa-external-link-square"></i>
|
||||
{{ctrl.addUsersBtnName}}
|
||||
</a>
|
||||
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.editor.index = 0" ng-class="{active: ctrl.editor.index === 0}">
|
||||
Users ({{ctrl.users.length}})
|
||||
</a>
|
||||
</li>
|
||||
<li class="gf-tabs-item" ng-show="ctrl.pendingInvites.length">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.editor.index = 1" ng-class="{active: ctrl.editor.index === 1}">
|
||||
Pending Invites ({{ctrl.pendingInvites.length}})
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-inverse" ng-href="{{ctrl.externalUserMngLinkUrl}}" target="_blank" ng-if="ctrl.externalUserMngLinkUrl">
|
||||
<i class="fa fa-external-link-square"></i>
|
||||
{{ctrl.addUsersBtnName}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="grafana-info-box" ng-if="ctrl.externalUserMngInfo">
|
||||
<span ng-bind-html="ctrl.externalUserMngInfo"></span>
|
||||
@ -41,26 +59,26 @@
|
||||
<th></th>
|
||||
<th>Login</th>
|
||||
<th>Email</th>
|
||||
<th>
|
||||
Seen
|
||||
<tip>Time since user was seen using Grafana</tip>
|
||||
</th>
|
||||
<th>
|
||||
Seen
|
||||
<tip>Time since user was seen using Grafana</tip>
|
||||
</th>
|
||||
<th>Role</th>
|
||||
<th style="width: 34px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="user in ctrl.users">
|
||||
<td class="width-4 text-center">
|
||||
<img class="filter-table__avatar" ng-src="{{user.avatarUrl}}"></img>
|
||||
</td>
|
||||
<img class="filter-table__avatar" ng-src="{{user.avatarUrl}}"></img>
|
||||
</td>
|
||||
<td>{{user.login}}</td>
|
||||
<td><span class="ellipsis">{{user.email}}</span></td>
|
||||
<td>{{user.lastSeenAtAge}}</td>
|
||||
<td>{{user.lastSeenAtAge}}</td>
|
||||
<td>
|
||||
<div class="gf-form-select-wrapper width-9">
|
||||
<select type="text" ng-model="user.role" class="gf-form-input" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']" ng-change="ctrl.updateOrgUser(user)">
|
||||
</select>
|
||||
</div>
|
||||
<div class="gf-form-select-wrapper width-9">
|
||||
<select type="text" ng-model="user.role" class="gf-form-input" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']" ng-change="ctrl.updateOrgUser(user)">
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">
|
||||
|
@ -1,12 +1,9 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
</div>
|
||||
<div class="page-container page-body">
|
||||
<h3 class="page-sub-heading">User Profile</h3>
|
||||
|
||||
<form name="ctrl.userForm" class="gf-form-group">
|
||||
<h3 class="page-heading">Information</h3>
|
||||
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-8">Name</span>
|
||||
|
@ -1,20 +1,22 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h1>User Groups</h1>
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
|
||||
<div class="gf-form width-15">
|
||||
<label class="gf-form-label">Search</label>
|
||||
<input type="text" class="gf-form-input" placeholder="Find User Group by name" tabindex="1" give-focus="true"
|
||||
ng-model="ctrl.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.get()" />
|
||||
</div>
|
||||
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
|
||||
<a class="btn btn-success" ng-click="ctrl.openUserGroupModal()">
|
||||
<i class="fa fa-plus"></i>
|
||||
Create User Group
|
||||
</a>
|
||||
</div>
|
||||
<div class="gf-form width-15 gf-form-group">
|
||||
<span style="position: relative;">
|
||||
<input type="text" class="gf-form-input" placeholder="Find User Group by name" tabindex="1" give-focus="true"
|
||||
ng-model="ctrl.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.get()" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="admin-list-table">
|
||||
<table class="filter-table form-inline" ng-show="ctrl.userGroups.length > 0">
|
||||
<thead>
|
||||
@ -42,7 +44,6 @@
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
@ -49,7 +49,7 @@ export class PrefsControlCtrl {
|
||||
|
||||
var template = `
|
||||
<form name="ctrl.prefsForm" class="section gf-form-group">
|
||||
<h3 class="page-heading">Preferences</h3>
|
||||
<h3 class="section-heading">Preferences</h3>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-11">UI Theme</span>
|
||||
|
@ -14,7 +14,7 @@ export class ProfileCtrl {
|
||||
constructor(private backendSrv, private contextSrv, private $location, navModelSrv) {
|
||||
this.getUser();
|
||||
this.getUserOrgs();
|
||||
this.navModel = navModelSrv.getNav('profile');
|
||||
this.navModel = navModelSrv.getNav('profile', 'profile-settings', 0);
|
||||
}
|
||||
|
||||
getUser() {
|
||||
|
@ -15,7 +15,7 @@ export class UserGroupsCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('cfg', 'users');
|
||||
this.navModel = navModelSrv.getNav('cfg', 'teams', 0);
|
||||
this.get();
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container" ng-form="playlistEditForm">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
</div>
|
||||
<div class="page-container page-body" ng-form="playlistEditForm">
|
||||
|
||||
<h3 class="page-sub-heading" ng-hide="ctrl.isNew">Edit Playlist</h3>
|
||||
<h3 class="page-sub-heading" ng-show="ctrl.isNew">New Playlist</h3>
|
||||
|
||||
<p class="playlist-description">A playlist rotates through a pre-selected list of Dashboards. A Playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.</p>
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<a class="btn btn-success " ng-show="ctrl.isNew()"
|
||||
<a class="btn btn-success " ng-show="ctrl.isNew"
|
||||
ng-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()"
|
||||
ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Create new playlist</a>
|
||||
<a class="btn btn-success" ng-show="!ctrl.isNew()"
|
||||
|
@ -1,15 +1,15 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<a class="btn btn-primary pull-right" href="playlists/create">
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<a class="btn btn-success pull-right" href="playlists/create">
|
||||
<i class="fa fa-plus"></i>
|
||||
New Playlist
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<table class="filter-table" style="margin-top: 20px">
|
||||
<table class="filter-table">
|
||||
<thead>
|
||||
<th><strong>Name</strong></th>
|
||||
<th><strong>Start url</strong></th>
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import coreModule from '../../core/core_module';
|
||||
|
||||
@ -11,10 +9,12 @@ export class PlaylistEditCtrl {
|
||||
playlist: any = {
|
||||
interval: '5m',
|
||||
};
|
||||
|
||||
playlistItems: any = [];
|
||||
dashboardresult: any = [];
|
||||
tagresult: any = [];
|
||||
navModel: any;
|
||||
isNew: boolean;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(
|
||||
@ -24,7 +24,9 @@ export class PlaylistEditCtrl {
|
||||
$route,
|
||||
navModelSrv
|
||||
) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists');
|
||||
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists', 0);
|
||||
this.isNew = $route.current.params.id;
|
||||
|
||||
if ($route.current.params.id) {
|
||||
var playlistId = $route.current.params.id;
|
||||
@ -104,10 +106,6 @@ export class PlaylistEditCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
isNew() {
|
||||
return !this.playlist.id;
|
||||
}
|
||||
|
||||
isPlaylistEmpty() {
|
||||
return !this.playlistItems.length;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ export class PlaylistsCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $scope, private backendSrv, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists');
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'playlists', 0);
|
||||
|
||||
backendSrv.get('/api/playlists').then(result => {
|
||||
this.playlists = result;
|
||||
|
@ -41,7 +41,7 @@ export class DataSourceEditCtrl {
|
||||
navModelSrv,
|
||||
) {
|
||||
|
||||
this.navModel = navModelSrv.getNav('cfg', 'datasources');
|
||||
this.navModel = navModelSrv.getNav('cfg', 'datasources', 0);
|
||||
this.datasources = [];
|
||||
this.tabIndex = 0;
|
||||
|
||||
@ -58,9 +58,7 @@ export class DataSourceEditCtrl {
|
||||
this.isNew = true;
|
||||
this.current = _.cloneDeep(defaults);
|
||||
|
||||
// add to nav & breadcrumbs
|
||||
this.navModel.node = {text: 'New data source', icon: 'icon-gf icon-gf-fw icon-gf-datasources'};
|
||||
this.navModel.breadcrumbs.push(this.navModel.node);
|
||||
this.navModel.breadcrumbs.push({text: 'New'});
|
||||
|
||||
// We are coming from getting started
|
||||
if (this.$location.search().gettingstarted) {
|
||||
@ -87,7 +85,7 @@ export class DataSourceEditCtrl {
|
||||
this.backendSrv.get('/api/datasources/' + id).then(ds => {
|
||||
this.isNew = false;
|
||||
this.current = ds;
|
||||
this.navModel.node = {text: ds.name, icon: 'icon-gf icon-gf-fw icon-gf-datasources'};
|
||||
this.navModel.node = {text: ds.name, icon: 'icon-gf icon-gf-fw icon-gf-datasources', id: 'ds-new'};
|
||||
this.navModel.breadcrumbs.push(this.navModel.node);
|
||||
|
||||
if (datasourceCreated) {
|
||||
|
@ -13,7 +13,7 @@ export class DataSourcesCtrl {
|
||||
private datasourceSrv,
|
||||
private navModelSrv) {
|
||||
|
||||
this.navModel = this.navModelSrv.getNav('cfg', 'datasources');
|
||||
this.navModel = this.navModelSrv.getNav('cfg', 'datasources', 0);
|
||||
|
||||
backendSrv.get('/api/datasources').then(result => {
|
||||
this.datasources = result;
|
||||
|
@ -13,12 +13,6 @@
|
||||
{{dash.title}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>
|
||||
Revision: {{dash.revision}}
|
||||
<span ng-if="dash.imported" class="small">(Imported: {{dash.importedRevision}})</span>
|
||||
<span>
|
||||
</td>
|
||||
<td style="text-align: right">
|
||||
<button class="btn btn-secondary btn-small" ng-click="ctrl.import(dash, false)" ng-show="!dash.imported">
|
||||
Import
|
||||
|
@ -1,89 +1,80 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div ng-if="ctrl.current.readOnly" class="grafana-info-box span8">Disclaimer. This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.</div>
|
||||
<div class="page-container page-body">
|
||||
|
||||
<div class="page-header-tabs" ng-show="ctrl.hasDashboards">
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.tabIndex = 0" ng-class="{active: ctrl.tabIndex === 0}">
|
||||
Config
|
||||
</a>
|
||||
</li>
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.tabIndex = 1" ng-class="{active: ctrl.tabIndex === 1}">
|
||||
Dashboards
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="ctrl.current.readOnly" class="page-action-bar">
|
||||
<div class="grafana-info-box span8">
|
||||
Disclaimer. This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.tabIndex === 0" class="tab-content">
|
||||
<h3 class="page-sub-heading" ng-hide="ctrl.isNew">Edit Data Source</h3>
|
||||
<h3 class="page-sub-heading" ng-show="ctrl.isNew">New Data Source</h3>
|
||||
|
||||
<form name="ctrl.editForm" ng-if="ctrl.current">
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-7">Name</span>
|
||||
<input class="gf-form-input max-width-23" type="text" ng-model="ctrl.current.name" placeholder="name" required>
|
||||
<info-popover offset="0px -135px" mode="right-absolute">
|
||||
The name is used when you select the data source in panels.
|
||||
The <em>Default</em> data source is preselected in new
|
||||
panels.
|
||||
</info-popover>
|
||||
</div>
|
||||
<gf-form-switch class="gf-form" label="Default" checked="ctrl.current.isDefault" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
<form name="ctrl.editForm" ng-if="ctrl.current">
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-7">Name</span>
|
||||
<input class="gf-form-input max-width-23" type="text" ng-model="ctrl.current.name" placeholder="name" required>
|
||||
<info-popover offset="0px -135px" mode="right-absolute">
|
||||
The name is used when you select the data source in panels.
|
||||
The <em>Default</em> data source is preselected in new
|
||||
panels.
|
||||
</info-popover>
|
||||
</div>
|
||||
<gf-form-switch class="gf-form" label="Default" checked="ctrl.current.isDefault" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-7">Type</span>
|
||||
<div class="gf-form-select-wrapper max-width-23">
|
||||
<select class="gf-form-input" ng-model="ctrl.current.type" ng-options="v.id as v.name for v in ctrl.types" ng-change="ctrl.userChangedType()"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-7">Type</span>
|
||||
<div class="gf-form-select-wrapper max-width-23">
|
||||
<select class="gf-form-input" ng-model="ctrl.current.type" ng-options="v.id as v.name for v in ctrl.types" ng-change="ctrl.userChangedType()"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info gf-form-group" ng-if="ctrl.datasourceMeta.state === 'alpha'">
|
||||
This plugin is marked as being in alpha state, which means it is in early development phase and
|
||||
updates will include breaking changes.
|
||||
</div>
|
||||
<div class="alert alert-info gf-form-group" ng-if="ctrl.datasourceMeta.state === 'alpha'">
|
||||
This plugin is marked as being in alpha state, which means it is in early development phase and
|
||||
updates will include breaking changes.
|
||||
</div>
|
||||
|
||||
<rebuild-on-change property="ctrl.datasourceMeta.id">
|
||||
<plugin-component type="datasource-config-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
<rebuild-on-change property="ctrl.datasourceMeta.id">
|
||||
<plugin-component type="datasource-config-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
|
||||
<div ng-if="ctrl.testing" class="gf-form-group section">
|
||||
<h5 ng-show="!ctrl.testing.done">Testing.... <i class="fa fa-spiner fa-spin"></i></h5>
|
||||
<div class="alert-{{ctrl.testing.status}} alert" ng-show="ctrl.testing.done">
|
||||
<div class="alert-icon">
|
||||
<i class="fa fa-exclamation-triangle" ng-show="ctrl.testing.status === 'error'"></i>
|
||||
<i class="fa fa-check" ng-show="ctrl.testing.status !== 'error'"></i>
|
||||
</div>
|
||||
<div class="alert-body">
|
||||
<div class="alert-title">{{ctrl.testing.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="ctrl.hasDashboards">
|
||||
<h3 class="section-heading">Bundled Plugin Dashboards</h3>
|
||||
<div class="section">
|
||||
<dashboard-import-list plugin="ctrl.datasourceMeta" datasource="ctrl.current"></dashboard-import-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<button type="submit" class="btn btn-success" ng-disabled="ctrl.current.readOnly" ng-click="ctrl.saveChanges()">Save</button>
|
||||
<button type="submit" class="btn btn-danger" ng-disabled="ctrl.current.readOnly" ng-show="!ctrl.isNew" ng-click="ctrl.delete()">
|
||||
Delete
|
||||
</button>
|
||||
<a class="btn btn-link" href="datasources">Cancel</a>
|
||||
</div>
|
||||
<div ng-if="ctrl.testing" class="gf-form-group section">
|
||||
<h5 ng-show="!ctrl.testing.done">Testing.... <i class="fa fa-spiner fa-spin"></i></h5>
|
||||
<div class="alert-{{ctrl.testing.status}} alert" ng-show="ctrl.testing.done">
|
||||
<div class="alert-icon">
|
||||
<i class="fa fa-exclamation-triangle" ng-show="ctrl.testing.status === 'error'"></i>
|
||||
<i class="fa fa-check" ng-show="ctrl.testing.status !== 'error'"></i>
|
||||
</div>
|
||||
<div class="alert-body">
|
||||
<div class="alert-title">{{ctrl.testing.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div class="gf-form-button-row">
|
||||
<button type="submit" class="btn btn-success" ng-disabled="ctrl.current.readOnly" ng-click="ctrl.saveChanges()">Save</button>
|
||||
<button type="submit" class="btn btn-danger" ng-disabled="ctrl.current.readOnly" ng-show="!ctrl.isNew" ng-click="ctrl.delete()">
|
||||
Delete
|
||||
</button>
|
||||
<a class="btn btn-link" href="datasources">Cancel</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div ng-if="ctrl.tabIndex === 1" class="tab-content">
|
||||
<dashboard-import-list plugin="ctrl.datasourceMeta" datasource="ctrl.current"></dashboard-import-list>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
<div class="gf-form-group">
|
||||
<h3 class="page-heading">HTTP settings</h3>
|
||||
<h3 class="section-heading">HTTP</h3>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
@ -38,39 +38,38 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="page-heading">HTTP Auth</h3>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-switch class="gf-form" label="Basic Auth" checked="current.basicAuth" label-class="width-8" switch-class="max-width-6"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label="With Credentials" tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests." checked="current.withCredentials" label-class="width-11" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="TLS Client Auth" label-class="width-8" checked="current.jsonData.tlsAuth" switch-class="max-width-6"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="With CA Cert" tooltip="Needed for verifing self-signed TLS Certs" checked="current.jsonData.tlsAuthWithCACert" label-class="width-11" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="section-heading">Auth</h3>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="Skip TLS Verification (Insecure)" label-class="width-16" checked="current.jsonData.tlsSkipVerify" switch-class="max-width-6"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label="Basic Auth" checked="current.basicAuth" label-class="width-8" switch-class="max-width-6"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label="With Credentials" tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests." checked="current.withCredentials" label-class="width-11" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="TLS Client Auth" label-class="width-8" checked="current.jsonData.tlsAuth" switch-class="max-width-6"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="With CA Cert" tooltip="Needed for verifing self-signed TLS Certs" checked="current.jsonData.tlsAuthWithCACert" label-class="width-11" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-switch class="gf-form" ng-if="current.access=='proxy'" label="Skip TLS Verification (Insecure)" label-class="width-16" checked="current.jsonData.tlsSkipVerify" switch-class="max-width-6"></gf-form-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="current.basicAuth">
|
||||
<h6>Basic Auth Details</h6>
|
||||
<div class="gf-form" ng-if="current.basicAuth">
|
||||
<span class="gf-form-label width-7">
|
||||
User
|
||||
</span>
|
||||
<input class="gf-form-input max-width-21" type="text" ng-model='current.basicAuthUser' placeholder="user" required></input>
|
||||
</div>
|
||||
<div class="gf-form" ng-if="current.basicAuth">
|
||||
<span class="gf-form-label width-7">
|
||||
User
|
||||
</span>
|
||||
<input class="gf-form-input max-width-21" type="text" ng-model='current.basicAuthUser' placeholder="user" required></input>
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-7">
|
||||
Password
|
||||
</span>
|
||||
<input class="gf-form-input max-width-21" type="password" ng-model='current.basicAuthPassword' placeholder="password" required></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-7">
|
||||
Password
|
||||
</span>
|
||||
<input class="gf-form-input max-width-21" type="password" ng-model='current.basicAuthPassword' placeholder="password" required></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">
|
||||
|
@ -1,16 +1,16 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<a class="page-header__cta btn btn-success" href="datasources/new">
|
||||
Add data source
|
||||
</a>
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<a class="page-header__cta btn btn-success" href="datasources/new">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add data source
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<section class="card-section" layout-mode>
|
||||
<layout-selector></layout-selector>
|
||||
|
||||
<ol class="card-list">
|
||||
<li class="card-item-wrapper" ng-repeat="ds in ctrl.datasources">
|
||||
<a class="card-item" href="datasources/edit/{{ds.id}}/">
|
||||
@ -43,4 +43,4 @@
|
||||
<div ng-if="ctrl.datasources.length === 0">
|
||||
<em>No data sources defined</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,62 +1,42 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
|
||||
<div class="page-container" ng-init="ctrl.init()">
|
||||
<div class="page-header">
|
||||
<div class="plugin-header">
|
||||
<span class="plugin-header-logo">
|
||||
<img ng-src="{{ctrl.model.info.logos.large}}">
|
||||
</span>
|
||||
|
||||
<div class="plugin-header-info-block">
|
||||
<h1 class="plugin-header-name">{{ctrl.model.name}}</h1>
|
||||
<div class="plugin-header-author">By {{ctrl.model.info.author.name}}</div>
|
||||
<div class="plugin-header-stamps">
|
||||
<span class="plugin-header-stamps-type">
|
||||
<i class="{{ctrl.pluginIcon}}"></i> {{ctrl.model.type}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item" ng-repeat="tab in ctrl.tabs">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.tabIndex = $index" ng-class="{active: ctrl.tabIndex === $index}">
|
||||
{{::tab}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body" ng-init="ctrl.init()">
|
||||
<div class="page-action-bar">
|
||||
<button class="btn" ng-repeat="tab in ctrl.tabs" ng-class="{'btn-secondary': ctrl.tabIndex === $index, 'btn-inverse': ctrl.tabIndex !== $index}" ng-click="ctrl.tabIndex = $index">
|
||||
{{tab}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="page-body">
|
||||
<div class="tab-content page-content-with-sidebar" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Readme'">
|
||||
<div class="sidebar-container">
|
||||
|
||||
<div class="tab-content sidebar-content" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Readme'">
|
||||
<div ng-bind-html="ctrl.readmeHtml" class="markdown-html">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-content page-content-with-sidebar" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Config'">
|
||||
<div class="tab-content sidebar-content" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Config'">
|
||||
<div ng-if="ctrl.model.id">
|
||||
<plugin-component type="app-config-ctrl"></plugin-component>
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<button type="submit" class="btn btn-success" ng-click="ctrl.enable()" ng-show="!ctrl.model.enabled">Enable</button>
|
||||
<button type="submit" class="btn btn-success" ng-click="ctrl.update()" ng-show="ctrl.model.enabled">Update</button>
|
||||
<button type="submit" class="btn btn-danger" ng-click="ctrl.disable()" ng-show="ctrl.model.enabled">Disable</button>
|
||||
</div>
|
||||
<div class="gf-form-button-row">
|
||||
<button type="submit" class="btn btn-success" ng-click="ctrl.enable()" ng-show="!ctrl.model.enabled">Enable</button>
|
||||
<button type="submit" class="btn btn-success" ng-click="ctrl.update()" ng-show="ctrl.model.enabled">Update</button>
|
||||
<button type="submit" class="btn btn-danger" ng-click="ctrl.disable()" ng-show="ctrl.model.enabled">Disable</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-content page-content-with-sidebar" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Dashboards'">
|
||||
<dashboard-import-list plugin="ctrl.model"></dashboard-import-list>
|
||||
<div class="tab-content sidebar.content" ng-if="ctrl.tabs[ctrl.tabIndex] === 'Dashboards'">
|
||||
<dashboard-import-list plugin="ctrl.model"></dashboard-import-list>
|
||||
</div>
|
||||
|
||||
<aside class="page-sidebar">
|
||||
<section class="page-sidebar-section">
|
||||
<h4>Version</h4>
|
||||
<span>{{ctrl.model.info.version}}</span>
|
||||
<div ng-show="ctrl.model.hasUpdate">
|
||||
<div ng-show="ctrl.model.hasUpdate">
|
||||
<a ng-click="ctrl.updateAvailable()" bs-tooltip="ctrl.model.latestVersion">Update Available!</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="page-sidebar-section" ng-show="ctrl.model.type === 'app'">
|
||||
<h5>Includes</h4>
|
||||
|
@ -1,63 +1,81 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
<i class="icon-gf icon-gf-apps"></i>
|
||||
Plugins <span class="muted small">(currently installed)</span>
|
||||
</h1>
|
||||
<!-- <div class="page-header-canvas"> -->
|
||||
<!-- <div class="page-container"> -->
|
||||
<!-- <navbar model="ctrl.navModel"></navbar> -->
|
||||
<!-- -->
|
||||
<!-- <div class="page-header"> -->
|
||||
<!-- <page-h1 model="ctrl.navModel"></page-h1> -->
|
||||
<!-- -->
|
||||
<!-- <div class="page-header-tabs"> -->
|
||||
<!-- <ul class="gf-tabs"> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" href="plugins?type=panel" ng-class="{active: ctrl.tabIndex === 0}"> -->
|
||||
<!-- <i class="icon-gf icon-gf-panel"></i> -->
|
||||
<!-- Panels -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" href="plugins?type=datasource" ng-class="{active: ctrl.tabIndex === 1}"> -->
|
||||
<!-- <i class="gicon gicon-datasources"></i> -->
|
||||
<!-- Data sources -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- <li class="gf-tabs-item"> -->
|
||||
<!-- <a class="gf-tabs-link" href="plugins?type=app" ng-class="{active: ctrl.tabIndex === 2}"> -->
|
||||
<!-- <i class="icon-gf icon-gf-apps"></i> -->
|
||||
<!-- Apps -->
|
||||
<!-- </a> -->
|
||||
<!-- </li> -->
|
||||
<!-- </ul> -->
|
||||
<!-- -->
|
||||
<!-- <a class="get-more-plugins-link pull-right" href="https://grafana.com/plugins?utm_source=grafana_plugin_list" target="_blank"> -->
|
||||
<!-- Find more <img src="public/img/icn-plugins-tiny.svg" />plugins on Grafana.com -->
|
||||
<!-- </a> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<div class="page-header-tabs">
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" href="plugins?type=panel" ng-class="{active: ctrl.tabIndex === 0}">
|
||||
Panels
|
||||
</a>
|
||||
</li>
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" href="plugins?type=datasource" ng-class="{active: ctrl.tabIndex === 1}">
|
||||
Data sources
|
||||
</a>
|
||||
</li>
|
||||
<li class="gf-tabs-item">
|
||||
<a class="gf-tabs-link" href="plugins?type=app" ng-class="{active: ctrl.tabIndex === 2}">
|
||||
Apps
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="page-container page-body">
|
||||
<div class="page-action-bar">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">Search</label>
|
||||
<input type="text" class="gf-form-input width-20" ng-model="ctrl.searchQuery" ng-change="ctrl.onQueryUpdated()" />
|
||||
</div>
|
||||
|
||||
<a class="get-more-plugins-link" href="https://grafana.com/plugins?utm_source=grafana_plugin_list" target="_blank">
|
||||
Find more <img src="public/img/icn-plugins-tiny.svg" />plugins on Grafana.com
|
||||
</a>
|
||||
</div>
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<a class="btn btn-success" href="https://grafana.com/plugins?utm_source=grafana_plugin_list" target="_blank">
|
||||
Find more plugins on Grafana.com
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<section class="card-section" layout-mode>
|
||||
<layout-selector></layout-selector>
|
||||
<section class="card-section" layout-mode>
|
||||
<layout-selector></layout-selector>
|
||||
|
||||
<ol class="card-list" >
|
||||
<li class="card-item-wrapper" ng-repeat="plugin in ctrl.plugins">
|
||||
<a class="card-item" href="plugins/{{plugin.id}}/edit">
|
||||
<div class="card-item-header">
|
||||
<div class="card-item-type">
|
||||
<i class="icon-gf icon-gf-{{plugin.type}}"></i>
|
||||
{{plugin.type}}
|
||||
</div>
|
||||
<div class="card-item-notice" ng-show="plugin.hasUpdate">
|
||||
<span bs-tooltip="plugin.latestVersion">Update available!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item-body">
|
||||
<figure class="card-item-figure">
|
||||
<img ng-src="{{plugin.info.logos.small}}">
|
||||
</figure>
|
||||
<div class="card-item-details">
|
||||
<div class="card-item-name">{{plugin.name}}</div>
|
||||
<div class="card-item-sub-name">By {{plugin.info.author.name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<ol class="card-list" >
|
||||
<li class="card-item-wrapper" ng-repeat="plugin in ctrl.plugins">
|
||||
<a class="card-item" href="plugins/{{plugin.id}}/edit">
|
||||
<div class="card-item-header">
|
||||
<div class="card-item-type">
|
||||
<i class="icon-gf icon-gf-{{plugin.type}}"></i>
|
||||
{{plugin.type}}
|
||||
</div>
|
||||
<div class="card-item-notice" ng-show="plugin.hasUpdate">
|
||||
<span bs-tooltip="plugin.latestVersion">Update available!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item-body">
|
||||
<figure class="card-item-figure">
|
||||
<img ng-src="{{plugin.info.logos.small}}">
|
||||
</figure>
|
||||
<div class="card-item-details">
|
||||
<div class="card-item-name">{{plugin.name}}</div>
|
||||
<div class="card-item-sub-name">By {{plugin.info.author.name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -27,7 +27,7 @@ export class PluginEditCtrl {
|
||||
$routeParams,
|
||||
navModelSrv,
|
||||
) {
|
||||
this.navModel = navModelSrv.getNav('cfg', 'plugins');
|
||||
this.navModel = navModelSrv.getNav('cfg', 'plugins', 0);
|
||||
this.model = {};
|
||||
this.pluginId = $routeParams.pluginId;
|
||||
this.tabIndex = 0;
|
||||
|
@ -1,34 +1,28 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
export class PluginListCtrl {
|
||||
plugins: any[];
|
||||
tabIndex: number;
|
||||
navModel: any;
|
||||
searchQuery: string;
|
||||
allPlugins: any[];
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv: any, $location, navModelSrv) {
|
||||
this.tabIndex = 0;
|
||||
this.navModel = navModelSrv.getNav('cfg', 'plugins');
|
||||
this.navModel = navModelSrv.getNav('cfg', 'plugins', 0);
|
||||
|
||||
var pluginType = $location.search().type || 'panel';
|
||||
switch (pluginType) {
|
||||
case "datasource": {
|
||||
this.tabIndex = 1;
|
||||
break;
|
||||
}
|
||||
case "app": {
|
||||
this.tabIndex = 2;
|
||||
break;
|
||||
}
|
||||
case "panel":
|
||||
default:
|
||||
this.tabIndex = 0;
|
||||
}
|
||||
|
||||
this.backendSrv.get('api/plugins', {embedded: 0, type: pluginType}).then(plugins => {
|
||||
this.backendSrv.get('api/plugins', {embedded: 0}).then(plugins => {
|
||||
this.plugins = plugins;
|
||||
this.allPlugins = plugins;
|
||||
});
|
||||
}
|
||||
|
||||
onQueryUpdated() {
|
||||
let regex = new RegExp(this.searchQuery, 'ig');
|
||||
this.plugins = _.filter(this.allPlugins, item => {
|
||||
return regex.test(item.name) || regex.test(item.type);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
<navbar model="ctrl.navModel"></navbar>
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<page-h1 model="ctrl.navModel"></page-h1>
|
||||
</div>
|
||||
|
||||
<table class="filter-table" style="margin-top: 20px">
|
||||
<div class="page-container page-body">
|
||||
<table class="filter-table">
|
||||
<thead>
|
||||
<th><strong>Name</strong></th>
|
||||
<th><strong>Snapshot url</strong></th>
|
||||
|
@ -9,7 +9,7 @@ export class SnapshotsCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $rootScope, private backendSrv, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'snapshots');
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'snapshots', 0);
|
||||
this.backendSrv.get('/api/dashboard/snapshots').then(result => {
|
||||
this.snapshots = result;
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
suggest-url="http://localhost:8080">
|
||||
</datasource-http-settings>
|
||||
|
||||
<h3 class="page-heading">Graphite details</h3>
|
||||
<h3 class="section-heading">Graphite details</h3>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
|
@ -85,6 +85,7 @@
|
||||
@import "components/code_editor";
|
||||
@import "components/dashboard_grid";
|
||||
@import "components/dashboard_list";
|
||||
@import "components/page_header";
|
||||
|
||||
|
||||
// PAGES
|
||||
|
@ -29,8 +29,9 @@
|
||||
.dashnav-action-icons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
padding: ($spacer * 1) ($spacer * 2);
|
||||
padding: 0 $spacer * 2;
|
||||
}
|
||||
|
||||
.dash-row-menu-container {
|
||||
|
@ -52,6 +52,7 @@ $critical: #ed2e18;
|
||||
// -------------------------
|
||||
$body-bg: rgb(23,24,25);
|
||||
$page-bg: rgb(22, 23, 25);
|
||||
|
||||
$body-color: $gray-4;
|
||||
$text-color: $gray-4;
|
||||
$text-color-strong: $white;
|
||||
|
@ -227,7 +227,5 @@ $dashboard-padding: $panel-margin * 2;
|
||||
$panel-padding: 0px 10px 5px 10px;
|
||||
|
||||
// tabs
|
||||
$tabs-padding-top: 0.6rem;
|
||||
$tabs-padding-bottom: 0.4rem;
|
||||
$tabs-top-margin: 0.5rem;
|
||||
$tabs-padding: 10px 15px 10px;
|
||||
|
||||
|
@ -43,5 +43,13 @@
|
||||
background-image: url('../img/icons_#{$theme-name}_theme/icon_add_panel.svg');
|
||||
}
|
||||
|
||||
.gicon-alert-notification-channel {
|
||||
background-image: url('../img/icons_#{$theme-name}_theme/icon_notification_channels.svg');
|
||||
}
|
||||
|
||||
.gicon-user-group {
|
||||
background-image: url('../img/icons_#{$theme-name}_theme/icon_user_group.svg');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
.footer {
|
||||
color: $footer-link-color;
|
||||
padding: 5rem 0 1rem 0;
|
||||
font-size: $font-size-xs;
|
||||
font-size: $font-size-sm;
|
||||
width: 98%; /* was causing horiz scrollbars - need to examine */
|
||||
|
||||
a {
|
||||
|
159
public/sass/components/_page_header.scss
Normal file
159
public/sass/components/_page_header.scss
Normal file
@ -0,0 +1,159 @@
|
||||
|
||||
.page-header-canvas {
|
||||
background: linear-gradient(90deg, #292a2d, black);
|
||||
box-shadow: inset 0px -4px 14px #2d2d2d;
|
||||
border-bottom: 1px solid $dark-4;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
padding: 2.5rem 0 0 0;
|
||||
|
||||
.btn {
|
||||
float: right;
|
||||
margin-left: 1rem;
|
||||
|
||||
// better align icons
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-header__inner {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.page-header__title {
|
||||
font-size: $font-size-h2;
|
||||
margin-bottom: 1px;
|
||||
padding-top: $spacer;
|
||||
}
|
||||
|
||||
.page-header__img {
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.page-header__icon {
|
||||
font-size: 50px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
|
||||
&.fa {
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
&.gicon {
|
||||
top: 9px;
|
||||
}
|
||||
|
||||
&.icon-gf {
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header__logo {
|
||||
margin: 0 $spacer;
|
||||
}
|
||||
|
||||
.page-header__sub-title {
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
.page-header-stamps-type {
|
||||
color: $link-color-disabled;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-breadcrumbs {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
line-height: 0.5;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
display: inline-block;
|
||||
box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.35);
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
counter-reset: flag;
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
@include gradientBar($btn-inverse-bg, $btn-inverse-bg-hl, $btn-inverse-text-color);
|
||||
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
padding: 0 7px 0 37px;
|
||||
position: relative;
|
||||
box-shadow: $card-shadow;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 10px;
|
||||
border-radius: 5px 0 0 5px; /*to match with the parent's radius*/
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&:first-child::before {
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 5px 5px 0; /*this was to prevent glitches on hover*/
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
background: #333;
|
||||
background: linear-gradient(#333, #000);
|
||||
}
|
||||
|
||||
&.active::after,
|
||||
&:hover::after {
|
||||
background: #333;
|
||||
background: linear-gradient(135deg, #333, #000);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -14px; // half of square's length
|
||||
|
||||
// same dimension as the line-height of .breadcrumb-item
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
transform: scale(0.707) rotate(45deg);
|
||||
// we need to prevent the arrows from getting buried under the next link
|
||||
z-index: 1;
|
||||
|
||||
// background same as links but the gradient will be rotated to compensate with the transform applied
|
||||
background: linear-gradient(135deg, $btn-inverse-bg, $btn-inverse-bg-hl);
|
||||
|
||||
// stylish arrow design using box shadow
|
||||
box-shadow: 2px -2px 0 2px rgb(35, 31, 31), 3px -3px 0 2px rgba(255, 255, 255, 0.1);
|
||||
|
||||
// 5px - for rounded arrows and
|
||||
// 50px - to prevent hover glitches on the border created using shadows*/
|
||||
border-radius: 0 5px 0 50px;
|
||||
}
|
||||
|
||||
// we dont need an arrow after the last link
|
||||
&:last-child::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
margin: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: ($tabs-padding-top + $tabs-top-margin) $spacer $tabs-padding-bottom;
|
||||
padding: $tabs-padding;
|
||||
color: $text-color;
|
||||
i {
|
||||
font-size: 120%;
|
||||
|
@ -1,41 +1,8 @@
|
||||
.nav-tabs-alt {
|
||||
& > li > a {
|
||||
color: darken($link-color, 20%);
|
||||
}
|
||||
|
||||
li > a:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
li.active > a,
|
||||
li.active > a:focus,
|
||||
li.active > a:hover {
|
||||
@include border-radius(3px);
|
||||
border: 1px solid $divider-border-color;
|
||||
background-color: transparent;
|
||||
border-bottom: 1px solid $page-bg;
|
||||
color: $link-color;
|
||||
}
|
||||
|
||||
li.disabled > a {
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.open .dropdown-toggle {
|
||||
background-color: #060606;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding: 10px;
|
||||
background-color: $panel-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.gf-tabs {
|
||||
@include clearfix();
|
||||
float: left;
|
||||
margin: $tabs-top-margin 0 0 0;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.gf-tabs-item {
|
||||
@ -44,13 +11,17 @@
|
||||
}
|
||||
|
||||
.gf-tabs-link {
|
||||
padding: $tabs-padding-top $spacer $tabs-padding-bottom $spacer;
|
||||
padding: $tabs-padding;
|
||||
margin-right: $spacer/2;
|
||||
border: 1px solid transparent;
|
||||
position: relative;
|
||||
display: block;
|
||||
border: solid transparent;
|
||||
border-width: 2px 1px 1px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
|
||||
@include border-radius(2px 2px 0 0);
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -60,20 +31,9 @@
|
||||
&.active,
|
||||
&.active:hover,
|
||||
&.active:focus {
|
||||
@include border-radius(3px);
|
||||
border-color: rgba(216, 131, 40, 0.77);
|
||||
border-bottom: 1px solid $page-bg;
|
||||
border-color: $orange $dark-4 transparent;
|
||||
background: $page-bg;
|
||||
color: $link-color;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-tabs-wrapper {
|
||||
@include brand-bottom-border();
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.form-tabs-content {
|
||||
padding: $spacer*2 $spacer;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
.page-container {
|
||||
@extend .container;
|
||||
padding: $spacer $spacer $spacer $spacer*3;
|
||||
padding: 0 $spacer * 2;
|
||||
}
|
||||
|
||||
.scroll-canvas {
|
||||
@ -31,6 +31,35 @@
|
||||
}
|
||||
|
||||
.page-body {
|
||||
padding-top: $spacer*2;
|
||||
}
|
||||
|
||||
.page-heading {
|
||||
font-size: 1.25rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: $spacer * 0.7;
|
||||
}
|
||||
|
||||
.page-action-bar {
|
||||
margin-bottom: $spacer * 2;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
> a, > button {
|
||||
margin-left: $spacer;
|
||||
}
|
||||
}
|
||||
|
||||
.page-action-bar__spacer {
|
||||
width: $spacer * 2;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
width: calc(100% - #{$page-sidebar-width + $page-sidebar-margin}); // sidebar width + margin
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
@include media-breakpoint-up(md) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -38,10 +67,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.page-content-with-sidebar {
|
||||
width: calc(100% - #{$page-sidebar-width + $page-sidebar-margin}); // sidebar width + margin
|
||||
}
|
||||
|
||||
.page-sidebar {
|
||||
@include media-breakpoint-up(md) {
|
||||
width: $page-sidebar-width;
|
||||
@ -49,60 +74,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.page-header {
|
||||
padding: 2rem 0 0 0;
|
||||
margin-bottom: 2rem;
|
||||
@include brand-bottom-border();
|
||||
@include clearfix();
|
||||
|
||||
h1 {
|
||||
font-size: $font-size-h2;
|
||||
flex-grow: 1;
|
||||
display: inline-block;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
margin-right: 0.5rem;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
}
|
||||
}
|
||||
|
||||
a, button {
|
||||
float: right;
|
||||
margin-left: $spacer;
|
||||
|
||||
// better align icons
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.page-heading {
|
||||
font-size: 1.25rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: $spacer * 0.7;
|
||||
}
|
||||
|
||||
.admin-page {
|
||||
max-width: 800px;
|
||||
margin-left: 10px;
|
||||
h2 {
|
||||
margin-left: 15px;
|
||||
margin-bottom: 0px;
|
||||
font-size: $font-size-lg;
|
||||
color: $text-color;
|
||||
i {
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
.page-sub-heading {
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
.page-sidebar {
|
||||
@ -120,89 +93,3 @@
|
||||
.page-sidebar-section {
|
||||
margin-bottom: $spacer*2;
|
||||
}
|
||||
|
||||
.page-breadcrumbs {
|
||||
display: flex;
|
||||
padding: 10px 25px;
|
||||
line-height: 0.5;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
display: inline-block;
|
||||
box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.35);
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
counter-reset: flag;
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
padding: 0 7px 0 37px;
|
||||
@include gradientBar($btn-inverse-bg, $btn-inverse-bg-hl, $btn-inverse-text-color);
|
||||
position: relative;
|
||||
box-shadow: $card-shadow;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 10px;
|
||||
border-radius: 5px 0 0 5px; /*to match with the parent's radius*/
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&:first-child:before {
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 5px 5px 0; /*this was to prevent glitches on hover*/
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
background: #333;
|
||||
background: linear-gradient(#333, #000);
|
||||
}
|
||||
|
||||
&.active:after,
|
||||
&:hover:after {
|
||||
background: #333;
|
||||
background: linear-gradient(135deg, #333, #000);
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -14px; // half of square's length
|
||||
|
||||
// same dimension as the line-height of .breadcrumb-item
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
transform: scale(0.707) rotate(45deg);
|
||||
// we need to prevent the arrows from getting buried under the next link
|
||||
z-index: 1;
|
||||
|
||||
// background same as links but the gradient will be rotated to compensate with the transform applied
|
||||
background: linear-gradient(135deg, $btn-inverse-bg, $btn-inverse-bg-hl);
|
||||
|
||||
// stylish arrow design using box shadow
|
||||
box-shadow: 2px -2px 0 2px rgb(35, 31, 31), 3px -3px 0 2px rgba(255, 255, 255, 0.1);
|
||||
|
||||
// 5px - for rounded arrows and
|
||||
// 50px - to prevent hover glitches on the border created using shadows*/
|
||||
border-radius: 0 5px 0 50px;
|
||||
}
|
||||
|
||||
// we dont need an arrow after the last link
|
||||
&:last-child:after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,41 +1,3 @@
|
||||
.plugin-header {
|
||||
@include clearfix();
|
||||
|
||||
padding: $spacer 0 $spacer/2 0;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.plugin-header-logo {
|
||||
float: left;
|
||||
width: 7rem;
|
||||
img {
|
||||
width: 7rem;
|
||||
}
|
||||
margin-right: $spacer;
|
||||
}
|
||||
|
||||
.plugin-header-info-block {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.plugin-header-author {
|
||||
}
|
||||
|
||||
.plugin-header-stamps-type {
|
||||
color: $link-color-disabled;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.plugin-info-list-item {
|
||||
img {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
white-space: nowrap;
|
||||
max-width: $page-sidebar-width;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.get-more-plugins-link {
|
||||
color: $gray-3;
|
||||
@ -55,3 +17,15 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.plugin-info-list-item {
|
||||
img {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
white-space: nowrap;
|
||||
max-width: $page-sidebar-width;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user