Repository: nifi
Updated Branches:
  refs/heads/master 23350543f -> 3f60eac54


[NIFI-2599] Enhance Status History Dialog. This closes #894


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/3f60eac5
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/3f60eac5
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/3f60eac5

Branch: refs/heads/master
Commit: 3f60eac54413e90e8137471dcd1e50fa6137ef5a
Parents: 2335054
Author: Scott Aslan <[email protected]>
Authored: Tue Aug 23 10:40:23 2016 -0400
Committer: Matt Gilman <[email protected]>
Committed: Tue Aug 23 10:53:10 2016 -0400

----------------------------------------------------------------------
 .../WEB-INF/partials/status-history-dialog.jsp  |   16 +-
 .../nifi-web-ui/src/main/webapp/css/header.css  |    2 +-
 .../src/main/webapp/css/status-history.css      |   14 +-
 .../main/webapp/js/jquery/modal/jquery.modal.js |   14 +-
 .../src/main/webapp/js/nf/nf-status-history.js  | 1265 +++++++++---------
 .../webapp/js/nf/summary/nf-summary-table.js    |    1 +
 6 files changed, 641 insertions(+), 671 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/status-history-dialog.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/status-history-dialog.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/status-history-dialog.jsp
index 4b227d0..7daac42 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/status-history-dialog.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/status-history-dialog.jsp
@@ -16,16 +16,16 @@
 --%>
 <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
 <div id="status-history-dialog" class="hidden large-dialog">
+    <div id="status-history-refresh-container">
+        <button id="status-history-refresh-button" class="refresh-button 
pointer fa fa-refresh" title="Refresh"></button>
+        <div id="status-history-last-refreshed-container" 
class="last-refreshed-container">
+            Last updated:&nbsp;<span id="status-history-last-refreshed"></span>
+        </div>
+        <div id="status-history-loading-container" 
class="loading-container"></div>
+    </div>
     <div class="dialog-content">
         <div id="status-history-details"></div>
-        <div id="status-history-refresh-container">
-            <button id="status-history-refresh-button" class="refresh-button 
pointer fa fa-refresh" title="Refresh"></button>
-            <div id="status-history-last-refreshed-container" 
class="last-refreshed-container">
-                Last updated:&nbsp;<span 
id="status-history-last-refreshed"></span>
-            </div>
-            <div id="status-history-loading-container" 
class="loading-container"></div>
-            <div id="status-history-metric-combo"></div>
-        </div>
+        <div id="status-history-metric-combo"></div>
         <div id="status-history-container">
             <div id="status-history-chart-container"></div>
             <div id="status-history-chart-control-container"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
index c742c2f..24a370b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
@@ -190,7 +190,7 @@ md-toolbar.md-small .md-toolbar-tools {
     font-style: normal;
     font-weight: normal;
     font-size: 12px;
-    max-width: 250px;
+    max-width: 130px;
     text-overflow: ellipsis;
     line-height: normal;
     overflow: hidden;

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
index ac969c2..e421f61 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
@@ -27,9 +27,9 @@
 
 #status-history-refresh-container {
     position: absolute;
-    top: 0px;
-    left: 40%;
-    right: 0px;
+    left: 20px;
+    bottom: 20px;
+    z-index: 1;
 }
 
 #status-history-loading-container {
@@ -57,6 +57,7 @@
 
 #status-history-metric-combo {
     float: right;
+    width: 250px;
 }
 
 #status-history-container {
@@ -68,7 +69,6 @@
 }
 
 #status-history-chart-container {
-    height: 265px;
     background-color: #fff;
     overflow: hidden;
     cursor: default;
@@ -86,6 +86,11 @@
     left: 0px;
     right: 60%;
     bottom: 0px;
+    overflow-y: auto;
+}
+
+#status-history-dialog > .dialog-content {
+    overflow: visible;
 }
 
 div.status-history-detail {
@@ -132,7 +137,6 @@ div.legend-entry {
 
 div.legend-label {
     font-weight: bold;
-    width: 240px;
     overflow: hidden;
     white-space: nowrap;
     line-height: normal;

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
index 1e73676..82f8bf6 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
@@ -463,13 +463,13 @@
                 nfDialog.glasspane = glasspane = 'transparent';
             }
 
-            //create glass pane overlay
-            var modalGlassMarkup = '<div data-nf-dialog-parent="' +
-                dialog.attr('id') + '" class="modal-glass" 
style="background-color: ' + glasspane + ';"></div>';
-
-            var modalGlass = $(modalGlassMarkup);
-
-            modalGlass.css('z-index', zIndex - 1).appendTo($('body'));
+            if (!$('body').find("[data-nf-dialog-parent='" + dialog.attr('id') 
+ "']").is(':visible')) {
+                //create glass pane overlay
+                $('<div></div>').attr('data-nf-dialog-parent', 
dialog.attr('id')).addClass("modal-glass").css({
+                    "background-color": glasspane,
+                    "z-index": zIndex - 1
+                }).appendTo($('body'));
+            }
 
             //persist data attribute
             dialog.data('nfDialog', nfDialog);

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
index 9a67688..17d40d8 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
@@ -233,6 +233,13 @@ nf.StatusHistory = (function () {
                 }
             }
         });
+
+        $('#status-history-dialog').modal('show');
+    };
+
+    var getChartMinHeight = function () {
+        return $('#status-history-chart-container').parent().outerHeight() - 
$('#status-history-chart-control-container').outerHeight() -
+            
parseInt($('#status-history-chart-control-container').css('margin-top'), 10);
     };
 
     var getChartMaxHeight = function () {
@@ -252,748 +259,698 @@ nf.StatusHistory = (function () {
      * Updates the chart with the specified status history and the selected 
field.
      */
     var updateChart = function () {
-        var statusHistory = $('#status-history-dialog').data('status-history');
 
-        // get the selected descriptor
-        var selectedDescriptor = statusHistory.selectedDescriptor;
+        var statusHistoryDialog = $('#status-history-dialog');
 
-        // remove current details
-        $('#status-history-details').empty();
+        if (statusHistoryDialog.is(':visible')) {
+            var statusHistory = statusHistoryDialog.data('status-history');
 
-        // add status history details
-        var detailsContainer = buildDetailsContainer('Status History');
-        d3.map(statusHistory.details).forEach(function (label, value) {
-            addDetailItem(detailsContainer, label, value);
-        });
+            // get the selected descriptor
+            var selectedDescriptor = statusHistory.selectedDescriptor;
 
-        var margin = {
-            top: 15,
-            right: 20,
-            bottom: 25,
-            left: 75
-        };
+            // remove current details
+            $('#status-history-details').empty();
 
-        // -------------
-        // prep the data
-        // -------------
+            // add status history details
+            var detailsContainer = buildDetailsContainer('Status History');
+            d3.map(statusHistory.details).forEach(function (label, value) {
+                addDetailItem(detailsContainer, label, value);
+            });
 
-        // available colors
-        var color = d3.scale.category10();
+            var margin = {
+                top: 15,
+                right: 20,
+                bottom: 25,
+                left: 75
+            };
 
-        // determine the available instances
-        var instanceLabels = [];
-        $.each(statusHistory.instances, function (_, instance) {
-            instanceLabels.push(instance.label);
-        });
+            // -------------
+            // prep the data
+            // -------------
 
-        // specify the domain based on the detected instances
-        color.domain(instanceLabels);
+            // available colors
+            var color = d3.scale.category10();
 
-        // data for the chart
-        var statusData = [];
+            // determine the available instances
+            var instanceLabels = [];
+            $.each(statusHistory.instances, function (_, instance) {
+                instanceLabels.push(instance.label);
+            });
 
-        // go through each instance of this status history
-        $.each(statusHistory.instances, function (_, instance) {
-            // if this is the first time this instance is being rendered, make 
it visible
-            if (nf.Common.isUndefinedOrNull(instances[instance.id])) {
-                instances[instance.id] = true;
-            }
+            // specify the domain based on the detected instances
+            color.domain(instanceLabels);
+
+            // data for the chart
+            var statusData = [];
+
+            // go through each instance of this status history
+            $.each(statusHistory.instances, function (_, instance) {
+                // if this is the first time this instance is being rendered, 
make it visible
+                if (nf.Common.isUndefinedOrNull(instances[instance.id])) {
+                    instances[instance.id] = true;
+                }
 
-            // and convert the model
-            statusData.push({
-                id: instance.id,
-                label: instance.label,
-                values: $.map(instance.snapshots, function (d) {
-                    return {
-                        timestamp: d.timestamp,
-                        value: d.statusMetrics[selectedDescriptor.field]
-                    };
-                }),
-                visible: instances[instance.id] === true
+                // and convert the model
+                statusData.push({
+                    id: instance.id,
+                    label: instance.label,
+                    values: $.map(instance.snapshots, function (d) {
+                        return {
+                            timestamp: d.timestamp,
+                            value: d.statusMetrics[selectedDescriptor.field]
+                        };
+                    }),
+                    visible: instances[instance.id] === true
+                });
             });
-        });
 
-        // --------------------------
-        // custom time axis formatter
-        // --------------------------
-
-        var customTimeFormat = d3.time.format.multi([
-            [':%S.%L', function (d) {
-                return d.getMilliseconds();
-            }],
-            [':%S', function (d) {
-                return d.getSeconds();
-            }],
-            ['%H:%M', function (d) {
-                return d.getMinutes();
-            }],
-            ['%H:%M', function (d) {
-                return d.getHours();
-            }],
-            ['%a %d', function (d) {
-                return d.getDay() && d.getDate() !== 1;
-            }],
-            ['%b %d', function (d) {
-                return d.getDate() !== 1;
-            }],
-            ['%B', function (d) {
-                return d.getMonth();
-            }],
-            ['%Y', function () {
-                return true;
-            }]
-        ]);
-
-        // ----------
-        // main chart
-        // ----------
+            // --------------------------
+            // custom time axis formatter
+            // --------------------------
 
-        var statusHistoryDialog = $('#status-history-dialog');
+            var customTimeFormat = d3.time.format.multi([
+                [':%S.%L', function (d) {
+                    return d.getMilliseconds();
+                }],
+                [':%S', function (d) {
+                    return d.getSeconds();
+                }],
+                ['%H:%M', function (d) {
+                    return d.getMinutes();
+                }],
+                ['%H:%M', function (d) {
+                    return d.getHours();
+                }],
+                ['%a %d', function (d) {
+                    return d.getDay() && d.getDate() !== 1;
+                }],
+                ['%b %d', function (d) {
+                    return d.getDate() !== 1;
+                }],
+                ['%B', function (d) {
+                    return d.getMonth();
+                }],
+                ['%Y', function () {
+                    return true;
+                }]
+            ]);
+
+            // ----------
+            // main chart
+            // ----------
+
+            // the container for the main chart
+            var chartContainer = $('#status-history-chart-container').empty();
+            if (chartContainer.hasClass('ui-resizable')) {
+                chartContainer.resizable('destroy');
+                chartContainer.removeAttr( "style" );
+            }
 
-        // show/center the dialog if necessary
-        if (!statusHistoryDialog.is(':visible')) {
-            statusHistoryDialog.modal('show');
-        }
+            // calculate the dimensions
+            chartContainer.height(getChartMinHeight());
 
-        // the container for the main chart
-        var chartContainer = $('#status-history-chart-container').empty();
-        if (chartContainer.hasClass('ui-resizable')) {
-            chartContainer.resizable('destroy');
-        }
+            // determine the new width/height
+            var width = chartContainer.outerWidth() - margin.left - 
margin.right;
+            var height = chartContainer.outerHeight() - margin.top - 
margin.bottom;
 
-        // calculate the dimensions
-        var width = chartContainer.parent().outerWidth() - margin.left - 
margin.right;
-        var height = chartContainer.outerHeight() - margin.top - margin.bottom;
+            maxWidth = $('#status-history-container').width();
+            if (width > maxWidth) {
+                width = maxWidth;
+            }
 
-        maxWidth = getChartMaxWidth();
-        if (width > maxWidth) {
-            width = maxWidth;
-        }
+            maxHeight = getChartMaxHeight();
+            if (height > maxHeight) {
+                height = maxHeight;
+            }
 
-        maxHeight = getChartMaxHeight();
-        if (height > maxHeight) {
-            height = maxHeight;
-        }
+            // define the x axis for the main chart
+            var x = d3.time.scale()
+                .range([0, width]);
 
-        // define the x axis for the main chart
-        var x = d3.time.scale()
-            .range([0, width]);
-
-        var xAxis = d3.svg.axis()
-            .scale(x)
-            .ticks(5)
-            .tickFormat(customTimeFormat)
-            .orient('bottom');
-
-        // define the y axis
-        var y = d3.scale.linear()
-            .range([height, 0]);
-
-        var yAxis = d3.svg.axis()
-            .scale(y)
-            .tickFormat(formatters[selectedDescriptor.formatter])
-            .orient('left');
-
-        // status line
-        var line = d3.svg.line()
-            .interpolate('monotone')
-            .x(function (d) {
-                return x(d.timestamp);
-            })
-            .y(function (d) {
-                return y(d.value);
-            });
+            var xAxis = d3.svg.axis()
+                .scale(x)
+                .ticks(5)
+                .tickFormat(customTimeFormat)
+                .orient('bottom');
 
-        // build the chart svg
-        var chartSvg = 
d3.select('#status-history-chart-container').append('svg')
-            .attr('style', 'pointer-events: none;')
-            .attr('width', chartContainer.parent().width())
-            .attr('height', chartContainer.innerHeight());
-        // define a clip the path
-        var clipPath = chartSvg.append('defs').append('clipPath')
-            .attr('id', 'clip')
-            .append('rect')
-            .attr('width', width)
-            .attr('height', height);
-
-        // build the chart
-        var chart = chartSvg.append('g')
-            .attr('transform', 'translate(' + margin.left + ', ' + margin.top 
+ ')');
-
-        // determine the min/max date
-        var minDate = d3.min(statusData, function (d) {
-            return d3.min(d.values, function (s) {
-                return s.timestamp;
-            });
-        });
-        var maxDate = d3.max(statusData, function (d) {
-            return d3.max(d.values, function (s) {
-                return s.timestamp;
-            });
-        });
-        addDetailItem(detailsContainer, 'Start', 
nf.Common.formatDateTime(minDate));
-        addDetailItem(detailsContainer, 'End', 
nf.Common.formatDateTime(maxDate));
-
-        // determine the x axis range
-        x.domain([minDate, maxDate]);
-
-        // determine the y axis range
-        y.domain([getMinValue(statusData), getMaxValue(statusData)]);
-
-        // build the x axis
-        chart.append('g')
-            .attr('class', 'x axis')
-            .attr('transform', 'translate(0, ' + height + ')')
-            .call(xAxis);
-
-        // build the y axis
-        chart.append('g')
-            .attr('class', 'y axis')
-            .call(yAxis)
-            .append('text')
-            .attr('transform', 'rotate(-90)')
-            .attr('y', 6)
-            .attr('dy', '.71em')
-            .attr('text-anchor', 'end')
-            .text(selectedDescriptor.label);
-
-        // build the chart
-        var status = chart.selectAll('.status')
-            .data(statusData)
-            .enter()
-            .append('g')
-            .attr('clip-path', 'url(#clip)')
-            .attr('class', 'status');
-
-        // draw the lines
-        status.append('path')
-            .attr('class', function (d) {
-                return 'chart-line chart-line-' + d.id;
-            })
-            .attr('d', function (d) {
-                return line(d.values);
-            })
-            .attr('stroke', function (d) {
-                return color(d.label);
-            })
-            .classed('hidden', function (d) {
-                return d.visible === false;
-            })
-            .append('title')
-            .text(function (d) {
-                return d.label;
-            });
+            // define the y axis
+            var y = d3.scale.linear()
+                .range([height, 0]);
+
+            var yAxis = d3.svg.axis()
+                .scale(y)
+                .tickFormat(formatters[selectedDescriptor.formatter])
+                .orient('left');
 
-        // draw the control points for each line
-        status.each(function (d) {
-            // create a group for the control points
-            var markGroup = d3.select(this).append('g')
-                .attr('class', function () {
-                    return 'mark-group mark-group-' + d.id;
+
+            // status line
+            var line = d3.svg.line()
+                .interpolate('monotone')
+                .x(function (d) {
+                    return x(d.timestamp);
                 })
-                .classed('hidden', function (d) {
-                    return d.visible === false;
+                .y(function (d) {
+                    return y(d.value);
                 });
 
-            // draw the control points
-            markGroup.selectAll('circle.mark')
-                .data(d.values)
+            // build the chart svg
+            var chartSvg = 
d3.select('#status-history-chart-container').append('svg')
+                .attr('style', 'pointer-events: none;')
+                .attr('width', chartContainer.parent().width())
+                .attr('height', chartContainer.innerHeight());
+            // define a clip the path
+            var clipPath = chartSvg.append('defs').append('clipPath')
+                .attr('id', 'clip')
+                .append('rect')
+                .attr('width', width)
+                .attr('height', height);
+
+            // build the chart
+            var chart = chartSvg.append('g')
+                .attr('transform', 'translate(' + margin.left + ', ' + 
margin.top + ')');
+
+            // determine the min/max date
+            var minDate = d3.min(statusData, function (d) {
+                return d3.min(d.values, function (s) {
+                    return s.timestamp;
+                });
+            });
+            var maxDate = d3.max(statusData, function (d) {
+                return d3.max(d.values, function (s) {
+                    return s.timestamp;
+                });
+            });
+            addDetailItem(detailsContainer, 'Start', 
nf.Common.formatDateTime(minDate));
+            addDetailItem(detailsContainer, 'End', 
nf.Common.formatDateTime(maxDate));
+
+            // determine the x axis range
+            x.domain([minDate, maxDate]);
+
+            // determine the y axis range
+            y.domain([getMinValue(statusData), getMaxValue(statusData)]);
+
+            // build the x axis
+            chart.append('g')
+                .attr('class', 'x axis')
+                .attr('transform', 'translate(0, ' + height + ')')
+                .call(xAxis);
+
+            // build the y axis
+            chart.append('g')
+                .attr('class', 'y axis')
+                .call(yAxis)
+                .append('text')
+                .attr('transform', 'rotate(-90)')
+                .attr('y', 6)
+                .attr('dy', '.71em')
+                .attr('text-anchor', 'end')
+                .text(selectedDescriptor.label);
+
+            // build the chart
+            var status = chart.selectAll('.status')
+                .data(statusData)
                 .enter()
-                .append('circle')
-                .attr('style', 'pointer-events: all;')
-                .attr('class', 'mark')
-                .attr('cx', function (v) {
-                    return x(v.timestamp);
+                .append('g')
+                .attr('clip-path', 'url(#clip)')
+                .attr('class', 'status');
+
+            // draw the lines
+            status.append('path')
+                .attr('class', function (d) {
+                    return 'chart-line chart-line-' + d.id;
                 })
-                .attr('cy', function (v) {
-                    return y(v.value);
+                .attr('d', function (d) {
+                    return line(d.values);
                 })
-                .attr('fill', function () {
+                .attr('stroke', function (d) {
                     return color(d.label);
                 })
-                .attr('r', 1.5)
+                .classed('hidden', function (d) {
+                    return d.visible === false;
+                })
                 .append('title')
-                .text(function (v) {
-                    return d.label + ' -- ' + 
formatters[selectedDescriptor.formatter](v.value);
+                .text(function (d) {
+                    return d.label;
                 });
-        });
-
-        // -------------
-        // control chart
-        // -------------
-
-        // the container for the main chart control
-        var chartControlContainer = 
$('#status-history-chart-control-container').empty();
-        var controlHeight = chartControlContainer.innerHeight() - margin.top - 
margin.bottom;
-
-        var xControl = d3.time.scale()
-            .range([0, width]);
-
-        var xControlAxis = d3.svg.axis()
-            .scale(xControl)
-            .ticks(5)
-            .tickFormat(customTimeFormat)
-            .orient('bottom');
-
-        var yControl = d3.scale.linear()
-            .range([controlHeight, 0]);
-
-        var yControlAxis = d3.svg.axis()
-            .scale(yControl)
-            .tickValues(y.domain())
-            .tickFormat(formatters[selectedDescriptor.formatter])
-            .orient('left');
-
-        // status line
-        var controlLine = d3.svg.line()
-            .interpolate('monotone')
-            .x(function (d) {
-                return xControl(d.timestamp);
-            })
-            .y(function (d) {
-                return yControl(d.value);
-            });
 
-        // build the svg
-        var controlChartSvg = 
d3.select('#status-history-chart-control-container').append('svg')
-            .attr('width', chartContainer.parent().width())
-            .attr('height', controlHeight + margin.top + margin.bottom);
-
-        // build the control chart
-        var control = controlChartSvg.append('g')
-            .attr('transform', 'translate(' + margin.left + ', ' + margin.top 
+ ')');
-
-        // increase the y domain slightly
-        var yControlDomain = y.domain();
-        yControlDomain[1] *= 1.04;
-
-        // define the domain for the control chart
-        xControl.domain(x.domain());
-        yControl.domain(yControlDomain);
-
-        // build the control x axis
-        control.append('g')
-            .attr('class', 'x axis')
-            .attr('transform', 'translate(0, ' + controlHeight + ')')
-            .call(xControlAxis);
-
-        // build the control y axis
-        control.append('g')
-            .attr('class', 'y axis')
-            .call(yControlAxis);
-
-        // build the control chart
-        var controlStatus = control.selectAll('.status')
-            .data(statusData)
-            .enter()
-            .append('g')
-            .attr('class', 'status');
-
-        // draw the lines
-        controlStatus.append('path')
-            .attr('class', function (d) {
-                return 'chart-line chart-line-' + d.id;
-            })
-            .attr('d', function (d) {
-                return controlLine(d.values);
-            })
-            .attr('stroke', function (d) {
-                return color(d.label);
-            })
-            .classed('hidden', function (d) {
-                return instances[d.id] === false;
-            })
-            .append('title')
-            .text(function (d) {
-                return d.label;
+            // draw the control points for each line
+            status.each(function (d) {
+                // create a group for the control points
+                var markGroup = d3.select(this).append('g')
+                    .attr('class', function () {
+                        return 'mark-group mark-group-' + d.id;
+                    })
+                    .classed('hidden', function (d) {
+                        return d.visible === false;
+                    });
+
+                // draw the control points
+                markGroup.selectAll('circle.mark')
+                    .data(d.values)
+                    .enter()
+                    .append('circle')
+                    .attr('style', 'pointer-events: all;')
+                    .attr('class', 'mark')
+                    .attr('cx', function (v) {
+                        return x(v.timestamp);
+                    })
+                    .attr('cy', function (v) {
+                        return y(v.value);
+                    })
+                    .attr('fill', function () {
+                        return color(d.label);
+                    })
+                    .attr('r', 1.5)
+                    .append('title')
+                    .text(function (v) {
+                        return d.label + ' -- ' + 
formatters[selectedDescriptor.formatter](v.value);
+                    });
             });
 
-        // -------------------
-        // configure the brush
-        // -------------------
+            // update the size of the chart
+            chartSvg.attr('width', chartContainer.parent().width())
+                .attr('height', chartContainer.innerHeight());
 
-        /**
-         * Updates the axis for the main chart.
-         *
-         * @param {array} xDomain   The new domain for the x axis
-         * @param {array} yDomain   The new domain for the y axis
-         */
-        var updateAxes = function (xDomain, yDomain) {
-            // update the domain of the main chart
-            x.domain(xDomain);
-            y.domain(yDomain);
+            // update the size of the clipper
+            clipPath.attr('width', width)
+                .attr('height', height);
 
-            // update the chart lines
-            status.selectAll('.chart-line')
-                .attr('d', function (d) {
-                    return line(d.values);
-                });
-            status.selectAll('circle.mark')
-                .attr('cx', function (v) {
-                    return x(v.timestamp);
-                })
-                .attr('cy', function (v) {
-                    return y(v.value);
-                })
-                .attr('r', function () {
-                    return brush.empty() ? 1.5 : 4;
-                });
+            // update the position of the x axis
+            chart.select('.x.axis').attr('transform', 'translate(0, ' + height 
+ ')');
 
-            // update the x axis
-            chart.select('.x.axis').call(xAxis);
-            chart.select('.y.axis').call(yAxis);
-        };
+            // -------------
+            // control chart
+            // -------------
 
-        /**
-         * Handles brush events by updating the main chart according to the 
context window
-         * or the control domain if there is no context window.
-         */
-        var brushed = function () {
-            // determine the new x and y domains
-            var xContextDomain, yContextDomain;
-            if (brush.empty()) {
-                // get the all visible instances
-                var visibleInstances = $.grep(statusData, function (d) {
-                    return d.visible;
-                });
+            // the container for the main chart control
+            var chartControlContainer = 
$('#status-history-chart-control-container').empty();
+            var controlHeight = chartControlContainer.innerHeight() - 
margin.top - margin.bottom;
 
-                // determine the appropriate y domain
-                if (visibleInstances.length === 0) {
-                    yContextDomain = yControl.domain();
-                } else {
-                    yContextDomain = [
-                        d3.min(visibleInstances, function (d) {
-                            return d3.min(d.values, function (s) {
-                                return s.value;
-                            });
-                        }),
-                        d3.max(visibleInstances, function (d) {
-                            return d3.max(d.values, function (s) {
-                                return s.value;
-                            });
-                        })
-                    ];
-                }
-                xContextDomain = xControl.domain();
+            var xControl = d3.time.scale()
+                .range([0, width]);
 
-                // clear the current extent
-                brushExtent = null;
-            } else {
-                var extent = brush.extent();
-                xContextDomain = [extent[0][0], extent[1][0]];
-                yContextDomain = [extent[0][1], extent[1][1]];
+            var xControlAxis = d3.svg.axis()
+                .scale(xControl)
+                .ticks(5)
+                .tickFormat(customTimeFormat)
+                .orient('bottom');
 
-                // hold onto the current brush
-                brushExtent = extent;
-            }
+            var yControl = d3.scale.linear()
+                .range([controlHeight, 0]);
 
-            // update the axes accordingly
-            updateAxes(xContextDomain, yContextDomain);
+            var yControlAxis = d3.svg.axis()
+                .scale(yControl)
+                .tickValues(y.domain())
+                .tickFormat(formatters[selectedDescriptor.formatter])
+                .orient('left');
 
-            // update the aggregate statistics according to the new domain
-            updateAggregateStatistics();
-        };
-
-        // build the brush
-        var brush = d3.svg.brush()
-            .x(xControl)
-            .y(yControl)
-            .on('brush', brushed);
+            // status line
+            var controlLine = d3.svg.line()
+                .interpolate('monotone')
+                .x(function (d) {
+                    return xControl(d.timestamp);
+                })
+                .y(function (d) {
+                    return yControl(d.value);
+                });
 
-        // conditionally set the brush extent
-        if (nf.Common.isDefinedAndNotNull(brushExtent)) {
-            brush = brush.extent(brushExtent);
-        }
+            // build the svg
+            var controlChartSvg = 
d3.select('#status-history-chart-control-container').append('svg')
+                .attr('width', chartContainer.parent().width())
+                .attr('height', controlHeight + margin.top + margin.bottom);
+
+            // build the control chart
+            var control = controlChartSvg.append('g')
+                .attr('transform', 'translate(' + margin.left + ', ' + 
margin.top + ')');
+
+            // increase the y domain slightly
+            var yControlDomain = y.domain();
+            yControlDomain[1] *= 1.04;
+
+            // define the domain for the control chart
+            xControl.domain(x.domain());
+            yControl.domain(yControlDomain);
+
+            // build the control x axis
+            control.append('g')
+                .attr('class', 'x axis')
+                .attr('transform', 'translate(0, ' + controlHeight + ')')
+                .call(xControlAxis);
+
+            // build the control y axis
+            control.append('g')
+                .attr('class', 'y axis')
+                .call(yControlAxis);
+
+            // build the control chart
+            var controlStatus = control.selectAll('.status')
+                .data(statusData)
+                .enter()
+                .append('g')
+                .attr('class', 'status');
 
-        // context area
-        control.append('g')
-            .attr('class', 'brush')
-            .call(brush);
-
-        // add expansion to the extent
-        control.select('rect.extent')
-            .attr('style', 'pointer-events: all;')
-            .on('dblclick', function () {
-                if (!brush.empty()) {
-                    // get the current extent to get the x range
-                    var extent = brush.extent();
+            // draw the lines
+            controlStatus.append('path')
+                .attr('class', function (d) {
+                    return 'chart-line chart-line-' + d.id;
+                })
+                .attr('d', function (d) {
+                    return controlLine(d.values);
+                })
+                .attr('stroke', function (d) {
+                    return color(d.label);
+                })
+                .classed('hidden', function (d) {
+                    return instances[d.id] === false;
+                })
+                .append('title')
+                .text(function (d) {
+                    return d.label;
+                });
 
-                    // get the y range (this value does not change from the 
original y domain)
-                    var yRange = yControl.domain();
+            // -------------------
+            // configure the brush
+            // -------------------
+
+            /**
+             * Updates the axis for the main chart.
+             *
+             * @param {array} xDomain   The new domain for the x axis
+             * @param {array} yDomain   The new domain for the y axis
+             */
+            var updateAxes = function (xDomain, yDomain) {
+                // update the domain of the main chart
+                x.domain(xDomain);
+                y.domain(yDomain);
 
-                    // expand the extent vertically
-                    brush.extent([[extent[0][0], yRange[0]], [extent[1][0], 
yRange[1]]]);
+                // update the chart lines
+                status.selectAll('.chart-line')
+                    .attr('d', function (d) {
+                        return line(d.values);
+                    });
+                status.selectAll('circle.mark')
+                    .attr('cx', function (v) {
+                        return x(v.timestamp);
+                    })
+                    .attr('cy', function (v) {
+                        return y(v.value);
+                    })
+                    .attr('r', function () {
+                        return brush.empty() ? 1.5 : 4;
+                    });
+
+                // update the x axis
+                chart.select('.x.axis').call(xAxis);
+                chart.select('.y.axis').call(yAxis);
+            };
+
+            /**
+             * Handles brush events by updating the main chart according to 
the context window
+             * or the control domain if there is no context window.
+             */
+            var brushed = function () {
+                // determine the new x and y domains
+                var xContextDomain, yContextDomain;
+                if (brush.empty()) {
+                    // get the all visible instances
+                    var visibleInstances = $.grep(statusData, function (d) {
+                        return d.visible;
+                    });
+
+                    // determine the appropriate y domain
+                    if (visibleInstances.length === 0) {
+                        yContextDomain = yControl.domain();
+                    } else {
+                        yContextDomain = [
+                            d3.min(visibleInstances, function (d) {
+                                return d3.min(d.values, function (s) {
+                                    return s.value;
+                                });
+                            }),
+                            d3.max(visibleInstances, function (d) {
+                                return d3.max(d.values, function (s) {
+                                    return s.value;
+                                });
+                            })
+                        ];
+                    }
+                    xContextDomain = xControl.domain();
 
-                    // update the brush control
-                    control.select('.brush').call(brush);
+                    // clear the current extent
+                    brushExtent = null;
+                } else {
+                    var extent = brush.extent();
+                    xContextDomain = [extent[0][0], extent[1][0]];
+                    yContextDomain = [extent[0][1], extent[1][1]];
 
-                    // run the brush to update the axes of the main chart
-                    brushed();
+                    // hold onto the current brush
+                    brushExtent = extent;
                 }
-            });
 
-        // --------------------
-        // aggregate statistics
-        // --------------------
+                // update the axes accordingly
+                updateAxes(xContextDomain, yContextDomain);
 
-        var updateAggregateStatistics = function () {
-            // locate the instances that have data points within the current 
brush
-            var withinBrush = $.map(statusData, function (d) {
-                var xDomain = x.domain();
-                var yDomain = y.domain();
+                // update the aggregate statistics according to the new domain
+                updateAggregateStatistics();
+            };
 
-                // copy to avoid modifying the original
-                var copy = $.extend({}, d);
+            // build the brush
+            var brush = d3.svg.brush()
+                .x(xControl)
+                .y(yControl)
+                .on('brush', brushed);
 
-                // update the copy to only include values within the brush
-                return $.extend(copy, {
-                    values: $.grep(d.values, function (s) {
-                        return s.timestamp.getTime() >= xDomain[0].getTime() 
&& s.timestamp.getTime() <= xDomain[1].getTime() && s.value >= yDomain[0] && 
s.value <= yDomain[1];
-                    })
-                });
-            });
+            // conditionally set the brush extent
+            if (nf.Common.isDefinedAndNotNull(brushExtent)) {
+                brush = brush.extent(brushExtent);
+            }
 
-            // consider visible nodes with data in the brush
-            var nodes = $.grep(withinBrush, function (d) {
-                return d.id !== config.nifiInstanceId && d.visible && 
d.values.length > 0;
-            });
+            // context area
+            control.append('g')
+                .attr('class', 'brush')
+                .call(brush);
 
-            var nodeMinValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMinValue(nodes));
-            var nodeMeanValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMeanValue(nodes));
-            var nodeMaxValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMaxValue(nodes));
+            // add expansion to the extent
+            control.select('rect.extent')
+                .attr('style', 'pointer-events: all;')
+                .on('dblclick', function () {
+                    if (!brush.empty()) {
+                        // get the current extent to get the x range
+                        var extent = brush.extent();
 
-            // update the currently displayed min/max/mean
-            $('#node-aggregate-statistics').text(nodeMinValue + ' / ' + 
nodeMaxValue + ' / ' + nodeMeanValue);
+                        // get the y range (this value does not change from 
the original y domain)
+                        var yRange = yControl.domain();
 
-            // only consider the cluster with data in the brush
-            var cluster = $.grep(withinBrush, function (d) {
-                return d.id === config.nifiInstanceId && d.visible && 
d.values.length > 0;
-            });
+                        // expand the extent vertically
+                        brush.extent([[extent[0][0], yRange[0]], 
[extent[1][0], yRange[1]]]);
 
-            // determine the cluster values
-            var clusterMinValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMinValue(cluster));
-            var clusterMeanValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMeanValue(cluster));
-            var clusterMaxValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMaxValue(cluster));
+                        // update the brush control
+                        control.select('.brush').call(brush);
 
-            // update the cluster min/max/mean
-            $('#cluster-aggregate-statistics').text(clusterMinValue + ' / ' + 
clusterMaxValue + ' / ' + clusterMeanValue);
-        };
+                        // run the brush to update the axes of the main chart
+                        brushed();
+                    }
+                });
 
-        // ----------------
-        // build the legend
-        // ----------------
+            // --------------------
+            // aggregate statistics
+            // --------------------
 
-        // identify all nodes and sort
-        var nodes = $.grep(statusData, function (status) {
-            return status.id !== config.nifiInstanceId;
-        }).sort(function (a, b) {
-            return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
-        });
+            var updateAggregateStatistics = function () {
+                // locate the instances that have data points within the 
current brush
+                var withinBrush = $.map(statusData, function (d) {
+                    var xDomain = x.domain();
+                    var yDomain = y.domain();
+
+                    // copy to avoid modifying the original
+                    var copy = $.extend({}, d);
 
-        // adds a legend entry for the specified instance
-        var addLegendEntry = function (legend, instance) {
-            // create the label and the checkbox
-            var instanceLabelElement = 
$('<div></div>').addClass('legend-label').css('color', 
color(instance.label)).text(instance.label).ellipsis();
-            var instanceCheckboxElement = $('<div 
class="nf-checkbox"></div>').on('click', function () {
-                // get the line and the control points for this instance 
(select all for the line to update control and main charts)
-                var chartLine = d3.selectAll('path.chart-line-' + instance.id);
-                var markGroup = d3.select('g.mark-group-' + instance.id);
-
-                // determine if it was hidden
-                var isHidden = markGroup.classed('hidden');
-
-                // toggle the visibility
-                chartLine.classed('hidden', function () {
-                    return !isHidden;
+                    // update the copy to only include values within the brush
+                    return $.extend(copy, {
+                        values: $.grep(d.values, function (s) {
+                            return s.timestamp.getTime() >= 
xDomain[0].getTime() && s.timestamp.getTime() <= xDomain[1].getTime() && 
s.value >= yDomain[0] && s.value <= yDomain[1];
+                        })
+                    });
                 });
-                markGroup.classed('hidden', function () {
-                    return !isHidden;
+
+                // consider visible nodes with data in the brush
+                var nodes = $.grep(withinBrush, function (d) {
+                    return d.id !== config.nifiInstanceId && d.visible && 
d.values.length > 0;
                 });
 
-                // update whether its visible
-                instance.visible = isHidden;
+                var nodeMinValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMinValue(nodes));
+                var nodeMeanValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMeanValue(nodes));
+                var nodeMaxValue = nodes.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMaxValue(nodes));
 
-                // record the current status so it persists across refreshes
-                instances[instance.id] = instance.visible;
+                // update the currently displayed min/max/mean
+                $('#node-aggregate-statistics').text(nodeMinValue + ' / ' + 
nodeMaxValue + ' / ' + nodeMeanValue);
 
-                // update the brush
-                brushed();
-            }).addClass(instance.visible ? 'checkbox-checked' : 
'checkbox-unchecked');
+                // only consider the cluster with data in the brush
+                var cluster = $.grep(withinBrush, function (d) {
+                    return d.id === config.nifiInstanceId && d.visible && 
d.values.length > 0;
+                });
 
-            // add the legend entry
-            $('<div 
class="legend-entry"></div>').append(instanceCheckboxElement).append(instanceLabelElement).on('mouseenter',
 function () {
-                d3.selectAll('path.chart-line-' + instance.id).classed('over', 
true);
-            }).on('mouseleave', function () {
-                d3.selectAll('path.chart-line-' + instance.id).classed('over', 
false);
-            }).appendTo(legend);
-        };
+                // determine the cluster values
+                var clusterMinValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMinValue(cluster));
+                var clusterMeanValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMeanValue(cluster));
+                var clusterMaxValue = cluster.length === 0 ? 'NA' : 
formatters[selectedDescriptor.formatter](getMaxValue(cluster));
 
-        // get the cluster instance
-        var cluster = $.grep(statusData, function (status) {
-            return status.id === config.nifiInstanceId;
-        });
+                // update the cluster min/max/mean
+                $('#cluster-aggregate-statistics').text(clusterMinValue + ' / 
' + clusterMaxValue + ' / ' + clusterMeanValue);
+            };
 
-        // build the cluster container
-        var clusterDetailsContainer = buildDetailsContainer('NiFi');
+            // ----------------
+            // build the legend
+            // ----------------
 
-        // add the total cluster values
-        addDetailItem(clusterDetailsContainer, 'Min / Max / Mean', '', 
'cluster-aggregate-statistics');
+            // identify all nodes and sort
+            var nodes = $.grep(statusData, function (status) {
+                return status.id !== config.nifiInstanceId;
+            }).sort(function (a, b) {
+                return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
+            });
 
-        // build the cluster legend
-        addLegendEntry(clusterDetailsContainer, cluster[0]);
+            // adds a legend entry for the specified instance
+            var addLegendEntry = function (legend, instance) {
+                // create the label and the checkbox
+                var instanceLabelElement = 
$('<div></div>').addClass('legend-label').css('color', 
color(instance.label)).text(instance.label).ellipsis();
+                var instanceCheckboxElement = $('<div 
class="nf-checkbox"></div>').on('click', function () {
+                    // get the line and the control points for this instance 
(select all for the line to update control and main charts)
+                    var chartLine = d3.selectAll('path.chart-line-' + 
instance.id);
+                    var markGroup = d3.select('g.mark-group-' + instance.id);
+
+                    // determine if it was hidden
+                    var isHidden = markGroup.classed('hidden');
+
+                    // toggle the visibility
+                    chartLine.classed('hidden', function () {
+                        return !isHidden;
+                    });
+                    markGroup.classed('hidden', function () {
+                        return !isHidden;
+                    });
+
+                    // update whether its visible
+                    instance.visible = isHidden;
+
+                    // record the current status so it persists across 
refreshes
+                    instances[instance.id] = instance.visible;
+
+                    // update the brush
+                    brushed();
+                }).addClass(instance.visible ? 'checkbox-checked' : 
'checkbox-unchecked');
+
+                // add the legend entry
+                $('<div 
class="legend-entry"></div>').append(instanceCheckboxElement).append(instanceLabelElement).on('mouseenter',
 function () {
+                    d3.selectAll('path.chart-line-' + 
instance.id).classed('over', true);
+                }).on('mouseleave', function () {
+                    d3.selectAll('path.chart-line-' + 
instance.id).classed('over', false);
+                }).appendTo(legend);
+            };
+
+            // get the cluster instance
+            var cluster = $.grep(statusData, function (status) {
+                return status.id === config.nifiInstanceId;
+            });
 
-        // if there are entries to render
-        if (nodes.length > 0) {
             // build the cluster container
-            var nodeDetailsContainer = buildDetailsContainer('Nodes');
+            var clusterDetailsContainer = buildDetailsContainer('NiFi');
 
             // add the total cluster values
-            addDetailItem(nodeDetailsContainer, 'Min / Max / Mean', '', 
'node-aggregate-statistics');
+            addDetailItem(clusterDetailsContainer, 'Min / Max / Mean', '', 
'cluster-aggregate-statistics');
 
-            // add each legend entry
-            $.each(nodes, function (_, instance) {
-                addLegendEntry(nodeDetailsContainer, instance);
-            });
-        }
+            // build the cluster legend
+            addLegendEntry(clusterDetailsContainer, cluster[0]);
 
-        // update the brush
-        brushed();
+            // if there are entries to render
+            if (nodes.length > 0) {
+                // build the cluster container
+                var nodeDetailsContainer = buildDetailsContainer('Nodes');
 
-        // ---------------
-        // handle resizing
-        // ---------------
+                // add the total cluster values
+                addDetailItem(nodeDetailsContainer, 'Min / Max / Mean', '', 
'node-aggregate-statistics');
 
-        var maxWidth, maxHeight, resizeExtent, dialog;
-        chartContainer.append('<div class="ui-resizable-handle 
ui-resizable-se"></div>').resizable({
-            minWidth: 425,
-            minHeight: 150,
-            handles: {
-                'se': '.ui-resizable-se'
-            },
-            start: function (e, ui) {
-                // record the current extent so it can be reset on stop
-                if (!brush.empty()) {
-                    resizeExtent = brush.extent();
-                }
-            },
-            resize: function (e, ui) {
-                // -----------
-                // containment
-                // -----------
-                dialog = $('#status-history-dialog');
-                var nfDialog = {};
-                if (nf.Common.isDefinedAndNotNull(dialog.data('nf-dialog'))) {
-                    nfDialog = dialog.data('nf-dialog');
-                }
-                nfDialog['min-width'] = (dialog.width()/$(window).width())*100 
+ '%';
-                nfDialog['min-height'] = 
(dialog.height()/$(window).height())*100 + '%';
-                nfDialog.responsive['fullscreen-width'] = dialog.outerWidth() 
+ 'px';
-                nfDialog.responsive['fullscreen-height'] = 
dialog.outerHeight() + 'px';
-
-                maxWidth = getChartMaxWidth();
-                if (ui.helper.width() > maxWidth) {
-                    ui.helper.width(maxWidth);
-
-                    nfDialog.responsive['fullscreen-width'] = 
$(window).width() + 'px';
-                    nfDialog['min-width'] = '100%';
-                }
-
-                maxHeight = getChartMaxHeight();
-                if (ui.helper.height() > maxHeight) {
-                    ui.helper.height(maxHeight);
-
-                    nfDialog.responsive['fullscreen-height'] = 
$(window).height() + 'px';
-                    nfDialog['min-height'] = '100%';
-                }
-
-                nfDialog['min-width'] = (parseInt(nfDialog['min-width'], 10) 
>= 100) ? '100%': nfDialog['min-width'];
-                nfDialog['min-height'] = (parseInt(nfDialog['min-height'], 10) 
>= 100) ? '100%': nfDialog['min-height'];
-
-                //persist data attribute
-                dialog.data('nfDialog', nfDialog);
-
-                // ----------------------
-                // status history dialog
-                // ----------------------
-
-                dialog.css('min-width', (chartContainer.outerWidth() + 
$('#status-history-details').outerWidth() + 40));
-                dialog.css('min-height', (chartContainer.outerHeight() +
-                    $('#status-history-refresh-container').outerHeight() + 
$('#status-history-chart-control-container').outerHeight() +
-                    $('.dialog-buttons').outerHeight() + 
$('.dialog-header').outerHeight() + 40 + 5));
-
-                dialog.center();
-            },
-            stop: function () {
-
-                // ----------
-                // main chart
-                // ----------
-
-                // determine the new width/height
-                width = chartContainer.outerWidth() - margin.left - 
margin.right;
-                height = chartContainer.outerHeight() - margin.top - 
margin.bottom;
-
-                // update the range
-                x.range([0, width]);
-                y.range([height, 0]);
-
-                // update the size of the chart
-                chartSvg.attr('width', chartContainer.parent().width())
-                    .attr('height', chartContainer.innerHeight());
-
-                // update the size of the clipper
-                clipPath.attr('width', width)
-                    .attr('height', height);
-
-                // update the position of the x axis
-                chart.select('.x.axis').attr('transform', 'translate(0, ' + 
height + ')');
-
-                // -------------
-                // control chart
-                // -------------
+                // add each legend entry
+                $.each(nodes, function (_, instance) {
+                    addLegendEntry(nodeDetailsContainer, instance);
+                });
+            }
 
-                // determine the new width/height
-                controlHeight = chartControlContainer.height() - margin.top - 
margin.bottom;
+            // update the brush
+            brushed();
+
+            // ---------------
+            // handle resizing
+            // ---------------
+
+            var maxWidth, maxHeight, minHeight, resizeExtent, dialog;
+            chartContainer.append('<div class="ui-resizable-handle 
ui-resizable-se"></div>').resizable({
+                minWidth: 425,
+                minHeight: 150,
+                handles: {
+                    'se': '.ui-resizable-se'
+                },
+                start: function (e, ui) {
+                    // record the current extent so it can be reset on stop
+                    if (!brush.empty()) {
+                        resizeExtent = brush.extent();
+                    }
+                },
+                resize: function (e, ui) {
+                    // -----------
+                    // containment
+                    // -----------
+                    dialog = $('#status-history-dialog');
+                    var nfDialog = {};
+                    if 
(nf.Common.isDefinedAndNotNull(dialog.data('nf-dialog'))) {
+                        nfDialog = dialog.data('nf-dialog');
+                    }
+                    nfDialog['min-width'] = (dialog.width() / 
$(window).width()) * 100 + '%';
+                    nfDialog['min-height'] = (dialog.height() / 
$(window).height()) * 100 + '%';
+                    nfDialog.responsive['fullscreen-width'] = 
dialog.outerWidth() + 'px';
+                    nfDialog.responsive['fullscreen-height'] = 
dialog.outerHeight() + 'px';
 
-                // update the range
-                xControl.range([0, width]);
-                yControl.range([controlHeight, 0]);
+                    maxWidth = getChartMaxWidth();
+                    if (ui.helper.width() > maxWidth) {
+                        ui.helper.width(maxWidth);
 
-                // update the size of the control chart
-                controlChartSvg.attr('width', chartContainer.parent().width())
-                    .attr('height', controlHeight + margin.top + 
margin.bottom);
+                        nfDialog.responsive['fullscreen-width'] = 
$(window).width() + 'px';
+                        nfDialog['min-width'] = '100%';
+                    }
 
-                // update the chart lines
-                controlStatus.selectAll('.chart-line').attr('d', function (d) {
-                    return controlLine(d.values);
-                });
+                    maxHeight = getChartMaxHeight();
+                    if (ui.helper.height() > maxHeight) {
+                        ui.helper.height(maxHeight);
 
-                // update the axes
-                control.select('.x.axis').call(xControlAxis);
-                control.select('.y.axis').call(yControlAxis);
+                        nfDialog.responsive['fullscreen-height'] = 
$(window).height() + 'px';
+                        nfDialog['min-height'] = '100%';
+                    }
 
-                // restore the extent if necessary
-                if (nf.Common.isDefinedAndNotNull(resizeExtent)) {
-                    brush.extent(resizeExtent);
-                }
+                    minHeight = getChartMinHeight();
+                    if (ui.helper.height() < minHeight) {
+                        ui.helper.height(minHeight);
+                    }
 
-                // update the brush
-                control.select('.brush').call(brush);
+                    nfDialog['min-width'] = (parseInt(nfDialog['min-width'], 
10) >= 100) ? '100%' : nfDialog['min-width'];
+                    nfDialog['min-height'] = (parseInt(nfDialog['min-height'], 
10) >= 100) ? '100%' : nfDialog['min-height'];
 
-                // invoking the brush will trigger appropriate redrawing of 
the main chart
-                brushed();
+                    //persist data attribute
+                    dialog.data('nfDialog', nfDialog);
 
-                // reset the resize extent
-                resizeExtent = null;
+                    // ----------------------
+                    // status history dialog
+                    // ----------------------
 
-                // resize chart container
-                chartContainer.width(Math.round( 
chartContainer.parent().width()));
-                chartControlContainer.width(Math.round( 
chartContainer.parent().width()));
+                    dialog.css('min-width', (chartContainer.outerWidth() + 
$('#status-history-details').outerWidth() + 40));
+                    dialog.css('min-height', (chartContainer.outerHeight() +
+                    $('#status-history-refresh-container').outerHeight() + 
$('#status-history-chart-control-container').outerHeight() +
+                    $('.dialog-buttons').outerHeight() + 
$('.dialog-header').outerHeight() + 40 + 5));
 
-                // toggle scrollable style
-                
nf.Common.toggleScrollable(dialog.find('.dialog-content').get(0));
-            }
-        });
+                    dialog.center();
+                },
+                stop: updateChart
+            });
+        }
     };
 
     /**
@@ -1122,9 +1079,17 @@ nf.StatusHistory = (function () {
                         brushExtent = null;
                         descriptor = null;
                         instances = null;
-                    }
+                    },
+                    open: updateChart
                 }
             });
+
+            $(window).on('resize', function (e) {
+                if (e.target === window) {
+                    updateChart();
+                }
+                
nf.Common.toggleScrollable($('#status-history-details').get(0));
+            })
         },
 
         /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f60eac5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
index a43390a..33b8093 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
@@ -276,6 +276,7 @@ nf.SummaryTable = (function () {
                     break;
                 case 'disabled':
                     classes += ' icon icon-enable-false';
+                    break;
                 case 'invalid':
                     classes += ' fa fa-warning';
                     break;

Reply via email to