You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/01/20 15:02:15 UTC

[39/42] incubator-nifi git commit: NIFI-250: - Starting to making the available controller services collapsible. Still need to clean up and handle selection properly.

NIFI-250:
- Starting to making the available controller services collapsible. Still need to clean up and handle selection properly.


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

Branch: refs/heads/NIFI-250
Commit: b204688bfa738c47bed71a1aab6c46171b21107f
Parents: b39fdbd
Author: Matt Gilman <ma...@gmail.com>
Authored: Fri Jan 16 11:59:51 2015 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Tue Jan 20 07:56:10 2015 -0500

----------------------------------------------------------------------
 .../nifi/web/api/dto/DocumentedTypeDTO.java     |  20 +-
 .../entity/ControllerServiceTypesEntity.java    |  46 ++++
 .../api/entity/ReportingTaskTypesEntity.java    |  46 ++++
 .../org/apache/nifi/web/api/dto/DtoFactory.java |  69 +++++-
 .../nifi/web/controller/ControllerFacade.java   |   1 -
 .../canvas/new-controller-service-dialog.jsp    |  48 ++++
 .../WEB-INF/partials/canvas/registration.jsp    |   2 +-
 .../nifi-web-ui/src/main/webapp/css/main.css    |  22 +-
 .../css/new-controller-service-dialog.css       | 133 +++++++++++
 .../src/main/webapp/css/registration.css        |   8 -
 .../src/main/webapp/css/settings.css            |   6 +
 .../js/jquery/tagcloud/jquery.tagcloud.css      |  62 +++++
 .../js/jquery/tagcloud/jquery.tagcloud.js       | 238 +++++++++++++++++++
 .../main/webapp/js/nf/canvas/nf-registration.js |   4 +-
 .../src/main/webapp/js/nf/canvas/nf-settings.js | 174 +++++++++++---
 15 files changed, 798 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
index 5a2d789..7cf1b84 100644
--- a/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
+++ b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
@@ -20,13 +20,13 @@ import java.util.Set;
 import javax.xml.bind.annotation.XmlType;
 
 /**
- * Class used for providing documentation of a specified type that may be
- * instantiated.
+ * Class used for providing documentation of a specified type.
  */
 @XmlType(name = "documentedType")
 public class DocumentedTypeDTO {
 
     private String type;
+    private Set<DocumentedTypeDTO> childTypes;
     private String description;
     private Set<String> tags;
 
@@ -57,7 +57,7 @@ public class DocumentedTypeDTO {
     }
 
     /**
-     * The tags associated with this type
+     * The tags associated with this type.
      *
      * @return
      */
@@ -68,4 +68,18 @@ public class DocumentedTypeDTO {
     public void setTags(final Set<String> tags) {
         this.tags = tags;
     }
+
+    /**
+     * Child types for this type.
+     * 
+     * @return 
+     */
+    public Set<DocumentedTypeDTO> getChildTypes() {
+        return childTypes;
+    }
+
+    public void setChildTypes(Set<DocumentedTypeDTO> childTypes) {
+        this.childTypes = childTypes;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
new file mode 100644
index 0000000..dafb8c2
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.api.entity;
+
+import java.util.Set;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.nifi.web.api.dto.DocumentedTypeDTO;
+
+/**
+ * A serialized representation of this class can be placed in the entity body of
+ * a response to the API. This particular entity holds a reference to a list of
+ * controller service types.
+ */
+@XmlRootElement(name = "controllerServiceTypesEntity")
+public class ControllerServiceTypesEntity extends Entity {
+
+    private Set<DocumentedTypeDTO> controllerServiceTypes;
+
+    /**
+     * The list of controller service types that are being serialized.
+     *
+     * @return
+     */
+    public Set<DocumentedTypeDTO> getControllerServiceTypes() {
+        return controllerServiceTypes;
+    }
+
+    public void setControllerServiceTypes(Set<DocumentedTypeDTO> controllerServiceTypes) {
+        this.controllerServiceTypes = controllerServiceTypes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
new file mode 100644
index 0000000..4b021ef
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.api.entity;
+
+import java.util.Set;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.nifi.web.api.dto.DocumentedTypeDTO;
+
+/**
+ * A serialized representation of this class can be placed in the entity body of
+ * a response to the API. This particular entity holds a reference to a list of
+ * reporting task types.
+ */
+@XmlRootElement(name = "reportingTaskTypesEntity")
+public class ReportingTaskTypesEntity extends Entity {
+
+    private Set<DocumentedTypeDTO> reportingTaskTypes;
+
+    /**
+     * The list of reporting task types that are being serialized.
+     *
+     * @return
+     */
+    public Set<DocumentedTypeDTO> getReportingTaskTypes() {
+        return reportingTaskTypes;
+    }
+
+    public void setReportingTaskTypes(Set<DocumentedTypeDTO> reportingTaskTypes) {
+        this.reportingTaskTypes = reportingTaskTypes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 30abaf8..7fad616 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -1136,16 +1136,18 @@ public final class DtoFactory {
      * @param type
      * @param baseTypes 
      */
-    private void identifyBaseTypes(final Class baseType, final Class type, final Set<String> baseTypes) {
+    private void identifyBaseTypes(final Class baseType, final Class type, final Set<Class> baseTypes, final  boolean recurse) {
         final Class[] interfaces = type.getInterfaces();
         for (final Class i : interfaces) {
             if (baseType.isAssignableFrom(i) && !baseType.equals(i)) {
-                baseTypes.add(i.getName());
+                baseTypes.add(i);
             }
         }
         
-        if (type.getSuperclass() != null) {
-            identifyBaseTypes(baseType, type.getSuperclass(), baseTypes);
+        if (recurse) {
+            if (type.getSuperclass() != null) {
+                identifyBaseTypes(baseType, type.getSuperclass(), baseTypes, recurse);
+            }
         }
     }
     
@@ -1160,20 +1162,61 @@ public final class DtoFactory {
         final Set<DocumentedTypeDTO> types = new LinkedHashSet<>();
         final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR);
         sortedClasses.addAll(classes);
+        
+        // identify all interfaces that extend baseClass for all classes
+        final Set<Class> interfaces = new HashSet<>();
+        for (final Class<?> cls : sortedClasses) {
+            identifyBaseTypes(baseClass, cls, interfaces, true);
+        }
+        
+        final Map<Class, DocumentedTypeDTO> lookup = new HashMap<>();
+        
+        // convert the interfaces to DTO form
+        for (final Class<?> i : interfaces) {
+            final DocumentedTypeDTO type = new DocumentedTypeDTO();
+            type.setType(i.getName());
+            type.setDescription(getCapabilityDescription(i));
+            type.setTags(getTags(i));
+            type.setChildTypes(new LinkedHashSet<DocumentedTypeDTO>());
+            lookup.put(i, type);
+        }
 
+        // include the interfaces
+        sortedClasses.addAll(interfaces);
+        
+        // get the DTO form for all interfaces and classes
         for (final Class<?> cls : sortedClasses) {
-            final DocumentedChildTypeDTO type = new DocumentedChildTypeDTO();
-            type.setType(cls.getName());
-            type.setDescription(getCapabilityDescription(cls));
-            type.setTags(getTags(cls));
+            boolean add = false;
+            
+            final DocumentedTypeDTO type;
+            if (lookup.containsKey(cls)) {
+                type = lookup.get(cls);
+                add = true;
+            } else {
+                type = new DocumentedTypeDTO();
+                type.setType(cls.getName());
+                type.setDescription(getCapabilityDescription(cls));
+                type.setTags(getTags(cls));
+            }
             
             // identify the base types
-            final Set<String> baseTypes = new LinkedHashSet<>();
-            identifyBaseTypes(baseClass, cls, baseTypes);
-            type.setBaseTypes(baseTypes);
+            final Set<Class> baseTypes = new LinkedHashSet<>();
+            identifyBaseTypes(baseClass, cls, baseTypes, false);
             
-            // add this type
-            types.add(type);
+            // include this type if it doesn't belong to another heirachary
+            if (baseTypes.isEmpty()) {
+                add = true;
+            }
+            
+            // get the DTO for each base type
+            for (final Class baseType : baseTypes) {
+                lookup.get(baseType).getChildTypes().add(type);
+            }
+            
+            // add if appropriate
+            if (add) {
+                types.add(type);
+            }
         }
 
         return types;

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index a9ad968..917e23a 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -115,7 +115,6 @@ import org.apache.nifi.admin.service.UserService;
 import org.apache.nifi.authorization.DownloadAuthorization;
 import org.apache.nifi.processor.DataUnit;
 import org.apache.nifi.reporting.ReportingTask;
-import org.apache.nifi.web.api.dto.DocumentedChildTypeDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.AccessDeniedException;

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-controller-service-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-controller-service-dialog.jsp b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-controller-service-dialog.jsp
new file mode 100644
index 0000000..b896d8a
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-controller-service-dialog.jsp
@@ -0,0 +1,48 @@
+<%--
+ 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.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="new-controller-service-dialog">
+    <div class="dialog-content">
+        <div id="controller-service-type-filter-controls">
+            <div id="controller-service-type-filter-container">
+                <input type="text" id="controller-service-type-filter"/>
+                <div id="controller-service-type-filter-options"></div>
+            </div>
+            <div id="controller-service-type-filter-status">
+                Displaying&nbsp;<span id="displayed-controller-service-types"></span>&nbsp;of&nbsp;<span id="total-controller-service-types"></span>
+            </div>
+        </div>
+        <div id="controller-service-tag-cloud-container">
+            <div class="setting">
+                <div class="setting-name">Tags</div>
+                <div class="setting-field">
+                    <div id="controller-service-tag-cloud"></div>
+                </div>
+            </div>
+        </div>
+        <div id="controller-service-types-container">
+            <div id="controller-service-types-table" class="unselectable"></div>
+            <div id="controller-service-description-container">
+                <div id="controller-service-type-name" class="ellipsis"></div>
+                <div id="controller-service-type-description" class="ellipsis multiline"></div>
+                <span class="hidden" id="selected-controller-service-name"></span>
+                <span class="hidden" id="selected-controller-service-type"></span>
+            </div>
+        </div>
+        <div class="clear"></div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/registration.jsp
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/registration.jsp b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/registration.jsp
index 4a965e4..56b3236 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/registration.jsp
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/registration.jsp
@@ -20,7 +20,7 @@
         <p id="register-title" class="message-pane-title">You are not authorized to access this data flow</p>
         <p id="register-content" class="message-pane-content">
         <div>
-            <div id="expand-registration-button" class="registration-collapsed pointer"></div>
+            <div id="expand-registration-button" class="collapsed pointer"></div>
             <span id="expand-registration-text" class="link">Request Access</span>
         </div>
         <div id="registration-form" class="settings hidden">

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/main.css
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/main.css b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/main.css
index 2724f71..c57c6ee 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/main.css
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/main.css
@@ -138,6 +138,14 @@ input.filter-list {
     margin-top: 4px;
 }
 
+.collapsed {
+    background: transparent url(../images/iconTwistArrow.png) no-repeat scroll top left;
+}
+
+.expanded {
+    background: transparent url(../images/iconTwistArrow.png) no-repeat scroll top right;
+}
+
 input[type=text], textarea {
     background: white url(../images/bgInputText.png) repeat-x scroll top;
     border: 1px solid #ccc;
@@ -253,20 +261,6 @@ div.has-bulletins {
     Styles for status/history/user tables.
 */
 
-div.expansion-button {
-    width: 11px;
-    height: 11px;
-    margin-left: 5px;
-}
-
-div.collapsed {
-    background: transparent url(../images/buttonExpandCollapse.png) no-repeat scroll top left;
-}
-
-div.expanded {
-    background: transparent url(../images/buttonExpandCollapse.png) no-repeat scroll top right;
-}
-
 span.label, div.label {
     font-weight: bold;
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/new-controller-service-dialog.css
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/new-controller-service-dialog.css b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/new-controller-service-dialog.css
new file mode 100644
index 0000000..67492ce
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/new-controller-service-dialog.css
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+/* 
+    New controller dialog.
+*/
+
+#new-controller-service-dialog {
+    z-index: 1301;
+    display: none;
+    width: 800px;
+    height: 450px;
+    border: 1px solid #eee;
+    line-height: normal;
+}
+
+#controller-service-tag-cloud-container {
+    float: left;
+    width: 190px;
+    height: 350px;
+}
+
+#controller-service-types-container {
+    float: left;
+    width: 588px;
+    height: 350px;
+}
+
+#controller-service-description-container {
+    width: 588px;
+    height: 100px;
+    margin-top: 10px;
+}
+
+#controller-service-type-name {
+    font-size: 12pt;
+    font-weight: bold;
+    color: #527991;
+    margin-bottom: 8px;
+    width: 588px;
+}
+
+#controller-service-type-description {
+    width: 588px;
+    height: 60px;
+}
+
+#controller-service-types-table {
+    width: 586px;
+    height: 249px;
+    border: 1px solid #666;
+}
+
+#controller-service-types-table-container th {
+    vertical-align: middle;
+}
+
+/*
+    Processor tag cloud
+*/
+
+#controller-service-tag-cloud ul.tag-cloud {
+    max-height: 257px;
+}
+
+#controller-service-tag-cloud ul.tag-cloud li {
+    max-width: 180px;
+}
+
+#controller-service-tag-cloud div.tag-cloud-separator {
+    width: 180px;
+}
+
+#controller-service-tag-cloud ul.tag-filter li {
+    width: 180px;
+}
+
+#controller-service-tag-cloud div.selected-tag-text {
+    width: 160px;
+}
+
+/*
+    Processor type table filter
+*/
+
+#controller-service-type-filter-controls {
+    float: right;
+    margin-top: -35px;
+    margin-right: 2px;
+    margin-bottom: 7px;
+}
+
+#controller-service-type-filter-status {
+    font-size: 9px;
+    font-weight: bold;
+    color: #9f6000;
+    clear: left; 
+    line-height: normal;
+    margin-left: 5px;
+}
+
+#controller-service-type-filter {
+    padding: 3px 0px 1px 3px;
+    font-size: 12px;
+    height: 18px;
+    line-height: 20px;
+    width: 173px;
+    border: 1px solid #ccc;
+    margin-right: 3px;
+    float: left;
+}
+
+#controller-service-type-filter-options {
+    float: left;
+    height: 17px;
+    line-height: 17px;
+    width: 85px;
+    margin-top: 1px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/registration.css
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/registration.css b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/registration.css
index d81596e..d4fdc7e 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/registration.css
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/registration.css
@@ -42,12 +42,4 @@
 #registration-justification {
     width: 600px;
     height: 200px;
-}
-
-div.registration-collapsed {
-    background: transparent url(../images/iconTwistArrow.png) no-repeat scroll top left;
-}
-
-div.registration-expanded {
-    background: transparent url(../images/iconTwistArrow.png) no-repeat scroll top right;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
index 0622aa9..a70a79b 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
@@ -42,6 +42,12 @@
     cursor: pointer;
 }
 
+span.expansion-button {
+    width: 10px;
+    height: 10px;
+    float: left;
+}
+
 /* settings tabs */
 
 #settings-tabs-container {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.css
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.css b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.css
new file mode 100644
index 0000000..dda7474
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.css
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/*
+    Styles for the Nifi tag cloud.
+*/
+
+ul.tag-cloud {
+    font-size: 90%;
+    padding: 2px;
+    margin-left: -5px;
+    overflow: hidden;
+}
+
+ul.tag-cloud li {
+    float: left;
+    list-style-type: none;
+    margin: 0 3px;
+    height: 20px;
+    line-height: 20px;
+    overflow: hidden;
+    white-space: nowrap;
+}
+
+div.tag-cloud-separator {
+    height: 1px;
+    border-bottom: 1px solid #aaa;
+    margin: 3px 0;
+}
+
+ul.tag-filter {
+    overflow: hidden;
+}
+
+ul.tag-filter li {
+    height: 18px;
+    line-height: 18px;
+    padding: 2px;
+}
+
+div.selected-tag-text {
+    float: left;
+}
+
+img.remove-selected-tag {
+    float: right;
+    margin-top: 1px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.js
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.js b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.js
new file mode 100644
index 0000000..51aa7d8
--- /dev/null
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/jquery/tagcloud/jquery.tagcloud.js
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+
+/**
+ * Create a tag cloud. The options are specified in the following
+ * format:
+ *
+ * {
+ *   tags: ['attributes', 'copy', 'regex', 'xml', 'copy', 'xml', 'attributes'],
+ *   select: selectHandler,
+ *   remove: removeHandler
+ * }
+ * 
+ * Options have a label (specified as the text property that is rendered
+ * to users) and a value which is not. Additionally, options can be marked
+ * as disabled. A disabled option cannot be selected by a user but may be
+ * programmatically selected (supporting the restoration of options that have
+ * become invalid). It is up to the developer to ensure that the selected 
+ * option is not disabled.
+ * 
+ * The optionClass option supports specifying a class to apply to the 
+ * option element.
+ */
+
+/**
+ * jQuery plugin for a NiFi style tag cloud.
+ * 
+ * @param {type} $
+ * @returns {undefined}
+ */
+(function ($) {
+
+    var isUndefined = function (obj) {
+        return typeof obj === 'undefined';
+    };
+
+    var isNull = function (obj) {
+        return obj === null;
+    };
+
+    var isDefinedAndNotNull = function (obj) {
+        return !isUndefined(obj) && !isNull(obj);
+    };
+
+    var isBlank = function (str) {
+        return isUndefined(str) || isNull(str) || str === '';
+    };
+
+    var config = {
+        maxTags: 25,
+        maxTagFontSize: 2,
+        minTagFontSize: 1,
+        minWidth: 20
+    };
+    
+    /**
+     * Adds the specified tag filter.
+     * 
+     * @argument {jQuery} cloudContainer    The tag cloud container
+     * @argument {string} tag               The tag to add
+     */
+    var addTagFilter = function (cloudContainer, tag) {
+        var config = cloudContainer.data('options');
+        var tagFilter = cloudContainer.find('ul.tag-filter');
+        
+        // ensure this tag hasn't already been added
+        var tagFilterExists = false;
+        tagFilter.find('li div.selected-tag-text').each(function () {
+            if (tag === $(this).text()) {
+                tagFilterExists = true;
+                return false;
+            }
+        });
+
+        // add this tag filter if applicable
+        if (!tagFilterExists) {
+            // create the list item content
+            var tagText = $('<div class="selected-tag-text"></div>').text(tag);
+            var removeTagIcon = $('<img src="images/iconDelete.png" class="remove-selected-tag pointer"></img>').click(function () {
+                // remove this tag
+                $(this).closest('li').remove();
+
+                // fire a remove event if applicable
+                if (isDefinedAndNotNull(config.remove)) {
+                    config.remove.call(cloudContainer, tag);
+                }
+            });
+            var selectedTagItem = $('<div></div>').append(tagText).append(removeTagIcon);
+
+            // create the list item and update the tag filter list
+            $('<li></li>').append(selectedTagItem).appendTo(tagFilter);
+
+            // fire a select event if applicable
+            if (isDefinedAndNotNull(config.select)) {
+                config.select.call(cloudContainer, tag);
+            }
+        }
+    };
+
+    var methods = {
+        
+        /**
+         * Initializes the tag cloud.
+         * 
+         * @argument {object} options The options for the tag cloud
+         */
+        init: function (options) {
+            return this.each(function () {
+                // ensure the options have been properly specified
+                if (isDefinedAndNotNull(options) && isDefinedAndNotNull(options.tags)) {
+                    // get the tag cloud
+                    var cloudContainer = $(this);
+                    
+                    // clear any current contents, remote events, and store options
+                    cloudContainer.empty().unbind().data('options', options);
+
+                    // build the component
+                    var cloud = $('<ul class="tag-cloud"></ul>').appendTo(cloudContainer);
+                    $('<div class="tag-cloud-separator">').appendTo(cloudContainer);
+                    var filter = $('<ul class="tag-filter"></ul>').appendTo(cloudContainer);
+
+                    var tagCloud = {};
+                    var tags = [];
+                    
+                    // count the frequency of each tag for this type
+                    $.each(options.tags, function (i, tag) {
+                        var normalizedTagName = tag.toLowerCase();
+
+                        if (nf.Common.isDefinedAndNotNull(tagCloud[normalizedTagName])) {
+                            tagCloud[normalizedTagName].count = tagCloud[normalizedTagName].count + 1;
+                        } else {
+                            var tagCloudEntry = {
+                                term: normalizedTagName,
+                                count: 1
+                            };
+                            tags.push(tagCloudEntry);
+                            tagCloud[normalizedTagName] = tagCloudEntry;
+                        }
+                    });
+                    
+                    // handle the case when no tags are present
+                    if (tags.length > 0) {
+                        // sort the tags by frequency to limit the less frequent tags
+                        tags.sort(function (a, b) {
+                            return b.count - a.count;
+                        });
+
+                        // limit to the most frequest tags
+                        if (tags.length > config.maxTags) {
+                            tags = tags.slice(0, config.maxTags);
+                        }
+
+                        // determine the max frequency
+                        var maxFrequency = tags[0].count;
+
+                        // sort the tags alphabetically
+                        tags.sort(function (a, b) {
+                            var compA = a.term.toUpperCase();
+                            var compB = b.term.toUpperCase();
+                            return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
+                        });
+
+                        // set the tag content
+                        $.each(tags, function (i, tag) {
+                            // determine the appropriate font size
+                            var fontSize = Math.log(tag.count) / Math.log(maxFrequency) * (config.maxTagFontSize - config.minTagFontSize) + config.minTagFontSize;
+                            var minWidth = config.minWidth * fontSize;
+
+                            // create the tag cloud entry
+                            $('<li></li>').append($('<span class="link"></span>').text(tag.term).css({
+                                'font-size': fontSize + 'em'
+                            })).css({
+                                'min-width': minWidth + 'px'
+                            }).click(function () {
+                                // ensure we don't exceed 5 selected
+                                if (filter.children('li').length < 5) {
+                                    var tagText = $(this).children('span').text();
+                                    addTagFilter(cloudContainer, tagText);
+                                }
+                            }).appendTo(cloud).ellipsis();
+                        });
+                    } else {
+                        // indicate when no tags are found
+                        $('<li><span class="unset">No tags specified</span></li>').appendTo(cloud);
+                    }
+                }
+            });
+        },
+        
+        /**
+         * Resets the selected tags from the tag cloud.
+         */
+        clearSelectedTags: function () {
+            return this.each(function() {
+                var cloudContainer = $(this);
+                cloudContainer.find('img.remove-selected-tag').trigger('click');
+            });
+        },
+        
+        /**
+         * Returns the selected tags of the first matching element.
+         */
+        getSelectedTags: function () {
+            var tags = [];
+
+            this.each(function () {
+                var cloudContainer = $(this);
+                cloudContainer.find('div.selected-tag-text').each(function() {
+                    tags.push($(this).text());
+                });
+            });
+
+            return tags;
+        }
+    };
+
+    $.fn.tagcloud = function (method) {
+        if (methods[method]) {
+            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+        } else {
+            return methods.init.apply(this, arguments);
+        }
+    };
+})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-registration.js
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-registration.js b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-registration.js
index ec64677..4fbcee7 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-registration.js
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-registration.js
@@ -35,9 +35,9 @@ nf.Registration = (function () {
             $('#expand-registration-button, #expand-registration-text').click(function () {
                 var registrationForm = $('#registration-form');
                 if (registrationForm.is(':visible')) {
-                    $('#expand-registration-button').removeClass('registration-expanded').addClass('registration-collapsed');
+                    $('#expand-registration-button').removeClass('registration-expanded').addClass('collapsed');
                 } else {
-                    $('#expand-registration-button').removeClass('registration-collapsed').addClass('registration-expanded');
+                    $('#expand-registration-button').removeClass('registration-collapsed').addClass('expanded');
                 }
                 registrationForm.toggle();
             });

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/b204688b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
----------------------------------------------------------------------
diff --git a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index 06bd71f..0e61b4d 100644
--- a/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -138,6 +138,18 @@ nf.Settings = (function () {
         }
     };
     
+    var isParentExpanded = function (item) {
+        var documentedType = item;
+        while (documentedType.parent !== null) {
+            if (documentedType.parent.collapsed === true) {
+                return false;
+            }
+            documentedType = documentedType.parent;
+        }
+        
+        return true;
+    };
+    
     /**
      * Performs the filtering.
      * 
@@ -146,6 +158,10 @@ nf.Settings = (function () {
      * @returns {Boolean}       Whether or not to include the item
      */
     var filterControllerServiceTypes = function (item, args) {
+        if (!isParentExpanded(item)) {
+            return false;
+        }
+        
         // determine if the item matches the filter
         var matchesFilter = matchesRegex(item, args);
 
@@ -247,6 +263,47 @@ nf.Settings = (function () {
     };
     
     /**
+     * Formats the type by introducing expand/collapse where appropriate.
+     * 
+     * @param {type} row
+     * @param {type} cell
+     * @param {type} value
+     * @param {type} columnDef
+     * @param {type} dataContext
+     */
+    var typeFormatter = function (row, cell, value, columnDef, dataContext) {
+        var markup = '';
+        
+        var indent = 0;
+        var documentedType = dataContext;
+        while (documentedType.parent !== null) {
+            indent += 10;
+            documentedType = documentedType.parent;
+        }
+        
+        var padding = 3;
+        
+        // create the markup for the row
+        if (dataContext.children.length > 0) {
+            // determine how to render the expansion button
+            var expansionStyle = 'expanded';
+            if (dataContext.collapsed === true) {
+                expansionStyle = 'collapsed';
+            }
+            
+            markup += ('<span style="margin-top: 5px; margin-left: ' + indent + 'px;" class="expansion-button ' + expansionStyle + '"></span><span style="margin-left: ' + padding + 'px;">' + value + '</span>');
+        } else {
+            if (dataContext.parent === null) {
+                padding = 0;
+            }
+            
+            markup += ('<span style="margin-left: ' + (indent + padding) + 'px;">' + value + '</span>');
+        }
+        
+        return markup;
+    };
+    
+    /**
      * Initializes the new controller service dialog.
      */
     var initNewControllerServiceDialog = function () {
@@ -266,8 +323,8 @@ nf.Settings = (function () {
 
         // initialize the processor type table
         var controllerServiceTypesColumns = [
-            {id: 'type', name: 'Type', field: 'label', sortable: true, resizable: true},
-            {id: 'tags', name: 'Tags', field: 'tags', sortable: true, resizable: true}
+            {id: 'type', name: 'Type', field: 'label', formatter: typeFormatter, sortable: false, resizable: true},
+            {id: 'tags', name: 'Tags', field: 'tags', sortable: false, resizable: true}
         ];
         var controllerServiceTypesOptions = {
             forceFitColumns: true,
@@ -288,41 +345,67 @@ nf.Settings = (function () {
             property: $('#controller-service-type-filter-options').combo('getSelectedOption').value
         });
         controllerServiceTypesData.setFilter(filterControllerServiceTypes);
+        controllerServiceTypesData.getItemMetadata = function (index) {
+            var item = controllerServiceTypesData.getItem(index);
+            if (item && item.children.length > 0) {
+                return {
+                    selectable: false
+                };
+            } else {
+                return {};
+            }
+        };
 
         // initialize the sort
-        sort({
-            columnId: 'type',
-            sortAsc: true
-        }, controllerServiceTypesData);
+//        sort({
+//            columnId: 'type',
+//            sortAsc: true
+//        }, controllerServiceTypesData);
 
         // initialize the grid
         var controllerServiceTypesGrid = new Slick.Grid('#controller-service-types-table', controllerServiceTypesData, controllerServiceTypesColumns, controllerServiceTypesOptions);
         controllerServiceTypesGrid.setSelectionModel(new Slick.RowSelectionModel());
         controllerServiceTypesGrid.registerPlugin(new Slick.AutoTooltips());
         controllerServiceTypesGrid.setSortColumn('type', true);
-        controllerServiceTypesGrid.onSort.subscribe(function (e, args) {
-            sort({
-                columnId: args.sortCol.field,
-                sortAsc: args.sortAsc
-            }, controllerServiceTypesData);
-        });
+//        controllerServiceTypesGrid.onSort.subscribe(function (e, args) {
+//            sort({
+//                columnId: args.sortCol.field,
+//                sortAsc: args.sortAsc
+//            }, controllerServiceTypesData);
+//        });
         controllerServiceTypesGrid.onSelectedRowsChanged.subscribe(function (e, args) {
             if ($.isArray(args.rows) && args.rows.length === 1) {
-                var processorTypeIndex = args.rows[0];
-                var processorType = controllerServiceTypesGrid.getDataItem(processorTypeIndex);
+                var controllerServiceTypeIndex = args.rows[0];
+                var controllerServiceType = controllerServiceTypesGrid.getDataItem(controllerServiceTypeIndex);
+
+                // only allow selection of service implementations
+                if (controllerServiceType.children.length === 0) {
+                    // set the controller service type description
+                    if (nf.Common.isBlank(controllerServiceType.description)) {
+                        $('#controller-service-type-description').attr('title', '').html('<span class="unset">No description specified</span>');
+                    } else {
+                        $('#controller-service-type-description').text(controllerServiceType.description).ellipsis();
+                    }
 
-                // set the processor type description
-                if (nf.Common.isBlank(processorType.description)) {
-                    $('#controller-service-type-description').attr('title', '').html('<span class="unset">No description specified</span>');
+                    // populate the dom
+                    $('#controller-service-type-name').text(controllerServiceType.label).ellipsis();
+                    $('#selected-controller-service-name').text(controllerServiceType.label);
+                    $('#selected-controller-service-type').text(controllerServiceType.type);
+                }
+            }
+        });
+        controllerServiceTypesGrid.onClick.subscribe(function (e, args) {
+            var item = controllerServiceTypesData.getItem(args.row);
+            if (item && item.children.length > 0) {
+                if (!item.collapsed) {
+                    item.collapsed = true;
                 } else {
-                    $('#controller-service-type-description').text(processorType.description).ellipsis();
+                    item.collapsed = false;
                 }
-
-                // populate the dom
-                $('#controller-service-type-name').text(processorType.label).ellipsis();
-                $('#selected-controller-service-name').text(processorType.label);
-                $('#selected-controller-service-type').text(processorType.type);
+                controllerServiceTypesData.updateItem(item.id, item);
             }
+
+//                e.stopImmediatePropagation();
         });
 
         // wire up the dataview to the grid
@@ -348,30 +431,44 @@ nf.Settings = (function () {
             url: config.urls.controllerServiceTypes,
             dataType: 'json'
         }).done(function(response) {
+            var id = 0;
             var tags = [];
-            console.log(response);
 
             // begin the update
             controllerServiceTypesData.beginUpdate();
 
-            // go through each processor type
-            $.each(response.controllerServiceTypes, function (i, documentedType) {
-                var type = documentedType.type;
-
-                // create the row for the processor type
-                controllerServiceTypesData.addItem({
-                    id: i,
-                    label: nf.Common.substringAfterLast(type, '.'),
-                    type: type,
+            var addType = function (parentItem, documentedType) {
+                var item = {
+                    id: id++,
+                    label: nf.Common.substringAfterLast(documentedType.type, '.'),
+                    type: documentedType.type,
                     description: nf.Common.escapeHtml(documentedType.description),
                     tags: documentedType.tags.join(', '),
-                    baseType: documentedType.baseTypes
-                });
-
+                    parent: parentItem,
+                    children: [],
+                    collapsed: false
+                };
+                
+                // add the documented type
+                controllerServiceTypesData.addItem(item);
+                
                 // count the frequency of each tag for this type
                 $.each(documentedType.tags, function (i, tag) {
                     tags.push(tag.toLowerCase());
                 });
+                
+                // add each of its children
+                $.each(documentedType.childTypes, function (_, documentedChildType) {
+                    var childItem = addType(item, documentedChildType);
+                    item.children.push(childItem);
+                });
+                
+                return item;
+            };
+
+            // go through each processor type
+            $.each(response.controllerServiceTypes, function (i, documentedType) {
+                addType(null, documentedType);
             });
 
             // end the udpate
@@ -456,7 +553,6 @@ nf.Settings = (function () {
             url: config.urls.reportingTaskTypes,
             dataType: 'json'
         }).done(function(response) {
-            console.log(response);
         });
         
     };
@@ -552,7 +648,7 @@ nf.Settings = (function () {
         /**
          * Shows the details of the controller service at the specified row.
          * 
-         * @param {type} row
+         * @param {documentedType} row
          */
         showControllerServiceDetails: function (row) {
             
@@ -561,7 +657,7 @@ nf.Settings = (function () {
         /**
          * Shows the details of the reporting task at the specified row.
          * 
-         * @param {type} row
+         * @param {documentedType} row
          */
         showReportingTaskDetails: function (row) {