Commit 3fc2e530 by Daniel Lee

Merge branch 'fix-11053' of https://github.com/alexanderzobnin/grafana into…

Merge branch 'fix-11053' of https://github.com/alexanderzobnin/grafana into alexanderzobnin-fix-11053
parents 8b2441e0 7b75b251
...@@ -136,6 +136,7 @@ ...@@ -136,6 +136,7 @@
"angular-route": "^1.6.6", "angular-route": "^1.6.6",
"angular-sanitize": "^1.6.6", "angular-sanitize": "^1.6.6",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"baron": "^3.0.3",
"brace": "^0.10.0", "brace": "^0.10.0",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"clipboard": "^1.7.1", "clipboard": "^1.7.1",
......
import React from 'react'; import React from 'react';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
export interface Props { export interface Props {
children: any; children: any;
...@@ -8,31 +8,36 @@ export interface Props { ...@@ -8,31 +8,36 @@ export interface Props {
export default class ScrollBar extends React.Component<Props, any> { export default class ScrollBar extends React.Component<Props, any> {
private container: any; private container: any;
private ps: PerfectScrollbar; private scrollbar: baron;
constructor(props) { constructor(props) {
super(props); super(props);
} }
componentDidMount() { componentDidMount() {
this.ps = new PerfectScrollbar(this.container, { this.scrollbar = baron({
wheelPropagation: true, root: this.container.parentElement,
scroller: this.container,
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
track: '.baron__track',
}); });
} }
componentDidUpdate() { componentDidUpdate() {
this.ps.update(); this.scrollbar.update();
} }
componentWillUnmount() { componentWillUnmount() {
this.ps.destroy(); this.scrollbar.dispose();
} }
// methods can be invoked by outside // methods can be invoked by outside
setScrollTop(top) { setScrollTop(top) {
if (this.container) { if (this.container) {
this.container.scrollTop = top; this.container.scrollTop = top;
this.ps.update(); this.scrollbar.update();
return true; return true;
} }
...@@ -42,7 +47,7 @@ export default class ScrollBar extends React.Component<Props, any> { ...@@ -42,7 +47,7 @@ export default class ScrollBar extends React.Component<Props, any> {
setScrollLeft(left) { setScrollLeft(left) {
if (this.container) { if (this.container) {
this.container.scrollLeft = left; this.container.scrollLeft = left;
this.ps.update(); this.scrollbar.update();
return true; return true;
} }
...@@ -55,8 +60,14 @@ export default class ScrollBar extends React.Component<Props, any> { ...@@ -55,8 +60,14 @@ export default class ScrollBar extends React.Component<Props, any> {
render() { render() {
return ( return (
<div className={this.props.className} ref={this.handleRef}> <div className="baron baron__root baron__clipper">
{this.props.children} <div className={this.props.className + ' baron__scroller'} ref={this.handleRef}>
{this.props.children}
</div>
<div className="baron__track">
<div className="baron__bar" />
</div>
</div> </div>
); );
} }
......
import PerfectScrollbar from 'perfect-scrollbar'; import $ from 'jquery';
import baron from 'baron';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
const scrollBarHTML = `
<div class="baron__track">
<div class="baron__bar"></div>
</div>
`;
const scrollRootClass = 'baron baron__root';
const scrollerClass = 'baron__scroller';
export function geminiScrollbar() { export function geminiScrollbar() {
return { return {
restrict: 'A', restrict: 'A',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
let scrollbar = new PerfectScrollbar(elem[0], { let scrollRoot = elem.parent();
wheelPropagation: true, let scroller = elem;
wheelSpeed: 3,
if (attrs.grafanaScrollbar && attrs.grafanaScrollbar === 'scrollonroot') {
scrollRoot = scroller;
}
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
elem.addClass(scrollerClass);
let scrollbar = baron({
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
track: '.baron__track',
}); });
let lastPos = 0; let lastPos = 0;
appEvents.on( appEvents.on(
...@@ -37,7 +63,8 @@ export function geminiScrollbar() { ...@@ -37,7 +63,8 @@ export function geminiScrollbar() {
}); });
scope.$on('$destroy', () => { scope.$on('$destroy', () => {
scrollbar.destroy(); // scrollbar.destroy();
scrollbar.dispose();
}); });
}, },
}; };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
<div class="search-dropdown"> <div class="search-dropdown">
<div class="search-dropdown__col_1"> <div class="search-dropdown__col_1">
<div class="search-results-scroller">
<div class="search-results-container" grafana-scrollbar> <div class="search-results-container" grafana-scrollbar>
<h6 ng-show="!ctrl.isLoading && ctrl.results.length === 0">No dashboards matching your query were found.</h6> <h6 ng-show="!ctrl.isLoading && ctrl.results.length === 0">No dashboards matching your query were found.</h6>
<dashboard-search-results <dashboard-search-results
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
on-folder-expanding="ctrl.folderExpanding()" on-folder-expanding="ctrl.folderExpanding()"
on-folder-expanded="ctrl.folderExpanded($folder)" /> on-folder-expanded="ctrl.folderExpanded($folder)" />
</div> </div>
</div>
</div> </div>
<div class="search-dropdown__col_2"> <div class="search-dropdown__col_2">
......
import angular from 'angular'; import angular from 'angular';
import $ from 'jquery';
import Drop from 'tether-drop'; import Drop from 'tether-drop';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
var module = angular.module('grafana.directives'); var module = angular.module('grafana.directives');
...@@ -86,6 +87,9 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) { ...@@ -86,6 +87,9 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
function panelHeightUpdated() { function panelHeightUpdated() {
panelContent.css({ height: ctrl.height + 'px' }); panelContent.css({ height: ctrl.height + 'px' });
}
function resizeScrollableContent() {
if (panelScrollbar) { if (panelScrollbar) {
panelScrollbar.update(); panelScrollbar.update();
} }
...@@ -100,8 +104,26 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) { ...@@ -100,8 +104,26 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
// update scrollbar after mounting // update scrollbar after mounting
ctrl.events.on('component-did-mount', () => { ctrl.events.on('component-did-mount', () => {
if (ctrl.__proto__.constructor.scrollable) { if (ctrl.__proto__.constructor.scrollable) {
panelScrollbar = new PerfectScrollbar(panelContent[0], { const scrollRootClass = 'baron baron__root baron__clipper panel-content--scrollable';
wheelPropagation: true, const scrollerClass = 'baron__scroller';
const scrollBarHTML = `
<div class="baron__track">
<div class="baron__bar"></div>
</div>
`;
let scrollRoot = panelContent;
let scroller = panelContent.find(':first-child').find(':first-child');
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
scroller.addClass(scrollerClass);
panelScrollbar = baron({
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
}); });
} }
}); });
...@@ -110,6 +132,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) { ...@@ -110,6 +132,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
ctrl.calculatePanelHeight(); ctrl.calculatePanelHeight();
panelHeightUpdated(); panelHeightUpdated();
$timeout(() => { $timeout(() => {
resizeScrollableContent();
ctrl.render(); ctrl.render();
}); });
}); });
...@@ -199,7 +222,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) { ...@@ -199,7 +222,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
} }
if (panelScrollbar) { if (panelScrollbar) {
panelScrollbar.update(); panelScrollbar.dispose();
} }
}); });
}, },
......
<div dash-class ng-if="ctrl.dashboard"> <div dash-class ng-if="ctrl.dashboard">
<dashnav dashboard="ctrl.dashboard"></dashnav> <dashnav dashboard="ctrl.dashboard"></dashnav>
<div class="scroll-canvas scroll-canvas--dashboard" grafana-scrollbar> <div class="scroll-canvas scroll-canvas--dashboard">
<dashboard-settings dashboard="ctrl.dashboard" <div grafana-scrollbar>
ng-if="ctrl.dashboardViewState.state.editview" <dashboard-settings dashboard="ctrl.dashboard"
class="dashboard-settings"> ng-if="ctrl.dashboardViewState.state.editview"
</dashboard-settings> class="dashboard-settings">
</dashboard-settings>
<div class="dashboard-container"> <div class="dashboard-container">
<dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard"> <dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard">
</dashboard-submenu> </dashboard-submenu>
<dashboard-grid get-panel-container="ctrl.getPanelContainer"> <dashboard-grid get-panel-container="ctrl.getPanelContainer">
</dashboard-grid> </dashboard-grid>
</div>
</div> </div>
</div> </div>
</div> </div>
import angular from 'angular'; import angular from 'angular';
import _ from 'lodash'; import _ from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
var module = angular.module('grafana.directives'); var module = angular.module('grafana.directives');
...@@ -238,8 +238,10 @@ module.directive('graphLegend', function(popoverSrv, $timeout) { ...@@ -238,8 +238,10 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
tbodyElem.append(tableHeaderElem); tbodyElem.append(tableHeaderElem);
tbodyElem.append(seriesElements); tbodyElem.append(seriesElements);
elem.append(tbodyElem); elem.append(tbodyElem);
tbodyElem.wrap('<div class="graph-legend-content"></div>');
} else { } else {
elem.append(seriesElements); elem.append('<div class="graph-legend-content"></div>');
elem.find('.graph-legend-content').append(seriesElements);
} }
if (!panel.legend.rightSide || (panel.legend.rightSide && legendWidth !== legendRightDefaultWidth)) { if (!panel.legend.rightSide || (panel.legend.rightSide && legendWidth !== legendRightDefaultWidth)) {
...@@ -250,23 +252,44 @@ module.directive('graphLegend', function(popoverSrv, $timeout) { ...@@ -250,23 +252,44 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
} }
function addScrollbar() { function addScrollbar() {
const scrollbarOptions = { const scrollRootClass = 'baron baron__root';
// Number of pixels the content height can surpass the container height without enabling the scroll bar. const scrollerClass = 'baron__scroller';
scrollYMarginOffset: 2, const scrollBarHTML = `
suppressScrollX: true, <div class="baron__track">
wheelPropagation: true, <div class="baron__bar"></div>
</div>
`;
let scrollRoot = elem;
let scroller = elem.find('.graph-legend-content');
// clear existing scroll bar track to prevent duplication
scrollRoot.find('.baron__track').remove();
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
scroller.addClass(scrollerClass);
let scrollbarParams = {
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
track: '.baron__track',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
}; };
if (!legendScrollbar) { if (!legendScrollbar) {
legendScrollbar = new PerfectScrollbar(elem[0], scrollbarOptions); legendScrollbar = baron(scrollbarParams);
} else { } else {
legendScrollbar.update(); destroyScrollbar();
legendScrollbar = baron(scrollbarParams);
} }
} }
function destroyScrollbar() { function destroyScrollbar() {
if (legendScrollbar) { if (legendScrollbar) {
legendScrollbar.destroy(); legendScrollbar.dispose();
legendScrollbar = undefined; legendScrollbar = undefined;
} }
} }
......
.add-panel { .add-panel {
height: 100%; height: 100%;
.baron__root {
height: calc(100% - 43px);
}
} }
.add-panel__header { .add-panel__header {
...@@ -39,7 +43,6 @@ ...@@ -39,7 +43,6 @@
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
overflow: auto; overflow: auto;
height: calc(100% - 43px);
align-content: flex-start; align-content: flex-start;
justify-content: space-around; justify-content: space-around;
position: relative; position: relative;
......
...@@ -56,11 +56,17 @@ ...@@ -56,11 +56,17 @@
padding-top: 6px; padding-top: 6px;
position: relative; position: relative;
height: 100%;
.popover-content { .popover-content {
padding: 0; padding: 0;
} }
} }
.graph-legend-content {
position: relative;
}
.graph-legend-icon { .graph-legend-icon {
position: relative; position: relative;
padding-right: 4px; padding-right: 4px;
...@@ -124,9 +130,9 @@ ...@@ -124,9 +130,9 @@
.graph-legend-table { .graph-legend-table {
tbody { tbody {
display: block; display: block;
position: relative;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
height: 100%;
padding-bottom: 1px; padding-bottom: 1px;
padding-right: 5px; padding-right: 5px;
padding-left: 5px; padding-left: 5px;
......
...@@ -9,6 +9,11 @@ ...@@ -9,6 +9,11 @@
-ms-touch-action: auto; -ms-touch-action: auto;
} }
// ._scrollbar {
// overflow-x: hidden !important;
// overflow-y: auto;
// }
/* /*
* Scrollbar rail styles * Scrollbar rail styles
*/ */
...@@ -104,13 +109,19 @@ ...@@ -104,13 +109,19 @@
// Srollbars // Srollbars
// //
::-webkit-scrollbar { // ::-webkit-scrollbar {
width: 8px; // width: 8px;
height: 8px; // height: 8px;
} // }
// ::-webkit-scrollbar:hover {
// height: 8px;
// }
::-webkit-scrollbar:hover { ::-webkit-scrollbar {
height: 8px; // Hide system scrollbar (Mac OS X)
width: 0;
height: 0;
} }
::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:start:decrement,
...@@ -172,3 +183,111 @@ ...@@ -172,3 +183,111 @@
border-top: 1px solid $scrollbarBorder; border-top: 1px solid $scrollbarBorder;
border-left: 1px solid $scrollbarBorder; border-left: 1px solid $scrollbarBorder;
} }
// Baron styles
.baron {
display: inline-block;
overflow: hidden;
// Width needs to be set to prevent content width issues
// Set to 99% instead of 100% for fixing Firefox issue (white stripe on the right of scrollbar)
width: 99%;
}
.baron__clipper {
position: relative;
overflow: hidden;
height: 100%;
}
.baron__scroller {
overflow-y: scroll;
-ms-overflow-style: none;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
border: 0;
padding: 0;
width: 100%;
height: 100%;
-webkit-overflow-scrolling: touch;
/* remove line to customize scrollbar in iOs */
}
.baron__scroller::-webkit-scrollbar {
width: 0;
height: 0;
}
.baron__track {
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
.baron._scrollbar .baron__track {
display: block;
}
.baron__free {
position: absolute;
top: 0;
bottom: 0;
right: 0;
}
.baron__bar {
display: none;
position: absolute;
right: 0;
z-index: 1;
// width: 10px;
background: #999;
// height: 15px;
width: 15px;
transition: background-color 0.2s linear, opacity 0.2s linear;
opacity: 0;
}
.baron._scrollbar .baron__bar {
display: block;
@include gradient-vertical($scrollbarBackground, $scrollbarBackground2);
border-radius: 6px;
width: 6px;
/* there must be 'right' for ps__thumb-y */
right: 0px;
/* please don't change 'position' */
position: absolute;
// background-color: transparent;
// opacity: 0.6;
&:hover,
&:focus {
// background-color: transparent;
opacity: 0.9;
}
}
.baron._scrolling > .baron__track .baron__bar {
opacity: 0.6;
}
.baron__control {
display: none;
}
.baron.panel-content--scrollable {
// Width needs to be set to prevent content width issues
// Set to 99% instead of 100% for fixing Firefox issue (white stripe on the right of scrollbar)
width: 99%;
.baron__scroller {
padding-top: 1px;
}
}
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-grow: 1; flex-grow: 1;
// overflow-y: scroll;
} }
.search-dropdown__col_2 { .search-dropdown__col_2 {
...@@ -99,6 +101,11 @@ ...@@ -99,6 +101,11 @@
} }
} }
.search-results-scroller {
position: relative;
height: 100%;
}
.search-results-container { .search-results-container {
height: 100%; height: 100%;
display: block; display: block;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<link rel="icon" type="image/png" href="public/img/fav32.png"> <link rel="icon" type="image/png" href="public/img/fav32.png">
<link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28"> <link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28">
<link rel="apple-touch-icon" href="public/img/fav32.png"> <link rel="apple-touch-icon" href="public/img/fav32.png">
</head> </head>
<body ng-cloak class="theme-[[ .Theme ]]"> <body ng-cloak class="theme-[[ .Theme ]]">
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
</div> </div>
<div class="main-view"> <div class="main-view">
<!-- Not sure do we really need grafana-scrollbar here? -->
<div class="scroll-canvas" grafana-scrollbar> <div class="scroll-canvas" grafana-scrollbar>
<div ng-view></div> <div ng-view></div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment