Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Add tooltips to the visualization wrapper #6006

Merged
merged 1 commit into from
Apr 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ui/embedded.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions ui/styl/modules/layout-vars.styl
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ $top-bar-height = 95px
$subnav-height = 60px
$chart-width = 1300px
$footer-height = 73px

// Z-INDEXES
$tooltip-layer = 100
2 changes: 2 additions & 0 deletions ui/styl/modules/palette.styl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ $secondary-gray-11 = #5D5D5D // skull icon background
$secondary-gray-12 = #ECECEC // cancel button background
$secondary-gray-13 = #8D8D8D // cancel button foreground
$secondary-gray-14 = #D6D6D6 // cancel button hover
$secondary-gray-15 = rgba(67, 84, 109, .22) // tooltip shadow
$secondary-gray-16 = #6D6F74 // tooltip text

$secondary-green-1 = #66AA26 // subnav active

Expand Down
38 changes: 38 additions & 0 deletions ui/styl/partials/layout.styl
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,41 @@ table
text-decoration none
color $main-gray

.tooltip
position absolute
z-index $tooltip-layer
padding 35px
border 1px solid $secondary-gray-1
box-shadow 2px 2px 0 $secondary-gray-15
border-radius 4px
display none
background-color white
top 20px
left 95%
right auto

.content
font-size 11px
color $secondary-gray-16
font-family Lato-Regular
.title
font-size 13px
color $main-navy
font-family Lato-Heavy
text-align center
width 100%
padding-bottom 5px

&.viz-tooltip
width 250px

.viz-info-icon:hover + .tooltip
display block

// The last visualization tooltip should be above and to the left to avoid running off the page.
div.charts
div:last-child .visualization-wrapper .tooltip
right 15%
left auto
bottom 100%
top auto
17 changes: 15 additions & 2 deletions ui/ts/components/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// <reference path="../util/types.ts" />
/// <reference path="../util/querycache.ts" />
/// <reference path="../models/metrics.ts" />
/// <reference path="tooltip.ts" />

/**
* Components defines reusable components which may be used on multiple pages,
Expand Down Expand Up @@ -224,11 +225,23 @@ module Components {
} else {
g = m("", "loading...");
}

let topContent: _mithril.MithrilVirtualElement[] = [];
if (ctrl.vm.axis.tooltip() || ctrl.vm.query.error()) {
topContent.push(m(".viz-info-icon", icon));
}
if (ctrl.vm.axis.tooltip()) {
topContent.push(m.component(Components.Tooltip, {
tooltipClass: ".viz-tooltip",
title: ctrl.vm.axis.title(),
content: ctrl.vm.axis.tooltip(),
}));
}

return m(
".visualization-wrapper" + warningClass,
[
// TODO: pass in and display info icon tooltip
m(".viz-top", m(".viz-info-icon", icon)),
m(".viz-top", topContent),
g,
m(".viz-bottom", m(".viz-title", ctrl.vm.axis.title())),
]
Expand Down
32 changes: 32 additions & 0 deletions ui/ts/components/tooltip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// source: component/tooltip.ts
/// <reference path="../../bower_components/mithriljs/mithril.d.ts" />

module Components {
"use strict";

/**
* Tooltip is a component that creates a configurable tooltip
*/
export module Tooltip {
import MithrilVirtualElement = _mithril.MithrilVirtualElement;

interface TooltipConfig {
// Class applied to the tooltip
tooltipClass?: string;
title?: string;
content: (string|MithrilVirtualElement|MithrilVirtualElement[]|(MithrilVirtualElement|string)[]);
icon?: string;
position?: string;
}

export function controller(): any {}

export function view(ctrl: any, tooltipConfig: TooltipConfig): _mithril.MithrilVirtualElement {
return m(".tooltip" + (tooltipConfig.position || ".right") + (tooltipConfig.tooltipClass || ""), [
tooltipConfig.icon ? m(tooltipConfig.icon) : m(""),
m(".title", tooltipConfig.title ? tooltipConfig.title : ""),
m(".content", tooltipConfig.content),
]);
}
}
}
16 changes: 14 additions & 2 deletions ui/ts/components/visualizations/visualizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Visualizations {
virtualVisualizationElement: MithrilVirtualElement;
visualizationArguments?: any;
warning?: () => string;
tooltip?: string;
}

export module VisualizationWrapper {
Expand All @@ -36,11 +37,22 @@ module Visualizations {
warningClass = " .viz-faded";
}

let topContent: _mithril.MithrilVirtualElement[] = [];
if (info.tooltip || (info.warning && info.warning())) {
topContent.push(m(".viz-info-icon", icon));
}
if (info.tooltip) {
topContent.push(m.component(Components.Tooltip, {
tooltipClass: ".viz-tooltip",
title: info.title,
content: info.tooltip,
}));
}

return m(
".visualization-wrapper" + warningClass,
[
// TODO: pass in and display info icon tooltip
m(".viz-top", m(".viz-info-icon", icon)),
m(".viz-top", topContent),
info.virtualVisualizationElement,
m(".viz-bottom", m(".viz-title", info.title)),
]
Expand Down
7 changes: 6 additions & 1 deletion ui/ts/models/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ module Models {
*/
yHigh: Utils.ChainProperty<number, Axis> = Utils.ChainProp(this, 1);

/**
* tooltip is the informational tooltip for the chart
*/
tooltip: Utils.ChainProperty<string, Axis> = Utils.ChainProp(this, null);

// Stores the hard-coded title if one is set.
private _title: string;

Expand All @@ -282,7 +287,7 @@ module Models {
title(t: string): Axis;

// TODO: allow computed chain props and move this code there
title(t?: string): any {
title(t?: string): (Axis|string) {
if (typeof t === "string") {
this._title = t;
return this;
Expand Down
22 changes: 19 additions & 3 deletions ui/ts/pages/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ module AdminViews {
format: "s",
dataFn: function (allStats: Models.Proto.NodeStatus[]): { value: number; } { return {value: allStats && allStats.length || 0 }; },
},
tooltip: "The total number of nodes in the cluster.",
});

this.axesSmall.push({
Expand All @@ -114,6 +115,11 @@ module AdminViews {
},
zoom: "50%",
},
tooltipFn: function (allStats: Models.Proto.NodeStatus[], totalStats: Models.Proto.StatusMetrics): string {
let used: string = Utils.Format.Bytes(totalStats[MetricNames.liveBytes]);
let capacity: string = Utils.Format.Bytes(totalStats[MetricNames.capacity]);
return `You are using ${used} of ${capacity} storage capacity across all nodes.`;
},
});

let latencySelectors: Selector[] = _.map(
Expand All @@ -127,6 +133,7 @@ module AdminViews {
.format((v: number): string => fmt(Utils.Convert.NanoToMilli(v)))
.title("Query Time")
.label("Milliseconds")
.tooltip("The estimated time between query request and response, in milliseconds. Averaged across all nodes.")
);

// TODO: should we use load instead of CPU?
Expand All @@ -138,6 +145,7 @@ module AdminViews {
Metrics.Select.Avg(_sysMetric("cpu.sys.percent"))
.title("CPU Sys %")
).format(d3.format(".2%")).title("CPU Usage").stacked(true)
.tooltip("The percentage of CPU used by CockroachDB (User %) and system-level operations (Sys %) across all nodes.")
);

// TODO: get total/average memory from all machines
Expand All @@ -146,13 +154,16 @@ module AdminViews {
Metrics.Select.Avg(_sysMetric("allocbytes"))
.title("Memory")
).format(Utils.Format.Bytes).title("Memory Usage")
.tooltip("The average memory in use across all nodes.")

);

this._addChart(
Metrics.NewAxis(
Metrics.Select.Avg(_nodeMetric("sql.conns"))
.title("Connections")
).format(d3.format(".1")).title("SQL Connections")
).format(d3.format(".1")).title("SQL Connections")
.tooltip("The total number of active SQL connections to the cluster.")
);

this._addChart(
Expand All @@ -164,14 +175,16 @@ module AdminViews {
.nonNegativeRate()
.title("Bytes Out")
).format(Utils.Format.Bytes).title("SQL Traffic")
.tooltip("The amount of network traffic sent to and from the SQL system, in bytes.")
);

this._addChart(
Metrics.NewAxis(
Metrics.Select.Avg(_nodeMetric("sql.select.count"))
.nonNegativeRate()
.title("Selects")
).format(d3.format(".1")).title("Reads")
).format(d3.format(".1")).title("Reads Per Second")
.tooltip("The number of SELECT statements, averaged over a 10 second period.")
);

this._addChart(
Expand All @@ -185,7 +198,8 @@ module AdminViews {
Metrics.Select.Avg(_nodeMetric("sql.delete.count"))
.nonNegativeRate()
.title("Delete")
).format(d3.format(".1")).title("Writes")
).format(d3.format(".1")).title("Writes Per Second")
.tooltip("The number of INSERT, UPDATE, and DELETE statements, averaged over a 10 second period.")
);

this.exec = new Metrics.Executor(this._query);
Expand Down Expand Up @@ -215,6 +229,7 @@ module AdminViews {

axis.title = axis.titleFn ? axis.titleFn(allStats) : axis.title;
axis.visualizationArguments.data = axis.visualizationArguments.dataFn(allStats, totalStats);
axis.tooltip = axis.tooltipFn ? axis.tooltipFn(allStats, totalStats) : axis.tooltip;
axis.virtualVisualizationElement =
m.component(Visualizations.NumberVisualization, axis.visualizationArguments);
axis.warning = () => {
Expand All @@ -237,6 +252,7 @@ module AdminViews {

axis.title = axis.titleFn ? axis.titleFn(allStats) : axis.title;
axis.visualizationArguments.data = axis.visualizationArguments.dataFn(allStats, totalStats);
axis.tooltip = axis.tooltipFn ? axis.tooltipFn(allStats, totalStats) : axis.tooltip;
axis.virtualVisualizationElement =
m.component(Visualizations.NumberVisualization, axis.visualizationArguments);
axis.warning = () => {
Expand Down