NIFI-2182:

- Ensuring the active thread count is shown.
NIFI-2019:
- Ensuring correct color of the run status in the From connection label.
NIFI-2183:
- Removing the DownloadSvg servlet and hidding the download icon until we're able to support save the svg entirely from the client side.

This closes #634.
This commit is contained in:
Matt Gilman 2016-07-12 19:24:11 -04:00 committed by Mark Payne
parent 8ab9fca7f8
commit 1e1630cc69
8 changed files with 68 additions and 199 deletions

View File

@ -1,88 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.web.servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
*
*/
public class DownloadSvg extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(DownloadSvg.class);
/**
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String svg = request.getParameter("svg");
// ensure the image markup has been included
if (svg == null) {
// set the response status
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
// write the response message
PrintWriter out = response.getWriter();
out.println("SVG must be specified.");
return;
}
try {
if (logger.isDebugEnabled()) {
logger.debug(svg);
}
String filename = request.getParameter("filename");
if (filename == null) {
filename = "image.svg";
} else if (!filename.endsWith(".svg")) {
filename += ".svg";
}
response.setContentType("image/svg+xml");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(svg);
} catch (final Exception e) {
logger.error(e.getMessage(), e);
// set the response status
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// write the response message
PrintWriter out = response.getWriter();
out.println("Unable to export image as a SVG.");
}
}
}

View File

@ -56,7 +56,7 @@
<div id="provenance-lineage-loading" class="loading-container"></div>
</div>
<div id="provenance-lineage-close-container">
<div id="provenance-lineage-downloader" title="Download"></div>
<div id="provenance-lineage-downloader" class="hidden" title="Download"></div>
<div id="provenance-lineage-closer" title="Close"></div>
</div>
<div id="provenance-lineage-context-menu"></div>

View File

@ -116,16 +116,6 @@
<url-pattern>/message</url-pattern>
</servlet-mapping>
<!-- servlet to support image downloading -->
<servlet>
<servlet-name>DownloadSvg</servlet-name>
<servlet-class>org.apache.nifi.web.servlet.DownloadSvg</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadSvg</servlet-name>
<url-pattern>/download-svg</url-pattern>
</servlet-mapping>
<!-- servlet to login page -->
<servlet>
<servlet-name>Login</servlet-name>

View File

@ -427,11 +427,11 @@ nf.CanvasUtils = (function () {
*/
activeThreadCount: function (selection, d, setOffset) {
// if there is active threads show the count, otherwise hide
if (nf.Common.isDefinedAndNotNull(d.status) && d.status.activeThreadCount > 0) {
if (nf.Common.isDefinedAndNotNull(d.status) && d.status.aggregateSnapshot.activeThreadCount > 0) {
// update the active thread count
var activeThreadCount = selection.select('text.active-thread-count')
.text(function () {
return d.status.activeThreadCount;
return d.status.aggregateSnapshot.activeThreadCount;
})
.style('display', 'block')
.each(function () {

View File

@ -787,7 +787,7 @@ nf.Connection = (function () {
}
})
.classed('is-missing-port', function () {
return d.component.source.exists === true;
return d.component.source.exists === false;
});
} else {
// there is no connection from, but check if the name was previous

View File

@ -250,7 +250,7 @@ nf.Port = (function () {
details.append('text')
.attr({
'class': 'active-thread-count-icon',
'y': 68
'y': 43 + offset
})
.text('\ue83f');
@ -258,7 +258,7 @@ nf.Port = (function () {
details.append('text')
.attr({
'class': 'active-thread-count',
'y': 68
'y': 43 + offset
});
}

View File

@ -724,41 +724,6 @@ nf.Common = (function () {
}
},
/**
* Creates a form inline in order to submit the specified params to the specified URL
* using the specified method.
*
* @param {string} url The URL
* @param {object} params An object with the params to include in the submission
*/
post: function (url, params) {
// temporarily override beforeunload
var previousBeforeUnload = window.onbeforeunload;
window.onbeforeunload = null;
// create a form for submission
var form = $('<form></form>').attr({
'method': 'POST',
'action': url,
'style': 'display: none;'
});
// add each parameter when specified
if (nf.Common.isDefinedAndNotNull(params)) {
$.each(params, function (name, value) {
$('<textarea></textarea>').attr('name', name).val(value).appendTo(form);
});
}
// submit the form and clean up
form.appendTo('body').submit().remove();
// restore previous beforeunload if necessary
if (previousBeforeUnload !== null) {
window.onbeforeunload = previousBeforeUnload;
}
},
/**
* Formats the specified array as an unordered list. If the array is not an
* array, null is returned.

View File

@ -1237,67 +1237,69 @@ nf.ProvenanceLineage = (function () {
$('#provenance-event-search').show();
$('#provenance-lineage').hide();
});
$('#provenance-lineage-downloader').on('click', function () {
var svg = $('#provenance-lineage-container').html();
// get the lineage to determine the actual dimensions
var lineage = $('g.lineage')[0];
var bbox = lineage.getBBox();
// adjust to provide some padding
var height = bbox.height + 30;
var width = bbox.width + 30;
var offsetX = bbox.x - 15;
var offsetY = bbox.y - 15;
// replace the svg height, width with the actual values
svg = svg.replace(/height=".*?"/, 'height="' + height + '"');
svg = svg.replace(/width=".*?"/, 'width="' + width + '"');
// remove any transform applied to the lineage
svg = svg.replace(/transform=".*?"/, '');
// adjust link positioning based on the offset of the bounding box
svg = svg.replace(/<path([^>]*?)d="M[\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?L[\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?"(.*?)>/g, function (match, before, rawMoveX, rawMoveY, rawLineX, rawLineY, after) {
// this regex captures the content before and after the d attribute in order to ensure that it contains the link class.
// within the svg image, there are other paths that are (within markers) that we do not want to offset
if (before.indexOf('link') === -1 && after.indexOf('link') === -1) {
return match;
}
var moveX = parseFloat(rawMoveX) - offsetX;
var moveY = parseFloat(rawMoveY) - offsetY;
var lineX = parseFloat(rawLineX) - offsetX;
var lineY = parseFloat(rawLineY) - offsetY;
return '<path' + before + 'd="M' + moveX + ',' + moveY + 'L' + lineX + ',' + lineY + '"' + after + '>';
});
// adjust node positioning based on the offset of the bounding box
svg = svg.replace(/<g([^>]*?)transform="translate\([\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?\)"(.*?)>/g, function (match, before, rawX, rawY, after) {
// this regex captures the content before and after the transform attribute in order to ensure that it contains the
// node class. only node groups are translated with absolute coordinates since all other translated groups fall under
// a parent that is already positioned. this makes their translation relative and not appropriate for this adjustment
if (before.indexOf('node') === -1 && after.indexOf('node') === -1) {
return match;
}
var x = parseFloat(rawX) - offsetX;
var y = parseFloat(rawY) - offsetY;
return '<g' + before + 'transform="translate(' + x + ',' + y + ')"' + after + '>';
});
// namespaces
svg = svg.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"');
// doctype
svg = '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' + svg;
// send to server to initiate download... client side only support is too browser specific at this point
nf.Common.post('./download-svg', {
'filename': 'provenance',
'svg': svg
});
});
// TODO - restore this as necessary when able to download lineage svg entirely client side
// $('#provenance-lineage-downloader').on('click', function () {
// var svg = $('#provenance-lineage-container').html();
//
// // get the lineage to determine the actual dimensions
// var lineage = $('g.lineage')[0];
// var bbox = lineage.getBBox();
//
// // adjust to provide some padding
// var height = bbox.height + 30;
// var width = bbox.width + 30;
// var offsetX = bbox.x - 15;
// var offsetY = bbox.y - 15;
//
// // replace the svg height, width with the actual values
// svg = svg.replace(/height=".*?"/, 'height="' + height + '"');
// svg = svg.replace(/width=".*?"/, 'width="' + width + '"');
//
// // remove any transform applied to the lineage
// svg = svg.replace(/transform=".*?"/, '');
//
// // adjust link positioning based on the offset of the bounding box
// svg = svg.replace(/<path([^>]*?)d="M[\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?L[\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?"(.*?)>/g, function (match, before, rawMoveX, rawMoveY, rawLineX, rawLineY, after) {
// // this regex captures the content before and after the d attribute in order to ensure that it contains the link class.
// // within the svg image, there are other paths that are (within markers) that we do not want to offset
// if (before.indexOf('link') === -1 && after.indexOf('link') === -1) {
// return match;
// }
//
// var moveX = parseFloat(rawMoveX) - offsetX;
// var moveY = parseFloat(rawMoveY) - offsetY;
// var lineX = parseFloat(rawLineX) - offsetX;
// var lineY = parseFloat(rawLineY) - offsetY;
// return '<path' + before + 'd="M' + moveX + ',' + moveY + 'L' + lineX + ',' + lineY + '"' + after + '>';
// });
//
// // adjust node positioning based on the offset of the bounding box
// svg = svg.replace(/<g([^>]*?)transform="translate\([\s]?([^\s]+?)[\s,]([^\s]+?)[\s]?\)"(.*?)>/g, function (match, before, rawX, rawY, after) {
// // this regex captures the content before and after the transform attribute in order to ensure that it contains the
// // node class. only node groups are translated with absolute coordinates since all other translated groups fall under
// // a parent that is already positioned. this makes their translation relative and not appropriate for this adjustment
// if (before.indexOf('node') === -1 && after.indexOf('node') === -1) {
// return match;
// }
//
// var x = parseFloat(rawX) - offsetX;
// var y = parseFloat(rawY) - offsetY;
// return '<g' + before + 'transform="translate(' + x + ',' + y + ')"' + after + '>';
// });
//
// // namespaces
// svg = svg.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"');
//
// // doctype
// svg = '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' + svg;
//
// // send to server to initiate download... client side only support is too browser specific at this point
// nf.Common.post('./download-svg', {
// 'filename': 'provenance',
// 'svg': svg
// });
// });
initLineageQueryDialog();
},