Skip to content

Commit

Permalink
Add tooltips to the visualization wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Lang committed Apr 18, 2016
1 parent 152e79d commit 61be7da
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 10 deletions.
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

0 comments on commit 61be7da

Please sign in to comment.