Prechádzať zdrojové kódy

Merge branch 'develop-new-page-header' into develop

Torkel Ödegaard 8 rokov pred
rodič
commit
e348ec8c3b
56 zmenil súbory, kde vykonal 834 pridanie a 724 odobranie
  1. 2 0
      pkg/api/dtos/index.go
  2. 57 55
      pkg/api/index.go
  3. 2 0
      public/app/core/angular_wrappers.ts
  4. 94 0
      public/app/core/components/PageHeader.tsx
  5. 7 9
      public/app/core/components/navbar/navbar.html
  6. 4 4
      public/app/core/components/navbar/navbar.ts
  7. 33 8
      public/app/core/nav_model_srv.ts
  8. 3 6
      public/app/features/admin/partials/configuration_home.html
  9. 1 1
      public/app/features/alerting/alert_list_ctrl.ts
  10. 3 2
      public/app/features/alerting/notification_edit_ctrl.ts
  11. 1 1
      public/app/features/alerting/notifications_list_ctrl.ts
  12. 16 22
      public/app/features/alerting/partials/alert_list.html
  13. 5 5
      public/app/features/alerting/partials/notification_edit.html
  14. 7 5
      public/app/features/alerting/partials/notifications_list.html
  15. 1 1
      public/app/features/dashboard/dashboard_list_ctrl.ts
  16. 8 12
      public/app/features/dashboard/partials/dashboardList.html
  17. 1 0
      public/app/features/org/all.ts
  18. 1 1
      public/app/features/org/org_api_keys_ctrl.ts
  19. 1 1
      public/app/features/org/org_details_ctrl.ts
  20. 2 3
      public/app/features/org/org_users_ctrl.ts
  21. 5 7
      public/app/features/org/partials/orgApiKeys.html
  22. 43 17
      public/app/features/org/partials/orgDetails.html
  23. 55 37
      public/app/features/org/partials/orgUsers.html
  24. 3 6
      public/app/features/org/partials/profile.html
  25. 12 11
      public/app/features/org/partials/user_groups.html
  26. 1 1
      public/app/features/org/prefs_control.ts
  27. 1 1
      public/app/features/org/profile_ctrl.ts
  28. 1 1
      public/app/features/org/user_groups_ctrl.ts
  29. 6 6
      public/app/features/playlist/partials/playlist.html
  30. 6 6
      public/app/features/playlist/partials/playlists.html
  31. 5 7
      public/app/features/playlist/playlist_edit_ctrl.ts
  32. 1 1
      public/app/features/playlist/playlists_ctrl.ts
  33. 3 5
      public/app/features/plugins/ds_edit_ctrl.ts
  34. 1 1
      public/app/features/plugins/ds_list_ctrl.ts
  35. 0 6
      public/app/features/plugins/import_list/import_list.html
  36. 68 77
      public/app/features/plugins/partials/ds_edit.html
  37. 24 25
      public/app/features/plugins/partials/ds_http_settings.html
  38. 9 9
      public/app/features/plugins/partials/ds_list.html
  39. 19 39
      public/app/features/plugins/partials/plugin_edit.html
  40. 74 56
      public/app/features/plugins/partials/plugin_list.html
  41. 1 1
      public/app/features/plugins/plugin_edit_ctrl.ts
  42. 13 19
      public/app/features/plugins/plugin_list_ctrl.ts
  43. 3 7
      public/app/features/snapshot/partials/snapshots.html
  44. 1 1
      public/app/features/snapshot/snapshot_ctrl.ts
  45. 1 1
      public/app/plugins/datasource/graphite/partials/config.html
  46. 1 0
      public/sass/_grafana.scss
  47. 2 1
      public/sass/_old_responsive.scss
  48. 1 0
      public/sass/_variables.dark.scss
  49. 1 3
      public/sass/_variables.scss
  50. 8 0
      public/sass/base/_icons.scss
  51. 1 1
      public/sass/components/_footer.scss
  52. 159 0
      public/sass/components/_page_header.scss
  53. 1 1
      public/sass/components/_tabbed_view.scss
  54. 11 51
      public/sass/components/_tabs.scss
  55. 32 145
      public/sass/layout/_page.scss
  56. 12 38
      public/sass/pages/_plugins.scss

+ 2 - 0
pkg/api/dtos/index.go

@@ -24,11 +24,13 @@ type NavLink struct {
 	Id           string     `json:"id,omitempty"`
 	Id           string     `json:"id,omitempty"`
 	Text         string     `json:"text,omitempty"`
 	Text         string     `json:"text,omitempty"`
 	Description  string     `json:"description,omitempty"`
 	Description  string     `json:"description,omitempty"`
+	SubTitle     string     `json:"subTitle,omitempty"`
 	Icon         string     `json:"icon,omitempty"`
 	Icon         string     `json:"icon,omitempty"`
 	Img          string     `json:"img,omitempty"`
 	Img          string     `json:"img,omitempty"`
 	Url          string     `json:"url,omitempty"`
 	Url          string     `json:"url,omitempty"`
 	Target       string     `json:"target,omitempty"`
 	Target       string     `json:"target,omitempty"`
 	Divider      bool       `json:"divider,omitempty"`
 	Divider      bool       `json:"divider,omitempty"`
 	HideFromMenu bool       `json:"hideFromMenu,omitempty"`
 	HideFromMenu bool       `json:"hideFromMenu,omitempty"`
+	HideFromTabs bool       `json:"hideFromTabs,omitempty"`
 	Children     []*NavLink `json:"children,omitempty"`
 	Children     []*NavLink `json:"children,omitempty"`
 }
 }

+ 57 - 55
pkg/api/index.go

@@ -101,38 +101,41 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
 	}
 	}
 
 
 	dashboardChildNavs := []*dtos.NavLink{
 	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: "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: "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{
 	data.NavTree = append(data.NavTree, &dtos.NavLink{
 		Text:     "Dashboards",
 		Text:     "Dashboards",
 		Id:       "dashboards",
 		Id:       "dashboards",
+		SubTitle: "Manage dashboards & folders",
 		Icon:     "gicon gicon-dashboard",
 		Icon:     "gicon gicon-dashboard",
-		Url:      setting.AppSubUrl + "/",
+		Url:      setting.AppSubUrl + "/dashboards",
 		Children: dashboardChildNavs,
 		Children: dashboardChildNavs,
 	})
 	})
 
 
 	if c.IsSignedIn {
 	if c.IsSignedIn {
 		profileNode := &dtos.NavLink{
 		profileNode := &dtos.NavLink{
-			Text:         c.SignedInUser.Login,
+			Text:         c.SignedInUser.Name,
+			SubTitle:     c.SignedInUser.Login,
 			Id:           "profile",
 			Id:           "profile",
 			Img:          data.User.GravatarUrl,
 			Img:          data.User.GravatarUrl,
 			Url:          setting.AppSubUrl + "/profile",
 			Url:          setting.AppSubUrl + "/profile",
 			HideFromMenu: true,
 			HideFromMenu: true,
 			Children: []*dtos.NavLink{
 			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},
 				{Text: "Change Password", Id: "change-password", Url: setting.AppSubUrl + "/profile/password", Icon: "fa fa-fw fa-lock", HideFromMenu: true},
 			},
 			},
 		}
 		}
 
 
 		if !setting.DisableSignoutMenu {
 		if !setting.DisableSignoutMenu {
 			// add sign out first
 			// 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)
 		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) {
 	if setting.AlertingEnabled && (c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR) {
 		alertChildNavs := []*dtos.NavLink{
 		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{
 		data.NavTree = append(data.NavTree, &dtos.NavLink{
 			Text:     "Alerting",
 			Text:     "Alerting",
+			SubTitle: "Alert rules & notifications",
 			Id:       "alerting",
 			Id:       "alerting",
 			Icon:     "gicon gicon-alert",
 			Icon:     "gicon gicon-alert",
 			Url:      setting.AppSubUrl + "/alerting/list",
 			Url:      setting.AppSubUrl + "/alerting/list",
@@ -202,10 +206,11 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
 
 
 	if c.OrgRole == m.ROLE_ADMIN {
 	if c.OrgRole == m.ROLE_ADMIN {
 		cfgNode := &dtos.NavLink{
 		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{
 			Children: []*dtos.NavLink{
 				{
 				{
 					Text:        "Data Sources",
 					Text:        "Data Sources",
@@ -213,29 +218,6 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
 					Description: "Add and configure data sources",
 					Description: "Add and configure data sources",
 					Id:          "datasources",
 					Id:          "datasources",
 					Url:         setting.AppSubUrl + "/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",
 					Text:        "Members",
@@ -245,12 +227,32 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
 					Url:         setting.AppSubUrl + "/org/users",
 					Url:         setting.AppSubUrl + "/org/users",
 				},
 				},
 				{
 				{
-					Text:        "Groups",
-					Id:          "users",
+					Text:        "Teams",
+					Id:          "teams",
 					Description: "Manage org groups",
 					Description: "Manage org groups",
-					Icon:        "fa fa-fw fa-users",
+					Icon:        "gicon gicon-user-group",
 					Url:         setting.AppSubUrl + "/org/user-groups",
 					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",
 					Text:        "API Keys",
 					Id:          "apikeys",
 					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)
 		data.NavTree = append(data.NavTree, cfgNode)
 	}
 	}

+ 2 - 0
public/app/core/angular_wrappers.ts

@@ -1,8 +1,10 @@
 import { react2AngularDirective } from 'app/core/utils/react2angular';
 import { react2AngularDirective } from 'app/core/utils/react2angular';
 import { PasswordStrength } from './components/PasswordStrength';
 import { PasswordStrength } from './components/PasswordStrength';
+import PageHeader from './components/PageHeader';
 
 
 export function registerAngularDirectives() {
 export function registerAngularDirectives() {
 
 
   react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
   react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
+  react2AngularDirective('pageHeader', PageHeader, ['model', "noTabs"]);
 
 
 }
 }

+ 94 - 0
public/app/core/components/PageHeader.tsx

@@ -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>
+    );
+  }
+}

+ 7 - 9
public/app/core/components/navbar/navbar.html

@@ -1,13 +1,11 @@
 <div class="page-nav">
 <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>
 </div>
 </div>
 
 

+ 4 - 4
public/app/core/components/navbar/navbar.ts

@@ -39,10 +39,10 @@ export function pageH1() {
   return {
   return {
     restrict: 'E',
     restrict: 'E',
     template: `
     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>
     </h1>
     `,
     `,
     scope: {
     scope: {

+ 33 - 8
public/app/core/nav_model_srv.ts

@@ -1,19 +1,27 @@
-///<reference path="../headers/common.d.ts" />
-
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
 import config from 'app/core/config';
 import config from 'app/core/config';
 import _ from 'lodash';
 import _ from 'lodash';
 
 
 export interface NavModelItem {
 export interface NavModelItem {
-  title: string;
+  text: string;
   url: string;
   url: string;
   icon?: 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 {
 export class NavModelSrv {
@@ -31,15 +39,32 @@ export class NavModelSrv {
 
 
   getNav(...args) {
   getNav(...args) {
     var children = this.navItems;
     var children = this.navItems;
-    var nav = {breadcrumbs: [], node: null};
+    var nav = new NavModel();
 
 
     for (let id of args) {
     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});
       let node = _.find(children, {id: id});
       nav.breadcrumbs.push(node);
       nav.breadcrumbs.push(node);
       nav.node = node;
       nav.node = node;
+      nav.main = node;
       children = node.children;
       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;
     return nav;
   }
   }
 
 

+ 3 - 6
public/app/features/admin/partials/configuration_home.html

@@ -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">
 	<section class="card-section card-list-layout-grid">
 		<ol class="card-list">
 		<ol class="card-list">
 			<li class="card-item-wrapper" ng-repeat="navItem in ctrl.navModel.node.children">
 			<li class="card-item-wrapper" ng-repeat="navItem in ctrl.navModel.node.children">
@@ -29,4 +26,4 @@
 			</li>
 			</li>
 		</ol>
 		</ol>
 	</section>
 	</section>
-</div>
+</div>

+ 1 - 1
public/app/features/alerting/alert_list_ctrl.ts

@@ -23,7 +23,7 @@ export class AlertListCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv, private $location, navModelSrv) {
   constructor(private backendSrv, private $location, navModelSrv) {
-    this.navModel = navModelSrv.getNav('alerting');
+    this.navModel = navModelSrv.getNav('alerting', 'alert-list', 0);
 
 
     var params = $location.search();
     var params = $location.search();
     this.filters.state = params.state || null;
     this.filters.state = params.state || null;

+ 3 - 2
public/app/features/alerting/notification_edit_ctrl.ts

@@ -9,7 +9,7 @@ export class AlertNotificationEditCtrl {
   testSeverity = "critical";
   testSeverity = "critical";
   notifiers: any;
   notifiers: any;
   notifierTemplateId: string;
   notifierTemplateId: string;
-
+  isNew: boolean;
   model: any;
   model: any;
   defaults: any = {
   defaults: any = {
     type: 'email',
     type: 'email',
@@ -23,7 +23,8 @@ export class AlertNotificationEditCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private $routeParams, private backendSrv, private $location, private $templateCache, navModelSrv) {
   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.backendSrv.get(`/api/alert-notifiers`).then(notifiers => {
       this.notifiers = notifiers;
       this.notifiers = notifiers;

+ 1 - 1
public/app/features/alerting/notifications_list_ctrl.ts

@@ -9,7 +9,7 @@ export class AlertNotificationsListCtrl {
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv, navModelSrv) {
   constructor(private backendSrv, navModelSrv) {
     this.loadNotifications();
     this.loadNotifications();
-    this.navModel = navModelSrv.getNav('alerting', 'channels');
+    this.navModel = navModelSrv.getNav('alerting', 'channels', 0);
   }
   }
 
 
   loadNotifications() {
   loadNotifications() {

+ 16 - 22
public/app/features/alerting/partials/alert_list.html

@@ -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>
     </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>
   </div>
 
 
   <section class="card-section card-list-layout-list">
   <section class="card-section card-list-layout-list">

+ 5 - 5
public/app/features/alerting/partials/notification_edit.html

@@ -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">
   <form name="ctrl.theForm" ng-if="ctrl.notifiers">
     <div class="gf-form-group">
     <div class="gf-form-group">

+ 7 - 5
public/app/features/alerting/partials/notifications_list.html

@@ -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
       New Channel
     </a>
     </a>
   </div>
   </div>

+ 1 - 1
public/app/features/dashboard/dashboard_list_ctrl.ts

@@ -17,7 +17,7 @@ export class DashboardListCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv, navModelSrv, private $q, private searchSrv: SearchSrv) {
   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.query = {query: '', mode: 'tree', tag: [], starred: false};
     this.selectedStarredFilter = this.starredFilterOptions[0];
     this.selectedStarredFilter = this.starredFilterOptions[0];
 
 

+ 8 - 12
public/app/features/dashboard/partials/dashboardList.html

@@ -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">
     <a class="btn btn-inverse" href="/dashboard/new">
       <i class="gicon gicon-dashboard-new"></i>
       <i class="gicon gicon-dashboard-new"></i>
       Dashboard
       Dashboard
@@ -12,14 +16,6 @@
       Folder
       Folder
     </a>
     </a>
   </div>
   </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">
   <div class="gf-form" ng-if="ctrl.query.tag.length">
     Filters:
     Filters:

+ 1 - 0
public/app/features/org/all.ts

@@ -5,6 +5,7 @@ import './select_org_ctrl';
 import './change_password_ctrl';
 import './change_password_ctrl';
 import './new_org_ctrl';
 import './new_org_ctrl';
 import './user_invite_ctrl';
 import './user_invite_ctrl';
+import './user_groups_ctrl';
 import './org_api_keys_ctrl';
 import './org_api_keys_ctrl';
 import './org_details_ctrl';
 import './org_details_ctrl';
 import './prefs_control';
 import './prefs_control';

+ 1 - 1
public/app/features/org/org_api_keys_ctrl.ts

@@ -4,7 +4,7 @@ export class OrgApiKeysCtrl {
 
 
   /** @ngInject **/
   /** @ngInject **/
   constructor ($scope, $http, backendSrv, navModelSrv) {
   constructor ($scope, $http, backendSrv, navModelSrv) {
-    $scope.navModel = navModelSrv.getNav('cfg', 'apikeys');
+    $scope.navModel = navModelSrv.getNav('cfg', 'apikeys', 0);
 
 
     $scope.roleTypes = ['Viewer', 'Editor', 'Admin'];
     $scope.roleTypes = ['Viewer', 'Editor', 'Admin'];
     $scope.token = { role: 'Viewer' };
     $scope.token = { role: 'Viewer' };

+ 1 - 1
public/app/features/org/org_details_ctrl.ts

@@ -6,7 +6,7 @@ export class OrgDetailsCtrl {
   constructor($scope, $http, backendSrv, contextSrv, navModelSrv) {
   constructor($scope, $http, backendSrv, contextSrv, navModelSrv) {
     $scope.init = function() {
     $scope.init = function() {
       $scope.getOrgInfo();
       $scope.getOrgInfo();
-      $scope.navModel = navModelSrv.getNav('cfg', 'org');
+      $scope.navModel = navModelSrv.getNav('cfg', 'org-settings', 0);
     };
     };
 
 
     $scope.getOrgInfo = function() {
     $scope.getOrgInfo = function() {

+ 2 - 3
public/app/features/org/org_users_ctrl.ts

@@ -23,7 +23,7 @@ export class OrgUsersCtrl {
       role: 'Viewer',
       role: 'Viewer',
     };
     };
 
 
-    this.navModel = navModelSrv.getNav('cfg', 'users');
+    this.navModel = navModelSrv.getNav('cfg', 'users', 0);
 
 
     this.get();
     this.get();
     this.editor = { index: 0 };
     this.editor = { index: 0 };
@@ -44,8 +44,7 @@ export class OrgUsersCtrl {
     if (this.externalUserMngLinkName) {
     if (this.externalUserMngLinkName) {
       return this.externalUserMngLinkName;
       return this.externalUserMngLinkName;
     }
     }
-
-    return "Add Members";
+    return "Add Member";
   }
   }
 
 
   get() {
   get() {

+ 5 - 7
public/app/features/org/partials/orgApiKeys.html

@@ -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">
 	<form name="addTokenForm" class="gf-form-group">
 		<div class="gf-form-inline">
 		<div class="gf-form-inline">
 			<div class="gf-form max-width-21">
 			<div class="gf-form max-width-21">
@@ -22,7 +20,7 @@
 		</div>
 		</div>
 	</form>
 	</form>
 
 
-	<h3 class="page-heading">Existing Keys</h3>
+	<h3 class="section-heading">Existing Keys</h3>
 	<table class="filter-table">
 	<table class="filter-table">
 		<thead>
 		<thead>
 			<tr>
 			<tr>

+ 43 - 17
public/app/features/org/partials/orgDetails.html

@@ -1,26 +1,52 @@
-<navbar model="navModel"></navbar>
+<!-- <div class="page&#45;header&#45;canvas"> -->
+<!--   <div class="page&#45;container" > -->
+<!--     <navbar model="navModel"></navbar> -->
+<!--  -->
+<!--     <div class="page&#45;header"> -->
+<!--       <page&#45;h1 model="navModel"></page&#45;h1> -->
+<!--  -->
+<!--       <ul class="gf&#45;tabs"> -->
+<!--         <li class="gf&#45;tabs&#45;item"> -->
+<!--           <a class="gf&#45;tabs&#45;link active" href="org"> -->
+<!--             <i class="fa fa&#45;fw fa&#45;sliders"></i> -->
+<!--             Preferences -->
+<!--           </a> -->
+<!--         </li> -->
+<!--         <li class="gf&#45;tabs&#45;item"> -->
+<!--           <a class="gf&#45;tabs&#45;link" href="org/users"> -->
+<!--             <i class="icon&#45;gf icon&#45;gf&#45;fw icon&#45;gf&#45;users"></i> -->
+<!--             Members -->
+<!--           </a> -->
+<!--         </li> -->
+<!--         <li class="gf&#45;tabs&#45;item"> -->
+<!--           <a class="gf&#45;tabs&#45;link" href="org/user&#45;groups"> -->
+<!--             <i class="gicon gicon&#45;user&#45;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">
     <div class="gf-form-button-row">
       <button type="submit" class="btn btn-success" ng-click="update()">Save</button>
       <button type="submit" class="btn btn-success" ng-click="update()">Save</button>
     </div>
     </div>
-	</form>
-
-	<prefs-control mode="org"></prefs-control>
-
+  </form>
+  <prefs-control mode="org"></prefs-control>
 </div>
 </div>
 
 
 
 

+ 55 - 37
public/app/features/org/partials/orgUsers.html

@@ -1,34 +1,52 @@
-<navbar model="ctrl.navModel"></navbar>
+<!-- <navbar model="ctrl.navModel"></navbar> -->
+<!--  -->
+<!-- <div class="page&#45;container"> -->
+<!-- 	<div class="page&#45;header"> -->
+<!-- 		<page&#45;h1 model="ctrl.navModel"></page&#45;h1> -->
+<!--  -->
+<!-- 		<button class="btn btn&#45;success" ng&#45;click="ctrl.openAddUsersView()" ng&#45;hide="ctrl.externalUserMngLinkUrl"> -->
+<!-- 			<span>{{ctrl.addUsersBtnName}}</span> -->
+<!-- 		</button> -->
+<!--  -->
+<!-- 		<div class="page&#45;header&#45;tabs"> -->
+<!--  -->
+<!-- 			<a class="btn btn&#45;inverse" ng&#45;href="{{ctrl.externalUserMngLinkUrl}}" target="_blank" ng&#45;if="ctrl.externalUserMngLinkUrl"> -->
+<!-- 				<i class="fa fa&#45;external&#45;link&#45;square"></i> -->
+<!-- 				{{ctrl.addUsersBtnName}} -->
+<!--       </a> -->
+<!--  -->
+<!-- 			<ul class="gf&#45;tabs"> -->
+<!-- 				<li class="gf&#45;tabs&#45;item"> -->
+<!-- 					<a class="gf&#45;tabs&#45;link" ng&#45;click="ctrl.editor.index = 0" ng&#45;class="{active: ctrl.editor.index === 0}"> -->
+<!-- 						Users ({{ctrl.users.length}}) -->
+<!-- 					</a> -->
+<!-- 				</li> -->
+<!-- 				<li class="gf&#45;tabs&#45;item" ng&#45;show="ctrl.pendingInvites.length"> -->
+<!-- 					<a class="gf&#45;tabs&#45;link" ng&#45;click="ctrl.editor.index = 1" ng&#45;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">
 		<button class="btn btn-success" ng-click="ctrl.openAddUsersView()" ng-hide="ctrl.externalUserMngLinkUrl">
+      <i class="fa fa-plus"></i>
 			<span>{{ctrl.addUsersBtnName}}</span>
 			<span>{{ctrl.addUsersBtnName}}</span>
 		</button>
 		</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">
   <div class="grafana-info-box" ng-if="ctrl.externalUserMngInfo">
     <span ng-bind-html="ctrl.externalUserMngInfo"></span>
     <span ng-bind-html="ctrl.externalUserMngInfo"></span>
@@ -41,26 +59,26 @@
           <th></th>
           <th></th>
           <th>Login</th>
           <th>Login</th>
           <th>Email</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>Role</th>
           <th style="width: 34px;"></th>
           <th style="width: 34px;"></th>
         </tr>
         </tr>
       </thead>
       </thead>
       <tr ng-repeat="user in ctrl.users">
       <tr ng-repeat="user in ctrl.users">
         <td class="width-4 text-center">
         <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>{{user.login}}</td>
         <td><span class="ellipsis">{{user.email}}</span></td>
         <td><span class="ellipsis">{{user.email}}</span></td>
-				<td>{{user.lastSeenAtAge}}</td>
+        <td>{{user.lastSeenAtAge}}</td>
         <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>
         <td>
         <td>
           <a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">
           <a ng-click="ctrl.removeUser(user)" class="btn btn-danger btn-mini">

+ 3 - 6
public/app/features/org/partials/profile.html

@@ -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">
 	<form name="ctrl.userForm" class="gf-form-group">
-		<h3 class="page-heading">Information</h3>
 
 
 		<div class="gf-form max-width-30">
 		<div class="gf-form max-width-30">
 			<span class="gf-form-label width-8">Name</span>
 			<span class="gf-form-label width-8">Name</span>

+ 12 - 11
public/app/features/org/partials/user_groups.html

@@ -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()">
     <a class="btn btn-success" ng-click="ctrl.openUserGroupModal()">
       <i class="fa fa-plus"></i>
       <i class="fa fa-plus"></i>
       Create User Group
       Create User Group
     </a>
     </a>
   </div>
   </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">
   <div class="admin-list-table">
     <table class="filter-table form-inline" ng-show="ctrl.userGroups.length > 0">
     <table class="filter-table form-inline" ng-show="ctrl.userGroups.length > 0">
       <thead>
       <thead>
@@ -42,7 +44,6 @@
           </td>
           </td>
         </tr>
         </tr>
       </tbody>
       </tbody>
-
     </table>
     </table>
   </div>
   </div>
 
 

+ 1 - 1
public/app/features/org/prefs_control.ts

@@ -49,7 +49,7 @@ export class PrefsControlCtrl {
 
 
 var template = `
 var template = `
 <form name="ctrl.prefsForm" class="section gf-form-group">
 <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">
   <div class="gf-form">
     <span class="gf-form-label width-11">UI Theme</span>
     <span class="gf-form-label width-11">UI Theme</span>

+ 1 - 1
public/app/features/org/profile_ctrl.ts

@@ -14,7 +14,7 @@ export class ProfileCtrl {
   constructor(private backendSrv, private contextSrv, private $location, navModelSrv) {
   constructor(private backendSrv, private contextSrv, private $location, navModelSrv) {
     this.getUser();
     this.getUser();
     this.getUserOrgs();
     this.getUserOrgs();
-    this.navModel = navModelSrv.getNav('profile');
+    this.navModel = navModelSrv.getNav('profile', 'profile-settings', 0);
   }
   }
 
 
   getUser() {
   getUser() {

+ 1 - 1
public/app/features/org/user_groups_ctrl.ts

@@ -15,7 +15,7 @@ export class UserGroupsCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv, navModelSrv) {
   constructor(private backendSrv, navModelSrv) {
-    this.navModel = navModelSrv.getNav('cfg', 'users');
+    this.navModel = navModelSrv.getNav('cfg', 'teams', 0);
     this.get();
     this.get();
   }
   }
 
 

+ 6 - 6
public/app/features/playlist/partials/playlist.html

@@ -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>
 	<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="clearfix"></div>
 
 
 	<div class="gf-form-button-row">
 	<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-disabled="ctrl.playlistEditForm.$invalid || ctrl.isPlaylistEmpty()"
 			ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Create new playlist</a>
 			ng-click="ctrl.savePlaylist(ctrl.playlist, ctrl.playlistItems)">Create new playlist</a>
 		<a class="btn btn-success" ng-show="!ctrl.isNew()"
 		<a class="btn btn-success" ng-show="!ctrl.isNew()"

+ 6 - 6
public/app/features/playlist/partials/playlists.html

@@ -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>
       <i class="fa fa-plus"></i>
       New Playlist
       New Playlist
     </a>
     </a>
   </div>
   </div>
 
 
-  <table class="filter-table" style="margin-top: 20px">
+  <table class="filter-table">
     <thead>
     <thead>
       <th><strong>Name</strong></th>
       <th><strong>Name</strong></th>
       <th><strong>Start url</strong></th>
       <th><strong>Start url</strong></th>

+ 5 - 7
public/app/features/playlist/playlist_edit_ctrl.ts

@@ -1,5 +1,3 @@
-///<reference path="../../headers/common.d.ts" />
-
 import _ from 'lodash';
 import _ from 'lodash';
 import coreModule from '../../core/core_module';
 import coreModule from '../../core/core_module';
 
 
@@ -11,10 +9,12 @@ export class PlaylistEditCtrl {
   playlist: any = {
   playlist: any = {
     interval: '5m',
     interval: '5m',
   };
   };
+
   playlistItems: any = [];
   playlistItems: any = [];
   dashboardresult: any = [];
   dashboardresult: any = [];
   tagresult: any = [];
   tagresult: any = [];
   navModel: any;
   navModel: any;
+  isNew: boolean;
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(
   constructor(
@@ -24,7 +24,9 @@ export class PlaylistEditCtrl {
     $route,
     $route,
     navModelSrv
     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) {
     if ($route.current.params.id) {
       var playlistId = $route.current.params.id;
       var playlistId = $route.current.params.id;
@@ -104,10 +106,6 @@ export class PlaylistEditCtrl {
       });
       });
   }
   }
 
 
-  isNew() {
-    return !this.playlist.id;
-  }
-
   isPlaylistEmpty() {
   isPlaylistEmpty() {
     return !this.playlistItems.length;
     return !this.playlistItems.length;
   }
   }

+ 1 - 1
public/app/features/playlist/playlists_ctrl.ts

@@ -9,7 +9,7 @@ export class PlaylistsCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private $scope, private backendSrv, navModelSrv) {
   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 => {
     backendSrv.get('/api/playlists').then(result => {
       this.playlists = result;
       this.playlists = result;

+ 3 - 5
public/app/features/plugins/ds_edit_ctrl.ts

@@ -41,7 +41,7 @@ export class DataSourceEditCtrl {
     navModelSrv,
     navModelSrv,
   ) {
   ) {
 
 
-    this.navModel = navModelSrv.getNav('cfg', 'datasources');
+    this.navModel = navModelSrv.getNav('cfg', 'datasources', 0);
     this.datasources = [];
     this.datasources = [];
     this.tabIndex = 0;
     this.tabIndex = 0;
 
 
@@ -58,9 +58,7 @@ export class DataSourceEditCtrl {
     this.isNew = true;
     this.isNew = true;
     this.current = _.cloneDeep(defaults);
     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
     // We are coming from getting started
     if (this.$location.search().gettingstarted) {
     if (this.$location.search().gettingstarted) {
@@ -87,7 +85,7 @@ export class DataSourceEditCtrl {
     this.backendSrv.get('/api/datasources/' + id).then(ds => {
     this.backendSrv.get('/api/datasources/' + id).then(ds => {
       this.isNew = false;
       this.isNew = false;
       this.current = ds;
       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);
       this.navModel.breadcrumbs.push(this.navModel.node);
 
 
       if (datasourceCreated) {
       if (datasourceCreated) {

+ 1 - 1
public/app/features/plugins/ds_list_ctrl.ts

@@ -13,7 +13,7 @@ export class DataSourcesCtrl {
     private datasourceSrv,
     private datasourceSrv,
     private navModelSrv) {
     private navModelSrv) {
 
 
-    this.navModel = this.navModelSrv.getNav('cfg', 'datasources');
+    this.navModel = this.navModelSrv.getNav('cfg', 'datasources', 0);
 
 
     backendSrv.get('/api/datasources').then(result => {
     backendSrv.get('/api/datasources').then(result => {
       this.datasources = result;
       this.datasources = result;

+ 0 - 6
public/app/features/plugins/import_list/import_list.html

@@ -13,12 +13,6 @@
 						{{dash.title}}
 						{{dash.title}}
 					</span>
 					</span>
 				</td>
 				</td>
-				<td>
-          <span>
-            Revision: {{dash.revision}}
-            <span ng-if="dash.imported" class="small">(Imported: {{dash.importedRevision}})</span>
-          <span>
-				</td>
 				<td style="text-align: right">
 				<td style="text-align: right">
 					<button class="btn btn-secondary btn-small" ng-click="ctrl.import(dash, false)" ng-show="!dash.imported">
 					<button class="btn btn-secondary btn-small" ng-click="ctrl.import(dash, false)" ng-show="!dash.imported">
 						Import
 						Import

+ 68 - 77
public/app/features/plugins/partials/ds_edit.html

@@ -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>
 </div>

+ 24 - 25
public/app/features/plugins/partials/ds_http_settings.html

@@ -1,7 +1,7 @@
 
 
 
 
 <div class="gf-form-group">
 <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-group">
     <div class="gf-form-inline">
     <div class="gf-form-inline">
       <div class="gf-form max-width-30">
       <div class="gf-form max-width-30">
@@ -38,39 +38,38 @@
     </div>
     </div>
   </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>
+  <h3 class="section-heading">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>
-
     <div class="gf-form-inline">
     <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" 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>
   </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>
 
 
 <div class="gf-form-group" ng-if="current.basicAuth">
 <div class="gf-form-group" ng-if="current.basicAuth">
   <h6>Basic Auth Details</h6>
   <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>
 
 
 <div class="gf-form-group" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">
 <div class="gf-form-group" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">

+ 9 - 9
public/app/features/plugins/partials/ds_list.html

@@ -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>
 	</div>
 
 
 	<section class="card-section" layout-mode>
 	<section class="card-section" layout-mode>
 		<layout-selector></layout-selector>
 		<layout-selector></layout-selector>
-
 		<ol class="card-list">
 		<ol class="card-list">
 			<li class="card-item-wrapper" ng-repeat="ds in ctrl.datasources">
 			<li class="card-item-wrapper" ng-repeat="ds in ctrl.datasources">
 				<a class="card-item" href="datasources/edit/{{ds.id}}/">
 				<a class="card-item" href="datasources/edit/{{ds.id}}/">
@@ -43,4 +43,4 @@
 	<div ng-if="ctrl.datasources.length === 0">
 	<div ng-if="ctrl.datasources.length === 0">
 		<em>No data sources defined</em>
 		<em>No data sources defined</em>
 	</div>
 	</div>
-</div>
+</div>

+ 19 - 39
public/app/features/plugins/partials/plugin_edit.html

@@ -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>
 
 
-  <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 ng-bind-html="ctrl.readmeHtml" class="markdown-html">
       </div>
       </div>
     </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">
       <div ng-if="ctrl.model.id">
         <plugin-component type="app-config-ctrl"></plugin-component>
         <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>
     </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>
     </div>
 
 
     <aside class="page-sidebar">
     <aside class="page-sidebar">
       <section class="page-sidebar-section">
       <section class="page-sidebar-section">
         <h4>Version</h4>
         <h4>Version</h4>
         <span>{{ctrl.model.info.version}}</span>
         <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>
           <a ng-click="ctrl.updateAvailable()" bs-tooltip="ctrl.model.latestVersion">Update Available!</a>
-				</div>
+        </div>
       </section>
       </section>
       <section class="page-sidebar-section" ng-show="ctrl.model.type === 'app'">
       <section class="page-sidebar-section" ng-show="ctrl.model.type === 'app'">
         <h5>Includes</h4>
         <h5>Includes</h4>

+ 74 - 56
public/app/features/plugins/partials/plugin_list.html

@@ -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&#45;header&#45;canvas"> -->
+<!--   <div class="page&#45;container"> -->
+<!--     <navbar model="ctrl.navModel"></navbar> -->
+<!--  -->
+<!--     <div class="page&#45;header"> -->
+<!-- 		  <page&#45;h1 model="ctrl.navModel"></page&#45;h1> -->
+<!--  -->
+<!--       <div class="page&#45;header&#45;tabs"> -->
+<!--         <ul class="gf&#45;tabs"> -->
+<!--           <li class="gf&#45;tabs&#45;item"> -->
+<!--             <a class="gf&#45;tabs&#45;link" href="plugins?type=panel" ng&#45;class="{active: ctrl.tabIndex === 0}"> -->
+<!--               <i class="icon&#45;gf icon&#45;gf&#45;panel"></i> -->
+<!--               Panels -->
+<!--             </a> -->
+<!--           </li> -->
+<!--           <li class="gf&#45;tabs&#45;item"> -->
+<!--             <a class="gf&#45;tabs&#45;link" href="plugins?type=datasource" ng&#45;class="{active: ctrl.tabIndex === 1}"> -->
+<!--               <i class="gicon gicon&#45;datasources"></i> -->
+<!--               Data sources -->
+<!--             </a> -->
+<!--           </li> -->
+<!--           <li class="gf&#45;tabs&#45;item"> -->
+<!--             <a class="gf&#45;tabs&#45;link" href="plugins?type=app" ng&#45;class="{active: ctrl.tabIndex === 2}"> -->
+<!--               <i class="icon&#45;gf icon&#45;gf&#45;apps"></i> -->
+<!--               Apps -->
+<!--             </a> -->
+<!--           </li> -->
+<!--         </ul> -->
+<!--  -->
+<!--         <a class="get&#45;more&#45;plugins&#45;link pull&#45;right" href="https://grafana.com/plugins?utm_source=grafana_plugin_list" target="_blank"> -->
+<!--           Find more <img src="public/img/icn&#45;plugins&#45;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>
 	</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>
 </div>

+ 1 - 1
public/app/features/plugins/plugin_edit_ctrl.ts

@@ -27,7 +27,7 @@ export class PluginEditCtrl {
     $routeParams,
     $routeParams,
     navModelSrv,
     navModelSrv,
   ) {
   ) {
-    this.navModel = navModelSrv.getNav('cfg', 'plugins');
+    this.navModel = navModelSrv.getNav('cfg', 'plugins', 0);
     this.model = {};
     this.model = {};
     this.pluginId = $routeParams.pluginId;
     this.pluginId = $routeParams.pluginId;
     this.tabIndex = 0;
     this.tabIndex = 0;

+ 13 - 19
public/app/features/plugins/plugin_list_ctrl.ts

@@ -1,34 +1,28 @@
-///<reference path="../../headers/common.d.ts" />
-
 import angular from 'angular';
 import angular from 'angular';
+import _ from 'lodash';
 
 
 export class PluginListCtrl {
 export class PluginListCtrl {
   plugins: any[];
   plugins: any[];
   tabIndex: number;
   tabIndex: number;
   navModel: any;
   navModel: any;
+  searchQuery: string;
+  allPlugins: any[];
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv: any, $location, navModelSrv) {
   constructor(private backendSrv: any, $location, navModelSrv) {
     this.tabIndex = 0;
     this.tabIndex = 0;
-    this.navModel = navModelSrv.getNav('cfg', 'plugins');
-
-    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.navModel = navModelSrv.getNav('cfg', 'plugins', 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.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);
     });
     });
   }
   }
 }
 }

+ 3 - 7
public/app/features/snapshot/partials/snapshots.html

@@ -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>
     <thead>
       <th><strong>Name</strong></th>
       <th><strong>Name</strong></th>
       <th><strong>Snapshot url</strong></th>
       <th><strong>Snapshot url</strong></th>

+ 1 - 1
public/app/features/snapshot/snapshot_ctrl.ts

@@ -9,7 +9,7 @@ export class SnapshotsCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private $rootScope, private backendSrv, navModelSrv) {
   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.backendSrv.get('/api/dashboard/snapshots').then(result => {
       this.snapshots = result;
       this.snapshots = result;
     });
     });

+ 1 - 1
public/app/plugins/datasource/graphite/partials/config.html

@@ -3,7 +3,7 @@
 	suggest-url="http://localhost:8080">
 	suggest-url="http://localhost:8080">
 </datasource-http-settings>
 </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-group">
 	<div class="gf-form">
 	<div class="gf-form">

+ 1 - 0
public/sass/_grafana.scss

@@ -85,6 +85,7 @@
 @import "components/code_editor";
 @import "components/code_editor";
 @import "components/dashboard_grid";
 @import "components/dashboard_grid";
 @import "components/dashboard_list";
 @import "components/dashboard_list";
+@import "components/page_header";
 
 
 
 
 // PAGES
 // PAGES

+ 2 - 1
public/sass/_old_responsive.scss

@@ -29,8 +29,9 @@
   .dashnav-action-icons {
   .dashnav-action-icons {
     display: none;
     display: none;
   }
   }
+
   .page-container {
   .page-container {
-    padding: ($spacer * 1) ($spacer * 2);
+    padding: 0 $spacer * 2;
   }
   }
 
 
   .dash-row-menu-container {
   .dash-row-menu-container {

+ 1 - 0
public/sass/_variables.dark.scss

@@ -52,6 +52,7 @@ $critical:              #ed2e18;
 // -------------------------
 // -------------------------
 $body-bg:  			   	    rgb(23,24,25);
 $body-bg:  			   	    rgb(23,24,25);
 $page-bg:  			   	    rgb(22, 23, 25);
 $page-bg:  			   	    rgb(22, 23, 25);
+
 $body-color:   		 	    $gray-4;
 $body-color:   		 	    $gray-4;
 $text-color:   	   		  $gray-4;
 $text-color:   	   		  $gray-4;
 $text-color-strong: 	  $white;
 $text-color-strong: 	  $white;

+ 1 - 3
public/sass/_variables.scss

@@ -227,7 +227,5 @@ $dashboard-padding: $panel-margin * 2;
 $panel-padding: 0px 10px 5px 10px;
 $panel-padding: 0px 10px 5px 10px;
 
 
 // tabs
 // tabs
-$tabs-padding-top: 0.6rem;
-$tabs-padding-bottom: 0.4rem;
-$tabs-top-margin: 0.5rem;
+$tabs-padding: 10px 15px 10px;
 
 

+ 8 - 0
public/sass/base/_icons.scss

@@ -43,5 +43,13 @@
   background-image: url('../img/icons_#{$theme-name}_theme/icon_add_panel.svg');
   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');
+}
+
 
 
 
 

+ 1 - 1
public/sass/components/_footer.scss

@@ -5,7 +5,7 @@
 .footer {
 .footer {
   color: $footer-link-color;
   color: $footer-link-color;
   padding: 5rem 0 1rem 0;
   padding: 5rem 0 1rem 0;
-  font-size: $font-size-xs;
+  font-size: $font-size-sm;
   width: 98%;  /* was causing horiz scrollbars - need to examine */
   width: 98%;  /* was causing horiz scrollbars - need to examine */
 
 
   a {
   a {

+ 159 - 0
public/sass/components/_page_header.scss

@@ -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;
+  }
+}
+

+ 1 - 1
public/sass/components/_tabbed_view.scss

@@ -34,7 +34,7 @@
   margin: 0;
   margin: 0;
   background-color: transparent;
   background-color: transparent;
   border: none;
   border: none;
-  padding: ($tabs-padding-top + $tabs-top-margin) $spacer $tabs-padding-bottom;
+  padding: $tabs-padding;
   color: $text-color;
   color: $text-color;
   i {
   i {
     font-size: 120%;
     font-size: 120%;

+ 11 - 51
public/sass/components/_tabs.scss

@@ -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 {
 .gf-tabs {
   @include clearfix();
   @include clearfix();
   float: left;
   float: left;
-  margin: $tabs-top-margin 0 0 0;
+  position: relative;
+  top: 1px;
 }
 }
 
 
 .gf-tabs-item {
 .gf-tabs-item {
@@ -44,13 +11,17 @@
 }
 }
 
 
 .gf-tabs-link {
 .gf-tabs-link {
-  padding: $tabs-padding-top $spacer $tabs-padding-bottom $spacer;
+  padding: $tabs-padding;
   margin-right: $spacer/2;
   margin-right: $spacer/2;
-  border: 1px solid transparent;
   position: relative;
   position: relative;
   display: block;
   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,
   &:hover,
   &:focus {
   &:focus {
@@ -60,20 +31,9 @@
   &.active,
   &.active,
   &.active:hover,
   &.active:hover,
   &.active:focus {
   &.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;
     color: $link-color;
-    position: relative;
-    top: 1px;
   }
   }
 }
 }
 
 
-.form-tabs-wrapper {
-  @include brand-bottom-border();
-  @include clearfix();
-}
-
-.form-tabs-content {
-  padding: $spacer*2 $spacer;
-}

+ 32 - 145
public/sass/layout/_page.scss

@@ -16,7 +16,7 @@
 
 
 .page-container {
 .page-container {
   @extend .container;
   @extend .container;
-  padding: $spacer $spacer $spacer $spacer*3;
+  padding: 0 $spacer * 2;
 }
 }
 
 
 .scroll-canvas {
 .scroll-canvas {
@@ -31,80 +31,53 @@
 }
 }
 
 
 .page-body {
 .page-body {
-  @include media-breakpoint-up(md) {
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-  }
+  padding-top: $spacer*2;
 }
 }
 
 
-.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;
-    margin-left: $page-sidebar-margin;
-  }
+.page-heading {
+  font-size: 1.25rem;
+  margin-top: 0;
+  margin-bottom: $spacer * 0.7;
 }
 }
 
 
-.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;
-    }
-  }
+.page-action-bar {
+  margin-bottom: $spacer * 2;
+  display: flex;
+  align-items: flex-start;
 
 
-  a, button {
-    float: right;
+  > a, > button {
     margin-left: $spacer;
     margin-left: $spacer;
-
-    // better align icons
-    .fa {
-      position: relative;
-      top: 1px;
-    }
   }
   }
 }
 }
 
 
+.page-action-bar__spacer {
+  width: $spacer * 2;
+  flex-grow: 1;
+}
 
 
+.sidebar-content {
+  width: calc(100% - #{$page-sidebar-width + $page-sidebar-margin}); // sidebar width + margin
+}
 
 
-.page-heading {
-  font-size: 1.25rem;
-  margin-top: 0;
-  margin-bottom: $spacer * 0.7;
+.sidebar-container {
+  @include media-breakpoint-up(md) {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+  }
 }
 }
 
 
-.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-sidebar {
+  @include media-breakpoint-up(md) {
+    width: $page-sidebar-width;
+    margin-left: $page-sidebar-margin;
   }
   }
 }
 }
 
 
+.page-sub-heading {
+  margin-bottom: $spacer;
+}
+
 .page-sidebar {
 .page-sidebar {
   color: $text-color-weak;
   color: $text-color-weak;
   h4 {
   h4 {
@@ -120,89 +93,3 @@
 .page-sidebar-section {
 .page-sidebar-section {
   margin-bottom: $spacer*2;
   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;
-  }
-}
-
-

+ 12 - 38
public/sass/pages/_plugins.scss

@@ -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 {
 .get-more-plugins-link {
   color: $gray-3;
   color: $gray-3;
@@ -55,3 +17,15 @@
     display: none;
     display: none;
   }
   }
 }
 }
+
+.plugin-info-list-item {
+  img {
+    width: 16px;
+  }
+
+  white-space: nowrap;
+  max-width: $page-sidebar-width;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+