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 2021/12/13 21:01:52 UTC

[nifi] branch main updated: [NIFI-9423-NIFI-9429]: Show icon and tooltip for Parameters with leading and/or trailing whitespace (#5569)

This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 3d5f357  [NIFI-9423-NIFI-9429]: Show icon and tooltip for Parameters with leading and/or trailing whitespace (#5569)
3d5f357 is described below

commit 3d5f357de896e81084049df3ad10ca64e6390f65
Author: M Tien <56...@users.noreply.github.com>
AuthorDate: Mon Dec 13 13:01:42 2021 -0800

    [NIFI-9423-NIFI-9429]: Show icon and tooltip for Parameters with leading and/or trailing whitespace (#5569)
    
    * NIFI-9423 - Show icon and tooltip for Parameter values that have leading and/or trailing whitespaces
    
    NIFI-9429 - Parameters should allow blank values that are non-null (only whitespace)
    
    * - Update areas to clean up tooltips in parameter values
    - Show whitespaces and ellipsis in parameter and property values and tooltips
    - Update serializeValue to accommodate for blank values
    
    * - Address review findings
    
    * - Remove commented out code
    
    * - Add multiline check for ellipsis
    
    * NIFI-9459 - Empty string checked will disable Edit Parameter value field on dialog open
    
    * - Add multi-line style to parameter and property table
    
    * - Safely insert title attribute content
    
    * - Fix Edit Parameter bug that clears textarea for sensitive and empty string values on dialog open
    
    This closes #5569
---
 .../nifi-web-ui/src/main/webapp/css/main.css       | 14 +++++
 .../jquery/propertytable/jquery.propertytable.js   | 31 +++++-----
 .../webapp/js/nf/canvas/nf-parameter-contexts.js   | 66 +++++++++++++++++++---
 .../nifi-web-ui/src/main/webapp/js/nf/nf-common.js | 26 +++++++--
 4 files changed, 112 insertions(+), 25 deletions(-)

diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
index fc6c807..8f0500f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
@@ -53,6 +53,20 @@ div.context-menu-provenance {
     overflow: hidden;
 }
 
+.ellipsis-white-space-pre {
+    white-space: pre;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+/* max 1 line text with ellipsis - works in Chrome and Firefox */
+.multi-line-clamp-ellipsis {
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 1;
+    overflow: hidden;
+}
+
 .ellipsis.multiline {
     white-space: normal;
 }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js
index 8869172..dfa9aa1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js
@@ -1292,7 +1292,7 @@
         // function for formatting the property value
         var valueFormatter = function (row, cell, value, columnDef, dataContext) {
             var valueMarkup;
-            var nameWidthOffset = 0;
+            var valueWidthOffset = 0;
             if (nfCommon.isDefinedAndNotNull(value)) {
                 // get the property descriptor
                 var descriptors = table.data('descriptors');
@@ -1323,14 +1323,20 @@
                         if (!resolvedAllowableValue && nfCommon.isDefinedAndNotNull(propertyDescriptor.identifiesControllerService)) {
                             valueMarkup = '<span class="table-cell blank">Incompatible Controller Service Configured</div>';
                         } else {
-                            valueMarkup = '<div class="table-cell value"><pre class="ellipsis">' + nfCommon.escapeHtml(value) + '</pre></div>';
+                            valueWidthOffset = 10;
 
-                            // add a tooltip icon for trailing and/or leading whitespace
+                            // check for multi-line
+                            if (nfCommon.isMultiLine(value)) {
+                                valueMarkup = '<div class="table-cell value"><div class="ellipsis-white-space-pre multi-line-clamp-ellipsis">' + nfCommon.escapeHtml(value) + '</div></div>';
+                            } else {
+                                valueMarkup = '<div class="table-cell value"><div class="ellipsis-white-space-pre">' + nfCommon.escapeHtml(value) + '</div></div>';
+                            }
+
+                            // check for leading or trailing whitespace
                             if (nfCommon.hasLeadTrailWhitespace(value)) {
                                 valueMarkup += '<div class="fa fa-info" alt="Info" style="float: right;"></div>';
-                                nameWidthOffset = 20; // 10 + icon width (10)
+                                valueWidthOffset = 20;
                             }
-
                         }
                     }
                 }
@@ -1343,7 +1349,8 @@
             if (dataContext.type === 'required') {
                 content.addClass('required');
             }
-            content.find('.ellipsis').width(columnDef.width - 10 - nameWidthOffset).ellipsis();
+            var contentValue = content.find('.ellipsis-white-space-pre');
+            contentValue.attr('title', contentValue.text()).width(columnDef.width - 10 - valueWidthOffset);
 
             // return the appropriate markup
             return $('<div />').append(content).html();
@@ -1789,13 +1796,11 @@
             if (whitespaceIcon.length && !whitespaceIcon.data('qtip')) {
                 var whitespaceTooltip = nfCommon.formatWhitespaceTooltip();
 
-                if (nfCommon.isDefinedAndNotNull(whitespaceTooltip)) {
-                    whitespaceIcon.qtip($.extend({},
-                        nfCommon.config.tooltipConfig,
-                        {
-                            content: whitespaceTooltip
-                        }));
-                }
+                whitespaceIcon.qtip($.extend({},
+                    nfCommon.config.tooltipConfig,
+                    {
+                        content: whitespaceTooltip
+                    }));
             }
         });
     };
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
index 146b627..2503d67 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
@@ -196,6 +196,9 @@
      * Reset the dialog.
      */
     var resetDialog = function () {
+        // clean up any tooltips that may have been generated
+        nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
         $('#parameter-context-name').val('');
         $('#parameter-context-name-read-only').text('');
 
@@ -227,9 +230,6 @@
 
         // reset the current parameter context
         currentParameterContextEntity = null;
-
-        // clean up any tooltips that may have been generated
-        nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle');
     };
 
     /**
@@ -861,6 +861,9 @@
                 parameterContext: parameterContext
             });
 
+            // clean up any tooltips that may have been generated
+            nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
             if (_.isNil(param.id)) {
                 var matchingParameter = _.find(parameterData.getItems(), {name: parameter.name});
                 if (_.isNil(matchingParameter)) {
@@ -993,13 +996,13 @@
         var serializedValue;
 
         var value = input.val();
-        if (!isChecked && _.isEmpty(value)) {
+        if (!isChecked && value === '') {
             value = null;
         }
 
         var hasChanged = parameter.value !== value;
 
-        if (!nfCommon.isBlank(value)) {
+        if (nfCommon.isDefinedAndNotNull(value)) {
             // if the value is sensitive and the user has not made a change
             if (!_.isEmpty(parameter) && parameter.sensitive === true && input.hasClass('sensitive') && parameter.isNew === false) {
                 serializedValue = parameter.previousValue;
@@ -1007,7 +1010,6 @@
             } else {
                 // value is not sensitive or it is sensitive and the user has changed it then always take the current value
                 serializedValue = value;
-
                 // if the param is sensitive and the param value has not "changed", that means it matches the mask and it should still be considered changed
                 if (!hasChanged && !_.isEmpty(parameter) && parameter.sensitive === true && parameter.isNew === false) {
                     hasChanged = true;
@@ -1061,6 +1063,9 @@
                 parameterContext: originalParameter.parameterContext
             });
 
+            // clean up any tooltips that may have been generated
+            nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
             // update row for the parameter
             parameterData.updateItem(originalParameter.id, parameter);
 
@@ -1129,6 +1134,9 @@
      * @returns {*}
      */
     var updateParameterContext = function (parameterContextEntity) {
+        // clean up any tooltips that may have been generated
+        nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
         var parameters = marshalParameters();
         var inheritedParameterContexts = marshalInheritedParameterContexts();
 
@@ -1831,6 +1839,7 @@
         };
 
         var valueFormatter = function (row, cell, value, columnDef, dataContext) {
+            var valueWidthOffset = 0;
             if (dataContext.sensitive === true && !_.isNil(value)) {
                 return '<span class="table-cell sensitive">Sensitive value set</span>';
             } else if (value === '') {
@@ -1838,7 +1847,28 @@
             } else if (_.isNil(value)) {
                 return '<span class="unset">No value set</span>';
             } else {
-                return nfCommon.escapeHtml(value);
+                var valueMarkup;
+                valueWidthOffset = 15;
+
+                // check for multi-line
+                if (nfCommon.isMultiLine(value)) {
+                    valueMarkup = '<div class="table-cell value"><div class="ellipsis-white-space-pre multi-line-clamp-ellipsis">' + nfCommon.escapeHtml(value) + '</div></div>';
+                } else {
+                    valueMarkup = '<div class="table-cell value"><div class="ellipsis-white-space-pre">' + nfCommon.escapeHtml(value) + '</div></div>';
+                }
+
+                // check for leading or trailing whitespace
+                if (nfCommon.hasLeadTrailWhitespace(value)) {
+                    valueMarkup += '<div class="fa fa-info" alt="Info" style="float: right;"></div>';
+                    valueWidthOffset = 30;
+                }
+
+                // adjust the width accordingly
+                var content = $(valueMarkup);
+                var contentValue = content.find('.ellipsis-white-space-pre');
+                contentValue.attr('title', contentValue.text()).width(columnDef.width - valueWidthOffset);
+
+                return $('<div />').append(content).html();
             }
         };
 
@@ -1922,6 +1952,9 @@
 
                 // determine the desired action
                 if (target.hasClass('delete-parameter')) {
+                    // clean any tooltips that may have been added for this item
+                    nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
                     if (!parameter.isNew) {
                         // mark the parameter in question for removal and refresh the table
                         parameterData.updateItem(parameter.id, $.extend(parameter, {
@@ -1978,7 +2011,10 @@
                         $('#parameter-sensitive-radio-button').prop('disabled', true);
                         $('#parameter-not-sensitive-radio-button').prop('disabled', true);
                         if (parameter.value === '') {
-                            $('#parameter-set-empty-string-field').removeClass('checkbox-unchecked').addClass('checkbox-checked');
+                            if (!parameter.sensitive) {
+                                $('#parameter-set-empty-string-field').removeClass('checkbox-unchecked').addClass('checkbox-checked');
+                                $('#parameter-value-field').prop('disabled', true);
+                            }
                         } else {
                             $('#parameter-set-empty-string-field').removeClass('checkbox-checked').addClass('checkbox-unchecked');
                         }
@@ -1988,6 +2024,7 @@
                             $('#parameter-not-sensitive-radio-button').prop('checked', false);
                             if (!_.isNil(parameter.value)) {
                                 $('#parameter-value-field').addClass('sensitive').val(nfCommon.config.sensitiveText).select();
+                                $('#parameter-set-empty-string-field').removeClass('checkbox-checked').addClass('checkbox-unchecked');
                             }
                         } else {
                             $('#parameter-sensitive-radio-button').prop('checked', false);
@@ -2124,6 +2161,17 @@
                         }));
                 }
             }
+
+            var whitespaceIcon = $(this).find('div.fa-info');
+            if (whitespaceIcon.length && !whitespaceIcon.data('qtip')) {
+                var whitespaceTooltip = nfCommon.formatWhitespaceTooltip();
+
+                whitespaceIcon.qtip($.extend({},
+                    nfCommon.config.tooltipConfig,
+                    {
+                        content: whitespaceTooltip
+                    }));
+            }
         });
     };
 
@@ -2202,6 +2250,8 @@
 
         $('#add-parameter').on('click', function () {
             var closeHandler = function () {
+                // clean up any tooltips that may have been generated
+                nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
                 resetParameterDialog();
             };
 
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index aa646c0..86483c9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -1008,16 +1008,20 @@
         },
 
         /**
-         * Checks the specified value for leading and/or trailing whitespace.
+         * Constant regex for leading and/or trailing whitespace.
+         */
+        LEAD_TRAIL_WHITE_SPACE_REGEX: /^[ \s]+|[ \s]+$/,
+
+        /**
+         * Checks the specified value for leading and/or trailing whitespace only.
          *
          * @argument {string} value     The value to check
          */
         hasLeadTrailWhitespace : function (value) {
-            if ( !value || value.trim().length === 0 ) {
+            if (nfCommon.isBlank(value)) {
                 return false;
             }
-            var leadOrTrailWhitespaceRegex = /^[ \s]+|[ \s]+$/;
-            return leadOrTrailWhitespaceRegex.test(value);
+            return nfCommon.LEAD_TRAIL_WHITE_SPACE_REGEX.test(value);
         },
 
         /**
@@ -1817,6 +1821,20 @@
             return key.split('.').reduce(function(o,x){
                 return(typeof o === undefined || o === null)? o : (typeof o[x] == 'function')?o[x]():o[x];
             }, obj);
+        },
+
+        /**
+         * Checks if the given value has multi-lines.
+         *
+         * @param value to check
+         * @returns {boolean}
+         */
+        isMultiLine: function (value) {
+            const multiLineMatcher = /\n/.exec(value);
+            if (multiLineMatcher) {
+                return true;
+            }
+            return false;
         }
 
     };