NIFI-906: This closes #600. Make NiFi docs responsible

- Switched from absolute layout to responsible using flex-box.
- Added toggle switch to control component listing pane visibility.

Signed-off-by: joewitt <joewitt@apache.org>
This commit is contained in:
Koji Kawamura 2016-07-01 10:34:14 +09:00 committed by joewitt
parent 97366d61bc
commit 7db728d219
4 changed files with 245 additions and 172 deletions

View File

@ -19,6 +19,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="../nifi/images/nifi16.ico"/> <link rel="shortcut icon" href="../nifi/images/nifi16.ico"/>
<title>NiFi Documentation</title> <title>NiFi Documentation</title>
@ -29,104 +30,110 @@
</head> </head>
<body id="documentation-body"> <body id="documentation-body">
<div id="banner-header" class="main-banner-header"></div> <div id="banner-header" class="main-banner-header"></div>
<div id="banner-footer" class="main-banner-footer"></div>
<span id="initial-selection" style="display: none;"><%= request.getParameter("select") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("select")) %></span> <span id="initial-selection" style="display: none;"><%= request.getParameter("select") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("select")) %></span>
<div id="documentation-header" class="documentation-header"> <div id="documentation-header" class="documentation-header">
<div id="nf-title">NiFi Documentation</div> <div id="component-list-toggle-link">-</div>
<div id="nf-version"></div> <div id="header-contents">
<div id="selected-component"></div> <div id="nf-title">NiFi Documentation</div>
<div class="clear"></div> <div id="nf-version"></div>
</div> <div id="selected-component"></div>
<div id="component-listing" class="component-listing">
<div class="section">
<div class="header">General</div>
<div id="general-links" class="component-links">
<ul>
<li class="component-item"><a class="component-link overview" href="html/overview.html" target="component-usage">Overview</a></li>
<li class="component-item"><a class="component-link getting-started" href="html/getting-started.html" target="component-usage">Getting Started</a></li>
<li class="component-item"><a class="component-link user-guide" href="html/user-guide.html" target="component-usage">User Guide</a></li>
<li class="component-item"><a class="component-link expression-language-guide" href="html/expression-language-guide.html" target="component-usage">Expression Language Guide</a></li>
<li class="component-item"><a class="component-link admin-guide" href="html/administration-guide.html" target="component-usage">Admin Guide</a></li>
</ul>
<span class="no-matching no-components hidden">No matching guides</span>
</div>
</div> </div>
<div class="section"> </div>
<div class="header">Processors</div> <div id="component-root-container">
<div id="processor-links" class="component-links"> <div id="component-listing-container">
<c:choose> <div id="component-listing" class="component-listing">
<c:when test="${not empty processors}"> <div class="section">
<div class="header">General</div>
<div id="general-links" class="component-links">
<ul> <ul>
<c:forEach var="entry" items="${processors}"> <li class="component-item"><a class="component-link overview" href="html/overview.html" target="component-usage">Overview</a></li>
<li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li> <li class="component-item"><a class="component-link getting-started" href="html/getting-started.html" target="component-usage">Getting Started</a></li>
</c:forEach> <li class="component-item"><a class="component-link user-guide" href="html/user-guide.html" target="component-usage">User Guide</a></li>
<li class="component-item"><a class="component-link expression-language-guide" href="html/expression-language-guide.html" target="component-usage">Expression Language Guide</a></li>
<li class="component-item"><a class="component-link admin-guide" href="html/administration-guide.html" target="component-usage">Admin Guide</a></li>
</ul> </ul>
<span class="no-matching no-components hidden">No matching processors</span> <span class="no-matching no-components hidden">No matching guides</span>
</c:when> </div>
<c:otherwise> </div>
<span class="no-components">No processor documentation found</span> <div class="section">
</c:otherwise> <div class="header">Processors</div>
</c:choose> <div id="processor-links" class="component-links">
</div> <c:choose>
</div> <c:when test="${not empty processors}">
<div class="section"> <ul>
<div class="header">Controller Services</div> <c:forEach var="entry" items="${processors}">
<div id="controller-service-links" class="component-links"> <li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li>
<c:choose> </c:forEach>
<c:when test="${not empty controllerServices}"> </ul>
<span class="no-matching no-components hidden">No matching processors</span>
</c:when>
<c:otherwise>
<span class="no-components">No processor documentation found</span>
</c:otherwise>
</c:choose>
</div>
</div>
<div class="section">
<div class="header">Controller Services</div>
<div id="controller-service-links" class="component-links">
<c:choose>
<c:when test="${not empty controllerServices}">
<ul>
<c:forEach var="entry" items="${controllerServices}">
<li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li>
</c:forEach>
</ul>
<span class="no-matching no-components hidden">No matching controller services</span>
</c:when>
<c:otherwise>
<span class="no-components">No controller service documentation found</span>
</c:otherwise>
</c:choose>
</div>
</div>
<div class="section">
<div class="header">Reporting Tasks</div>
<div id="reporting-task-links" class="component-links">
<c:choose>
<c:when test="${not empty reportingTasks}">
<ul>
<c:forEach var="entry" items="${reportingTasks}">
<li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li>
</c:forEach>
</ul>
<span class="no-matching no-components hidden">No matching reporting tasks</span>
</c:when>
<c:otherwise>
<span class="no-components">No reporting task documentation found</span>
</c:otherwise>
</c:choose>
</div>
</div>
<div class="section">
<div class="header">Developer</div>
<div id="developer-links" class="component-links">
<ul> <ul>
<c:forEach var="entry" items="${controllerServices}"> <li class="component-item"><a class="component-link rest-api" href="rest-api/index.html" target="component-usage">Rest Api</a></li>
<li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li> <li class="component-item"><a class="component-link developer-guide" href="html/developer-guide.html" target="component-usage">Developer Guide</a></li>
</c:forEach> <li class="component-item"><a class="component-link developer-guide" href="html/nifi-in-depth.html" target="component-usage">Apache NiFi In Depth</a></li>
</ul> </ul>
<span class="no-matching no-components hidden">No matching controller services</span> <span class="no-matching no-components hidden">No matching developer guides</span>
</c:when> </div>
<c:otherwise> </div>
<span class="no-components">No controller service documentation found</span> </div>
</c:otherwise> <div id="component-filter-controls">
</c:choose> <div id="component-filter-container">
<input type="text" id="component-filter"/>
</div>
<div id="component-filter-stats">
Displaying&nbsp;<span id="displayed-components">${totalComponents}</span>&nbsp;of&nbsp;${totalComponents}
</div>
</div> </div>
</div> </div>
<div class="section"> <div id="component-usage-container">
<div class="header">Reporting Tasks</div> <iframe id="component-usage" name="component-usage" frameborder="0" class="component-usage"></iframe>
<div id="reporting-task-links" class="component-links">
<c:choose>
<c:when test="${not empty reportingTasks}">
<ul>
<c:forEach var="entry" items="${reportingTasks}">
<li class="component-item"><a class="component-link" href="components/${entry.value}/index.html" target="component-usage">${entry.key}</a></li>
</c:forEach>
</ul>
<span class="no-matching no-components hidden">No matching reporting tasks</span>
</c:when>
<c:otherwise>
<span class="no-components">No reporting task documentation found</span>
</c:otherwise>
</c:choose>
</div>
</div>
<div class="section">
<div class="header">Developer</div>
<div id="developer-links" class="component-links">
<ul>
<li class="component-item"><a class="component-link rest-api" href="rest-api/index.html" target="component-usage">Rest Api</a></li>
<li class="component-item"><a class="component-link developer-guide" href="html/developer-guide.html" target="component-usage">Developer Guide</a></li>
<li class="component-item"><a class="component-link developer-guide" href="html/nifi-in-depth.html" target="component-usage">Apache NiFi In Depth</a></li>
</ul>
<span class="no-matching no-components hidden">No matching developer guides</span>
</div>
</div> </div>
</div> </div>
<div id="component-filter-controls"> <div id="banner-footer" class="main-banner-footer"></div>
<div id="component-filter-container">
<input type="text" id="component-filter"/>
</div>
<div id="component-filter-stats">
Displaying&nbsp;<span id="displayed-components">${totalComponents}</span>&nbsp;of&nbsp;${totalComponents}
</div>
</div>
<div id="component-usage-container">
<iframe id="component-usage" name="component-usage" frameborder="0" class="component-usage"></iframe>
</div>
</body> </body>
</html> </html>

View File

@ -23,7 +23,6 @@ html, html a {
} }
body { body {
width: 62.5em;
margin: 0 auto; margin: 0 auto;
display: block; display: block;
font-family: "Open Sans","DejaVu Sans",sans-serif; font-family: "Open Sans","DejaVu Sans",sans-serif;
@ -114,7 +113,6 @@ table tr:last-child td:last-child {
} }
td#allowable-values, td#default-value, td#name, td#value { td#allowable-values, td#default-value, td#name, td#value {
white-space:nowrap;
} }
/* links */ /* links */

View File

@ -32,32 +32,26 @@
div.main-banner-header { div.main-banner-header {
display: none; display: none;
z-index: 100;
font-weight: bold; font-weight: bold;
font-size: 1em; font-size: 1em;
text-align: center; text-align: center;
line-height: 15px; line-height: 15px;
color: #7e7e7e; color: #7e7e7e;
margin: 0px auto; margin: 0px auto;
width: 900px; width: 100%;
height: 17px; height: 1em;
background-color: #fff; background-color: #fff;
z-index: 100;
background-image: url(../images/bgHeader.png); background-image: url(../images/bgHeader.png);
background-position: center;
background-repeat: no-repeat;
} }
div.main-banner-footer { div.main-banner-footer {
display: none; display: none;
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
height: 15px;
color: #fff; color: #fff;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
font-size: 1em; font-size: 1em;
line-height: 15px;
overflow: visible; overflow: visible;
background-color: #9eb9c7; background-color: #9eb9c7;
background-image: url(../images/bgBannerFoot.png); background-image: url(../images/bgBannerFoot.png);
@ -68,52 +62,72 @@ div.main-banner-footer {
/* documentation */ /* documentation */
div.documentation-header { div.documentation-header {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 45px;
border-bottom: 1px solid #d1dee5; border-bottom: 1px solid #d1dee5;
color: #365c6a; color: #365c6a;
font-size: 13px; font-size: 13px;
display: flex;
}
#component-list-toggle-link {
padding: 4px;
font-size: 14px;
font-weight: bold;
color: #264c58;
cursor: pointer;
width: 12px;
text-align: center;
align-self: flex-end;
}
#header-contents {
display: flex;
flex-wrap: wrap;
} }
#nf-title { #nf-title {
float: left;
height: 50px;
padding: 5px;
font-size: 20px; font-size: 20px;
margin-top: 10px; margin: 5px 5px 0px 5px;
} }
#nf-version { #nf-version {
float: left;
font-size: 14px; font-size: 14px;
margin-left: 10px;
margin-top: 21px;
font-style: italic; font-style: italic;
color: #aaa; color: #aaa;
margin: 11px 5px 0px 5px;
flex-grow: 1;
} }
#selected-component { #selected-component {
float: right;
height: 50px;
padding: 5px;
margin-top: 10px;
font-size: 20px; font-size: 20px;
margin: 5px 5px 0px 5px;
}
/* content flex-box containers */
#component-root-container {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
#component-listing-container {
flex-grow: 1;
min-width: 312px;
padding: 0px 4px 0px 4px;
}
#component-usage-container {
flex-grow: 4;
min-width: 300px;
padding: 0px 4px 0px 4px;
} }
/* component listing */ /* component listing */
div.component-listing { div.component-listing {
width: 300px;
position: absolute;
top: 46px;
left: 0;
bottom: 40px;
overflow: auto; overflow: auto;
font-size: 16px; font-size: 16px;
padding: 4px;
} }
div.component-listing div.section { div.component-listing div.section {
@ -161,25 +175,17 @@ div.component-links span.no-components {
/* component filter control */ /* component filter control */
#component-filter-controls { #component-filter-controls {
width: 308px;
height: 40px;
position: absolute;
bottom: 0;
left: 0;
} }
#component-filter-container { #component-filter-container {
height: 24px;
margin-left: 2px; margin-left: 2px;
margin-top: 1px;
} }
#component-filter { #component-filter {
padding: 1px;
font-size: 12px; font-size: 12px;
height: 18px; height: 18px;
line-height: 20px; line-height: 20px;
width: 299px; width: 98%;
float: left; float: left;
} }
@ -195,20 +201,13 @@ input.component-filter-list {
clear: left; clear: left;
line-height: normal; line-height: normal;
margin-left: 7px; margin-left: 7px;
margin-top: 2px;
} }
/* component usage */ /* component usage */
#component-usage-container {
position: absolute;
top: 46px;
right: 0px;
bottom: 0px;
left: 312px;
overflow: hidden;
}
#component-usage { #component-usage {
overflow: auto; overflow: auto;
width: 100%;
height: 100%;
position: absolute;
} }

View File

@ -131,6 +131,8 @@ $(document).ready(function () {
}; };
// get the banners if we're not in the shell // get the banners if we're not in the shell
var bannerHeaderHeight = 0;
var bannerFooterHeight = 0;
var banners = $.Deferred(function (deferred) { var banners = $.Deferred(function (deferred) {
if (top === window) { if (top === window) {
$.ajax({ $.ajax({
@ -143,32 +145,13 @@ $(document).ready(function () {
if (isDefinedAndNotNull(response.banners.headerText) && response.banners.headerText !== '') { if (isDefinedAndNotNull(response.banners.headerText) && response.banners.headerText !== '') {
// update the header text // update the header text
var bannerHeader = $('#banner-header').text(response.banners.headerText).show(); var bannerHeader = $('#banner-header').text(response.banners.headerText).show();
bannerHeaderHeight = bannerHeader.height();
// show the banner
var updateTop = function (elementId) {
var element = $('#' + elementId);
element.css('top', (parseInt(bannerHeader.css('height')) + parseInt(element.css('top'))) + 'px');
};
// update the position of elements affected by top banners
updateTop('documentation-header');
updateTop('component-listing');
updateTop('component-usage-container');
} }
if (isDefinedAndNotNull(response.banners.footerText) && response.banners.footerText !== '') { if (isDefinedAndNotNull(response.banners.footerText) && response.banners.footerText !== '') {
// update the footer text and show it // update the footer text and show it
var bannerFooter = $('#banner-footer').text(response.banners.footerText).show(); var bannerFooter = $('#banner-footer').text(response.banners.footerText).show();
bannerFooterHeight = bannerFooter.height();
var updateBottom = function (elementId) {
var element = $('#' + elementId);
element.css('bottom', parseInt(bannerFooter.css('height')) + parseInt(element.css('bottom')) + 'px');
};
// update the position of elements affected by bottom banners
updateBottom('component-filter-controls');
updateBottom('component-listing');
updateBottom('component-usage-container');
} }
} }
@ -208,25 +191,111 @@ $(document).ready(function () {
} }
}).addClass('component-filter-list').val('Filter'); }).addClass('component-filter-list').val('Filter');
// get the component usage container to install the window listener // get the component containers to install the window listener
var componentUsageContainer = $('#component-usage-container'); var documentationHeader = $('#documentation-header');
var componentRootContainer = $('#component-root-container');
var componentListingContainer = $('#component-listing-container', componentRootContainer);
var componentListing = $('#component-listing', componentListingContainer);
var componentFilterControls = $('#component-filter-controls', componentRootContainer);
var componentUsageContainer = $('#component-usage-container', componentUsageContainer);
var componentUsage = $('#component-usage', componentUsageContainer);
// size the iframe accordingly var componentListingContainerPaddingX = 0;
var componentUsage = $('#component-usage').css({ componentListingContainerPaddingX += parseInt(componentListingContainer.css("padding-right"), 10);
width: componentUsageContainer.width(), componentListingContainerPaddingX += parseInt(componentListingContainer.css("padding-left"), 10);
height: componentUsageContainer.height()
}); var componentListingContainerPaddingY = 0;
componentListingContainerPaddingY += parseInt(componentListingContainer.css("padding-top"), 10);
componentListingContainerPaddingY += parseInt(componentListingContainer.css("padding-bottom"), 10);
var componentUsageContainerPaddingX = 0;
componentUsageContainerPaddingX += parseInt(componentUsageContainer.css("padding-right"), 10);
componentUsageContainerPaddingX += parseInt(componentUsageContainer.css("padding-left"), 10);
var componentUsageContainerPaddingY = 0;
componentUsageContainerPaddingY += parseInt(componentUsageContainer.css("padding-top"), 10);
componentUsageContainerPaddingY += parseInt(componentUsageContainer.css("padding-bottom"), 10);
var componentListingContainerMinWidth = parseInt(componentListingContainer.css("min-width"), 10) + componentListingContainerPaddingX;
var componentUsageContainerMinWidth = parseInt(componentUsageContainer.css("min-width"), 10) + componentUsageContainerPaddingX;
var smallDisplayBoundary = componentListingContainerMinWidth + componentUsageContainerMinWidth;
var cssComponentListingNormal = { backgroundColor: "#ffffff" };
var cssComponentListingSmall = { backgroundColor: "#fbfbfb" };
// add a window resize listener // add a window resize listener
$(window).resize(function () { $(window).resize(function () {
componentUsage.css({ // This -1 is the border-top of #component-usage-container
width: componentUsageContainer.width(), var baseHeight = window.innerHeight - 1;
height: componentUsageContainer.height() baseHeight -= bannerHeaderHeight;
baseHeight -= bannerFooterHeight;
baseHeight -= documentationHeader.height();
// resize component list accordingly
if (smallDisplayBoundary > window.innerWidth) {
// screen is not wide enough to display content usage
// within the same row.
componentListingContainer.css(cssComponentListingSmall);
componentListingContainer.css({
borderBottom: "1px solid #ddddd8"
});
componentListing.css({
height: "200px"
});
// resize the iframe accordingly
var componentUsageHeight = baseHeight;
if (componentListingContainer.is(":visible")) {
componentUsageHeight -= componentListingContainer.height();
componentUsageHeight -= 1; // border-bottom
}
componentUsageHeight -= componentListingContainerPaddingY;
componentUsageHeight -= componentUsageContainerPaddingY;
componentUsage.css({
width: componentUsageContainer.width(),
height: componentUsageHeight
});
componentUsageContainer.css({
height: componentUsage.height()
});
} else {
componentListingContainer.css(cssComponentListingNormal);
var componentListingHeight = baseHeight;
componentListingHeight -= componentFilterControls.height();
componentListingHeight -= componentListingContainerPaddingY;
componentListing.css({
height: componentListingHeight
});
// resize the iframe accordingly
componentUsage.css({
width: componentUsageContainer.width(),
height: baseHeight - componentUsageContainerPaddingY
});
componentUsageContainer.css({
height: componentUsage.height()
});
componentListingContainer.css({
borderBottom: "0px"
});
}
});
var toggleComponentListing = $('#component-list-toggle-link');
toggleComponentListing.click(function(){
componentListingContainer.toggle(0, function(){
toggleComponentListing.text($(this).is(":visible") ? "-" : "+");
$(window).resize();
}); });
}); });
// listen for loading of the iframe to update the title // listen for loading of the iframe to update the title
$('#component-usage').on('load', function () { $('#component-usage').on('load', function () {
// resize window accordingly.
$(window).resize();
var componentName = ''; var componentName = '';
var href = $(this).contents().get(0).location.href; var href = $(this).contents().get(0).location.href;