From e8807f4bce62db7a7b95a852c081a947eb886f11 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 6 Dec 2017 17:36:44 +0100 Subject: [PATCH] Fixing tabs for Grafana 5 - #10082 (#10103) * ux: Make new tabs responsive #10082 * ux: Add possibility to manipulate url in angular router outside of angular - and use it in the responsive navigation #10082 --- public/app/core/angular_wrappers.ts | 6 +-- .../{ => PageHeader}/PageHeader.tsx | 45 +++++++++++++++++-- public/app/core/components/grafana_app.ts | 3 +- public/app/core/services/all.js | 1 + public/app/core/services/global_event_srv.ts | 21 +++++++++ public/app/core/utils/react2angular.ts | 3 -- public/app/features/plugins/ds_list_ctrl.ts | 14 +++++- public/sass/_variables.scss | 2 +- public/sass/components/_page_header.scss | 15 +++++++ public/sass/components/_tabs.scss | 14 +++++- 10 files changed, 109 insertions(+), 15 deletions(-) rename public/app/core/components/{ => PageHeader}/PageHeader.tsx (54%) create mode 100644 public/app/core/services/global_event_srv.ts diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index 3880be7de8d..4cb3ca513cc 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -1,12 +1,10 @@ import { react2AngularDirective } from 'app/core/utils/react2angular'; import { PasswordStrength } from './components/PasswordStrength'; -import PageHeader from './components/PageHeader'; +import PageHeader from './components/PageHeader/PageHeader'; import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; export function registerAngularDirectives() { - react2AngularDirective('passwordStrength', PasswordStrength, ['password']); - react2AngularDirective('pageHeader', PageHeader, ['model', "noTabs"]); + react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); - } diff --git a/public/app/core/components/PageHeader.tsx b/public/app/core/components/PageHeader/PageHeader.tsx similarity index 54% rename from public/app/core/components/PageHeader.tsx rename to public/app/core/components/PageHeader/PageHeader.tsx index e0accc03fd4..5371b464ec3 100644 --- a/public/app/core/components/PageHeader.tsx +++ b/public/app/core/components/PageHeader/PageHeader.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { NavModel, NavModelItem } from '../nav_model_srv'; +import { NavModel, NavModelItem } from '../../nav_model_srv'; import classNames from 'classnames'; +import appEvents from 'app/core/app_events'; export interface IProps { model: NavModel; @@ -26,8 +27,44 @@ function TabItem(tab: NavModelItem) { ); } -function Tabs({main}: {main: NavModelItem}) { - return ; +function SelectOption(navItem: NavModelItem) { + if (navItem.hideFromTabs) { // TODO: Rename hideFromTabs => hideFromNav + return (null); + } + + return ( + + ); +} + +function Navigation({main}: {main: NavModelItem}) { + return (); +} + +function SelectNav({main, customCss}: {main: NavModelItem, customCss: string}) { + const defaultSelectedItem = main.children.find(navItem => { + return navItem.active === true; + }); + + const gotoUrl = evt => { + var element = evt.target; + var url = element.options[element.selectedIndex].value; + appEvents.emit('location-change', {href: url}); + }; + + return (); +} + +function Tabs({main, customCss}: {main: NavModelItem, customCss: string}) { + return ; } export default class PageHeader extends React.Component { @@ -63,7 +100,7 @@ export default class PageHeader extends React.Component {
{this.renderHeaderTitle(this.props.model.main)} - {this.props.model.main.children && } + {this.props.model.main.children && }
diff --git a/public/app/core/components/grafana_app.ts b/public/app/core/components/grafana_app.ts index c60c8a20a4c..77089b14ddc 100644 --- a/public/app/core/components/grafana_app.ts +++ b/public/app/core/components/grafana_app.ts @@ -12,7 +12,7 @@ import Drop from 'tether-drop'; export class GrafanaCtrl { /** @ngInject */ - constructor($scope, alertSrv, utilSrv, $rootScope, $controller, contextSrv) { + constructor($scope, alertSrv, utilSrv, $rootScope, $controller, contextSrv, globalEventSrv) { $scope.init = function() { $scope.contextSrv = contextSrv; @@ -23,6 +23,7 @@ export class GrafanaCtrl { profiler.init(config, $rootScope); alertSrv.init(); utilSrv.init(); + globalEventSrv.init(); $scope.dashAlerts = alertSrv; }; diff --git a/public/app/core/services/all.js b/public/app/core/services/all.js index a308febb219..0053d789cbe 100644 --- a/public/app/core/services/all.js +++ b/public/app/core/services/all.js @@ -8,5 +8,6 @@ define([ './segment_srv', './backend_srv', './dynamic_directive_srv', + './global_event_srv' ], function () {}); diff --git a/public/app/core/services/global_event_srv.ts b/public/app/core/services/global_event_srv.ts new file mode 100644 index 00000000000..a4d5865eb63 --- /dev/null +++ b/public/app/core/services/global_event_srv.ts @@ -0,0 +1,21 @@ +import coreModule from 'app/core/core_module'; +import appEvents from 'app/core/app_events'; + +// This service is for registering global events. +// Good for communication react > angular and vice verse +export class GlobalEventSrv { + + /** @ngInject */ + constructor(private $location, private $timeout) { + } + + init() { + appEvents.on('location-change', payload => { + this.$timeout(() => { // A hack to use timeout when we're changing things (in this case the url) from outside of Angular. + this.$location.path(payload.href); + }); + }); + } +} + +coreModule.service('globalEventSrv', GlobalEventSrv); diff --git a/public/app/core/utils/react2angular.ts b/public/app/core/utils/react2angular.ts index ad6f7476d6a..e7ad3502f88 100644 --- a/public/app/core/utils/react2angular.ts +++ b/public/app/core/utils/react2angular.ts @@ -1,10 +1,7 @@ import coreModule from 'app/core/core_module'; export function react2AngularDirective(name: string, component: any, options: any) { - coreModule.directive(name, ['reactDirective', reactDirective => { return reactDirective(component, options); }]); - } - diff --git a/public/app/features/plugins/ds_list_ctrl.ts b/public/app/features/plugins/ds_list_ctrl.ts index 5feadb68fe3..ce9047166ef 100644 --- a/public/app/features/plugins/ds_list_ctrl.ts +++ b/public/app/features/plugins/ds_list_ctrl.ts @@ -1,6 +1,7 @@ /// import coreModule from '../../core/core_module'; +import {appEvents} from 'app/core/core'; export class DataSourcesCtrl { datasources: any; @@ -11,13 +12,24 @@ export class DataSourcesCtrl { private $scope, private backendSrv, private datasourceSrv, + private $location, private navModelSrv) { this.navModel = this.navModelSrv.getNav('cfg', 'datasources', 0); - + this.navigateToUrl = this.navigateToUrl.bind(this); backendSrv.get('/api/datasources').then(result => { this.datasources = result; }); + + appEvents.on('location-change', payload => { + this.navigateToUrl(payload.href); + }); + } + + navigateToUrl(url) { + // debugger; + this.$location.path(url); + this.$location.replace(); } removeDataSourceConfirmed(ds) { diff --git a/public/sass/_variables.scss b/public/sass/_variables.scss index bb4645504aa..9a1e42995b3 100644 --- a/public/sass/_variables.scss +++ b/public/sass/_variables.scss @@ -235,5 +235,5 @@ $dashboard-padding: $panel-margin * 2; $panel-padding: 0px 10px 5px 10px; // tabs -$tabs-padding: 9px 15px 9px; +$tabs-padding: 10px 15px 9px; diff --git a/public/sass/components/_page_header.scss b/public/sass/components/_page_header.scss index b6f44be1c18..dc570e8f13c 100644 --- a/public/sass/components/_page_header.scss +++ b/public/sass/components/_page_header.scss @@ -72,6 +72,21 @@ text-transform: uppercase; } +.page-header__select_nav { + margin-bottom: 10px; + + @include media-breakpoint-up(lg) { + display: none; + } +} + +.page-header__tabs { + display: none; + @include media-breakpoint-up(lg) { + display: block; + } +} + .page-breadcrumbs { display: flex; padding: 10px 0; diff --git a/public/sass/components/_tabs.scss b/public/sass/components/_tabs.scss index 80874241b79..396c3f98880 100644 --- a/public/sass/components/_tabs.scss +++ b/public/sass/components/_tabs.scss @@ -16,7 +16,7 @@ position: relative; display: block; border: solid transparent; - border-width: 2px 1px 1px; + border-width: 0 1px 1px; border-radius: 3px 3px 0 0; i { @@ -34,6 +34,18 @@ border-color: $orange $tab-border-color transparent; background: $page-bg; color: $link-color; + overflow: hidden; + + &::before { + display: block; + content: ' '; + position: absolute; + left: 0; + right: 0; + height: 2px; + top: 0; + background-image: linear-gradient(to right, #ffd500 0%, #ff4400 99%, #ff4400 100%); + } } }