You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by pi...@apache.org on 2022/08/26 10:05:25 UTC

[atlas] branch master updated: ATLAS-4611 : (UI)Add text-editor for string attribute value of Business Metadata and for description field while creating Classification and Business Metadata

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

pinal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new d034bad23 ATLAS-4611 : (UI)Add text-editor for string attribute value of Business Metadata and for description field while creating Classification and Business Metadata
d034bad23 is described below

commit d034bad23188f4292ee9befb2414d621b5be8945
Author: Farhan Khan <fa...@cloudera.com>
AuthorDate: Wed Aug 24 17:10:44 2022 +0530

    ATLAS-4611 : (UI)Add text-editor for string attribute value of Business Metadata and for description field while creating Classification and Business Metadata
    
    Signed-off-by: Pinal Shah <pi...@freestoneinfotech.com>
---
 dashboardv2/public/css/scss/override.scss          |  8 ++-
 dashboardv2/public/css/scss/texteditor.scss        | 59 ++++++++++++++---
 .../public/js/external_lib/trumbowyg/trumbowyg.js  |  2 +-
 .../BusinessMetadataAttributeItemView_tmpl.html    |  5 +-
 .../BusinessMetadataDetailLayoutView_tmpl.html     | 18 +++++-
 .../CreateBusinessMetadataLayoutView_tmpl.html     |  2 +-
 .../glossary/GlossaryDetailLayoutView_tmpl.html    |  2 +-
 .../js/templates/tag/CreateTagLayoutView_tmpl.html |  2 +-
 .../tag/TagAttributeDetailLayoutView_tmpl.html     | 15 ++++-
 dashboardv2/public/js/utils/CommonViewFunction.js  | 39 +++--------
 dashboardv2/public/js/utils/Helper.js              |  6 ++
 dashboardv2/public/js/utils/Utils.js               | 75 +++++++++++++++++++---
 .../BusinessMetadataDetailLayoutView.js            | 10 ++-
 .../BusinessMetadataTableLayoutView.js             |  7 +-
 .../CreateBusinessMetadataLayoutView.js            |  4 +-
 .../views/entity/EntityBusinessMetaDataItemView.js | 58 ++++++++++++++++-
 .../js/views/entity/EntityBusinessMetaDataView.js  | 22 +++++--
 .../js/views/glossary/GlossaryDetailLayoutView.js  |  2 +-
 .../public/js/views/tag/CreateTagLayoutView.js     | 16 ++++-
 .../js/views/tag/TagAttributeDetailLayoutView.js   | 10 ++-
 dashboardv2/public/js/views/tag/TagLayoutView.js   |  4 +-
 dashboardv3/public/css/scss/override.scss          |  8 ++-
 dashboardv3/public/css/scss/texteditor.scss        | 59 ++++++++++++++---
 .../public/js/external_lib/trumbowyg/trumbowyg.js  |  2 +-
 .../BusinessMetadataAttributeItemView_tmpl.html    |  5 +-
 .../BusinessMetadataDetailLayoutView_tmpl.html     | 15 ++++-
 .../CreateBusinessMetadataLayoutView_tmpl.html     |  2 +-
 .../glossary/GlossaryDetailLayoutView_tmpl.html    |  2 +-
 .../js/templates/tag/CreateTagLayoutView_tmpl.html |  2 +-
 .../tag/TagAttributeDetailLayoutView_tmpl.html     | 15 ++++-
 dashboardv3/public/js/utils/CommonViewFunction.js  | 36 ++++-------
 dashboardv3/public/js/utils/Helper.js              |  6 ++
 dashboardv3/public/js/utils/Utils.js               | 74 ++++++++++++++++++---
 .../BusinessMetadataDetailLayoutView.js            | 10 ++-
 .../BusinessMetadataTableLayoutView.js             |  7 +-
 .../CreateBusinessMetadataLayoutView.js            |  4 +-
 .../views/entity/EntityBusinessMetaDataItemView.js | 60 ++++++++++++++++-
 .../js/views/entity/EntityBusinessMetaDataView.js  | 23 +++++--
 .../js/views/glossary/GlossaryDetailLayoutView.js  |  2 +-
 .../search/tree/ClassificationTreeLayoutView.js    |  4 +-
 .../public/js/views/tag/CreateTagLayoutView.js     | 16 ++++-
 .../js/views/tag/TagAttributeDetailLayoutView.js   | 10 ++-
 42 files changed, 585 insertions(+), 143 deletions(-)

diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss
index f98c7fcb7..7a14abf6d 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -573,7 +573,7 @@ div.columnmanager-dropdown-container {
     margin-right: 0px !important;
 }
 
-.glossary-longdescription-wrapper {
+.longdescription-wrapper {
     display: inline-block;
     height: 100px;
     background-color: #fff !important;
@@ -616,4 +616,10 @@ div.columnmanager-dropdown-container {
 
 .user-circle {
     display: inline;
+}
+
+.business-metadata-detail-attr {
+    ul {
+        list-style: disc
+    }
 }
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/texteditor.scss b/dashboardv2/public/css/scss/texteditor.scss
index 275bdcc3d..e05cf4d7d 100644
--- a/dashboardv2/public/css/scss/texteditor.scss
+++ b/dashboardv2/public/css/scss/texteditor.scss
@@ -19,14 +19,29 @@
 
 .trumbowyg {
     border-radius: 4px !important;
-    min-height: 150px !important;
+    min-height: 106px !important;
 
     .trumbowyg-button-pane {
-        background-color: #f6f7fb !important;
+        background: none;
+        border-bottom: none;
+        position: absolute;
+        bottom: 0px;
+
+        button {
+            transition: none;
+        }
+    }
+
+    .trumbowyg-button-pane-hidden {
+        display: none;
+    }
+
+    .trumbowyg-button-pane::after {
+        background: none !important;
     }
 
     .trumbowyg-editor {
-        min-height: 150px !important;
+        min-height: 70px !important;
         overflow-wrap: break-word;
     }
 
@@ -35,7 +50,19 @@
     }
 
     .trumbowyg-textarea {
-        min-height: 150px !important;
+        min-height: 106px !important;
+    }
+
+    .trumbowyg-button-pane .trumbowyg-button-group::after {
+        height: 25px;
+        vertical-align: middle;
+    }
+
+    .trumbowyg-button-pane button.trumbowyg-active,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):focus,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):hover {
+        background-color: #e8e9ee;
+        border-radius: 20px;
     }
 }
 
@@ -62,15 +89,31 @@
     width: 101px !important;
 }
 
-.trumbowyg-h1-dropdown-button{
+.trumbowyg-h1-dropdown-button {
     font-size: 36px !important;
 }
-.trumbowyg-h2-dropdown-button{
+
+.trumbowyg-h2-dropdown-button {
     font-size: 30px !important;
 }
-.trumbowyg-h3-dropdown-button{
+
+.trumbowyg-h3-dropdown-button {
     font-size: 24px !important;
 }
-.trumbowyg-h4-dropdown-button{
+
+.trumbowyg-h4-dropdown-button {
     font-size: 18px !important;
+}
+
+.small-texteditor {
+    .trumbowyg-button-pane button {
+        width: 25px !important;
+        height: 25px !important;
+    }
+    .trumbowyg-button-pane button.trumbowyg-active,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):focus,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):hover {
+        background-color: #e8e9ee;
+        border-radius: 20px;
+    }
 }
\ No newline at end of file
diff --git a/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js b/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js
index 7ef6d172e..fca766456 100644
--- a/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js
+++ b/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js
@@ -9,4 +9,4 @@
  *         Twitter : @AlexandreDemode
  *         Website : alex-d.fr
  */
-jQuery.trumbowyg={langs:{en:{viewHTML:"Plain Text",undo:"Undo",redo:"Redo",formatting:"Formatting",p:"Paragraph",blockquote:"Quote",code:"Code",header:"Header",bold:"Bold",italic:"Italic",strikethrough:"Strikethrough",underline:"Underline",strong:"Strong",em:"Emphasis",del:"Deleted",superscript:"Superscript",subscript:"Subscript",unorderedList:"Unordered list",orderedList:"Ordered list",insertImage:"Insert Image",link:"Link",createLink:"Insert link",unlink:"Remove link",justifyLeft:"Alig [...]
\ No newline at end of file
+jQuery.trumbowyg={langs:{en:{viewHTML:"Plain Text",undo:"Undo",redo:"Redo",formatting:"Formatting",p:"Paragraph",blockquote:"Quote",code:"Code",header:"Header",bold:"Bold",italic:"Italic",strikethrough:"Strikethrough",underline:"Underline",strong:"Strong",em:"Emphasis",del:"Deleted",superscript:"Superscript",subscript:"Subscript",unorderedList:"Unordered list",orderedList:"Ordered list",insertImage:"Insert Image",link:"Link",createLink:"Insert link",unlink:"Remove link",justifyLeft:"Alig [...]
\ No newline at end of file
diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
index 3d316f688..aedb6dabe 100644
--- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
+++ b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
@@ -95,9 +95,12 @@
     <div class="form-group" data-id="stringLengthContainer">
         <div class="stringlength-container">
             <label class="control-label col-sm-3 required" for="name">Max length</label>
-            <div class="col-sm-8">
+            <div class="col-sm-6">
                 <input type="number" class="form-control stringLengthVal require" data-id="stringLength" placeholder="Maximum length">
             </div>
+            <label class="control-label">
+                <i class="fa fa-question-circle help-btn" title="<div>String length limit includes any HTML formatting tags used.</div>" data-html="true"></i>
+            </label>
         </div>
     </div>
     <div class="form-group entity-businessMetadata-selector">
diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
index d8a2b5b87..d7230c034 100644
--- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
@@ -18,9 +18,21 @@
     <div class="fontLoader">
         <i class="fa fa-refresh fa-spin-custom"></i>
     </div>
-    <div class="tagDetail clearfix form-horizontal col-sm-12">
+    <div class="tagDetail clearfix col-sm-12">
         <h1 class="title"><span data-id="title"></span></h1>
-        <p class="form-group col-sm-12" data-id="description"></p>
+        <div class="long-description-container form-group clearfix">
+            <span class="pull-left text-muted">Description:&nbsp;</span>
+            <div class="isTextTypeBtn-wrapper pull-right">
+                <span class="text-muted pull-left">Formatted</span>
+                <label class="switch pull-left">
+                    <input type="checkbox" class="switch-input" name="textType" value="text">
+                    <span class="switch-slider"></span>
+                </label>
+                <span class="text-muted">Plain</span>
+            </div>
+            <div class="longdescription-wrapper form-control col-sm-12">
+                <div class="long-description" name="longDescription" data-id="description" disabled></div>
+            </div>
+        </div>
     </div>
-</div>
 </div>
\ No newline at end of file
diff --git a/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
index a78614d15..5a43a7662 100644
--- a/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
@@ -31,7 +31,7 @@
     <div class="form-group">
         <label class="control-label col-sm-2" for="description">Description</label>
         <div class="col-sm-10">
-            <input class="form-control" data-id="description" value="{{description}}" placeholder="Description" />
+            <textarea class="form-control customTextEditor" data-id="description" value="{{description}}" placeholder="Description" ></textarea>
         </div>
     </div>
     {{/if}}
diff --git a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
index c8b55f783..b3c642e9b 100644
--- a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
@@ -37,7 +37,7 @@
                 </label>
                 <span class="text-muted">Plain</span>
             </div>
-            <div class="glossary-longdescription-wrapper form-control col-sm-12">
+            <div class="longdescription-wrapper form-control col-sm-12">
                 <div class="long-description" name="longDescription" data-id="longDescription" disabled></div>
             </div>
         </div>
diff --git a/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html
index 27ea91247..28f0baa02 100644
--- a/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html
@@ -30,7 +30,7 @@
     <div class="form-group">
         <label class="control-label col-sm-2 required" for="description">Description</label>
         <div class="col-sm-10">
-            <input class="form-control" data-id="description" value="{{description}}" placeholder="Description(required)" />
+            <textarea class="form-control customTextEditor" data-id="description" value="{{description}}" placeholder="Description(required)" ></textarea>
         </div>
     </div>
     {{#if create}}
diff --git a/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
index d12785bd8..fd68a21aa 100644
--- a/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
@@ -21,7 +21,20 @@
     <div class="tagDetail clearfix form-horizontal col-sm-12">
         <h1 class="row title"><span data-id="title"></span></h1>
         <button type="button" data-id="editButton" class="btn btn-sm btn-action pull-right"><i class="fa fa-pencil"></i></button>
-        <p class="form-group" data-id="description"></p>
+        <div class="long-description-container form-group clearfix">
+            <span class="pull-left text-muted">Description:&nbsp;</span>
+            <div class="isTextTypeBtn-wrapper pull-right">
+                <span class="text-muted pull-left">Formatted</span>
+                <label class="switch pull-left">
+                    <input type="checkbox" class="switch-input" name="textType" value="text">
+                    <span class="switch-slider"></span>
+                </label>
+                <span class="text-muted">Plain</span>
+            </div>
+            <div class="longdescription-wrapper form-control col-sm-12">
+                <div class="long-description" name="longDescription" data-id="description" disabled></div>
+            </div>
+        </div>
         <div class="superType form-group" style="display:none">
             <label class="control-label-sm-pr pull-left">Direct super-classifications:</label>
             <div data-id="superType" class="btn-inline">
diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js
index f15b32e1c..4ce47a13d 100644
--- a/dashboardv2/public/js/utils/CommonViewFunction.js
+++ b/dashboardv2/public/js/utils/CommonViewFunction.js
@@ -695,9 +695,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
             //Below condition is added for sanitizing the longDescription text against XSS attack.
             if (model) {
                 var longDescriptionContent = isGlossaryView ? model.get('longDescription') : model.longDescription,
-                    sanitizeLongDescriptionContent;
+                    sanitizeLongDescriptionContent = "";
                 if (longDescriptionContent) {
-                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent(longDescriptionContent);
+                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent({ data: longDescriptionContent });
                     isGlossaryView ? model.set("longDescription", sanitizeLongDescriptionContent) : model.longDescription = sanitizeLongDescriptionContent;
                 }
             }
@@ -718,7 +718,6 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
                 view = new CreateEditCategoryTermLayoutView({ "glossaryCollection": collection, "modelJSON": model });
                 title = (isTermView ? 'Term' : 'Category');
             }
-
             var modal = new Modal({
                 "title": ((model ? "Update " : "Create ") + title),
                 "content": view,
@@ -726,38 +725,19 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
                 "okCloses": false,
                 "okText": model ? "Update" : "Create",
                 "allowCancel": true,
-                "width": "765px"
+                "width": "640px"
             }).open();
-            modal.$el.find('input[data-id=shortDescription]').on('input keydown', function(e) {
-                $(this).val($(this).val().replace(/\s+/g, ' '));
-            });
             modal.$el.find('button.ok').attr("disabled", "true");
             var longDescriptionEditor = modal.$el.find('textarea[data-id=longDescription]'),
-                okBtn = modal.$el.find('button.ok');
-            longDescriptionEditor.trumbowyg({
-                btns: [
-                    ['formatting'],
-                    ['strong', 'em', 'underline', 'del'],
-                    ['link'],
-                    ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
-                    ['unorderedList', 'orderedList'],
-                    ['viewHTML']
-                ],
-                removeformatPasted: true,
-                urlProtocol: true,
-                defaultLinkTarget: '_blank'
-            }).on('tbwchange', function() {
-                okBtn.removeAttr("disabled");
-            });
+                okBtn = modal.$el.find('button.ok'),
+                modalOkBtn = function() {
+                    okBtn.removeAttr("disabled");
+                };
+            Utils.addCustomTextEditor({ selector: longDescriptionEditor, callback: modalOkBtn, initialHide: false });
             modal.on('ok', function() {
                 modal.$el.find('button.ok').showButtonLoader();
                 //Below condition is added for sanitizing the longDescription text against XSS attack.
-                var editorContent, cleanContent;
-                editorContent = longDescriptionEditor.trumbowyg('html');
-                if (editorContent !== "") {
-                    cleanContent = Utils.sanitizeHtmlContent(editorContent);
-                    longDescriptionEditor.trumbowyg('html', cleanContent);
-                }
+                longDescriptionEditor.trumbowyg('html', Utils.sanitizeHtmlContent({ selector: longDescriptionEditor }));
                 //End
                 CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, "modal": modal }, options));
             });
@@ -766,6 +746,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
                 if (options.onModalClose) {
                     options.onModalClose()
                 }
+                longDescriptionEditor.trumbowyg('closeModal');
             });
         });
     }
diff --git a/dashboardv2/public/js/utils/Helper.js b/dashboardv2/public/js/utils/Helper.js
index 0ba1b6c4e..8efeeb9c5 100644
--- a/dashboardv2/public/js/utils/Helper.js
+++ b/dashboardv2/public/js/utils/Helper.js
@@ -128,6 +128,12 @@ define(['require',
     $("body").on('click', '.btn', function() {
         $(this).blur();
     });
+    $('body').on('click', function(e) {
+        if ($(e.target).hasClass('trumbowyg-editor-hidden')) {
+            $('.trumbowyg').find('.trumbowyg-button-pane').removeClass('trumbowyg-button-pane-hidden');
+            $('.trumbowyg').css('border', '1px solid #8fa5b1');
+        }
+    });
     $('body').on('keyup input', '.modal-body', function(e) {
         var target = e.target,
             isGlossary = (e.target.dataset.id === "searchTerm" || e.target.dataset.id === "searchCategory") ? true : false; // assign term/category modal
diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js
index f3126db75..eb0588903 100644
--- a/dashboardv2/public/js/utils/Utils.js
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, DOMPurify) {
+define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, DOMPurify) {
     'use strict';
 
     var Utils = {};
@@ -952,14 +952,7 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
         }
         return dateValue;
     }
-    //-----------------------------------------DOMPurify--------------------------------------
-    //This below function expects string that needs to be sanitize against XSS attack.
-    Utils.sanitizeHtmlContent = function(string) {
-        if (string) {
-            return DOMPurify.sanitize(string, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] });
-        }
-    }
-    //----------------------------------------------------------------------------------------
+
     //------------------------------------------------idleTimeout-----------------------------
     $.fn.idleTimeout = function(userRuntimeConfig) {
 
@@ -1227,7 +1220,69 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
 
         });
     };
-
     //------------------------------------------------
+
+    //--------------------------------------Custom Text Editor-----------------------------------//
+    Utils.addCustomTextEditor = function(options) {
+        var selector = options.selector ? options.selector : ".customTextEditor",
+            defaultBtns = [
+                ['formatting'],
+                ['strong', 'em', 'underline', 'del'],
+                ['link'],
+                ['unorderedList', 'orderedList'],
+                ['viewHTML']
+            ],
+            smallTextEditorBtn = [
+                ['strong', 'em', 'underline', 'del'],
+                ['link'],
+                ['unorderedList', 'orderedList'],
+            ],
+            customBtnDefs = {
+                formatting: {
+                    dropdown: ['p', 'h1', 'h2', 'h3', 'h4'],
+                    ico: 'p'
+                }
+            },
+            $btnPane, $parent;
+        $(selector).trumbowyg({
+            btns: options.small ? smallTextEditorBtn : defaultBtns,
+            autogrow: true,
+            removeformatPasted: true,
+            urlProtocol: true,
+            defaultLinkTarget: '_blank',
+            btnsDef: options.small ? {} : customBtnDefs
+        }).on('tbwinit', function() {
+            $btnPane = $(this).parent().find('.trumbowyg-button-pane');
+            $parent = $(this).parent();
+            if (options.small) {
+                $parent.addClass('small-texteditor');
+            }
+            if (!options.initialHide) {
+                $btnPane.addClass('trumbowyg-button-pane-hidden');
+                $parent.css('border', '1px solid #e8e9ee');
+            }
+        }).on('tbwblur', function(e) {
+            $btnPane.addClass('trumbowyg-button-pane-hidden');
+            $parent.css('border', '1px solid #e8e9ee');
+        }).on('tbwfocus', function(e) {
+            $btnPane.removeClass('trumbowyg-button-pane-hidden');
+            $parent.css('border', '1px solid #8fa5b1');
+        }).on('tbwchange', function(e) {
+            options.callback ? options.callback(e) : null;
+        }).on('tbwmodalopen', function(e) {
+            $('input[name="title"], input[name="target"]').parent().css('display', 'none');
+        });
+    }
+
+    Utils.sanitizeHtmlContent = function(options) {
+        var editorContent, cleanedContent;
+        editorContent = options.selector ? $(options.selector).trumbowyg('html') : options.data;
+        if (options && editorContent) {
+            cleanedContent = DOMPurify.sanitize(editorContent, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] });
+        }
+        return cleanedContent;
+    }
+    //-----------------------------------------END---------------------//
+
     return Utils;
 });
diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
index 422808b82..b3d1ff337 100644
--- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
+++ b/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
@@ -32,11 +32,16 @@ define(['require',
             /** ui selector cache */
             ui: {
                 title: '[data-id="title"]',
-                description: '[data-id="description"]'
+                description: '[data-id="description"]',
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
                 var events = {};
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.renderDetail();
+                };
                 return events;
             },
             /**
@@ -46,6 +51,7 @@ define(['require',
             initialize: function(options) {
                 _.extend(this, _.pick(options, 'model'));
                 $('body').addClass("detail-page");
+                this.isTextTypeChecked = false;
             },
             onRender: function() {
                 this.renderDetail();
@@ -53,7 +59,7 @@ define(['require',
             renderDetail: function() {
                 this.ui.title.html('<span>' + this.model.get('name') + '</span>');
                 if (this.model.get('description')) {
-                    this.ui.description.text(this.model.get('description'));
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get('description')) : this.ui.description.html(this.model.get('description'));
                 }
             },
             onDestroy: function() {
diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
index 6527eeb27..ccff1fdaf 100644
--- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
+++ b/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
@@ -215,6 +215,7 @@ define(['require',
                         isNewBusinessMetadata: isNewBusinessMetadata
                     });
                     that.RModal.show(that.view);
+                    Utils.addCustomTextEditor({ small: false });
                 });
             },
             renderTableLayoutView: function() {
@@ -296,7 +297,11 @@ define(['require',
                         editable: false,
                         formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                             fromRaw: function(rawValue, model) {
-                                return _.escape(model.get('description'));
+                                var description = model.get('description');
+                                if (description.length > 50) {
+                                    description = description.substr(0, 50) + "...";
+                                }
+                                return description;
                             }
                         })
                     },
diff --git a/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js b/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
index 21bb663ab..165b99500 100644
--- a/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
+++ b/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
@@ -223,7 +223,7 @@ define(['require',
                 };
                 this.loaderStatus(true);
                 var name = this.ui.name.val(),
-                    description = this.ui.description.val();
+                    description = Utils.sanitizeHtmlContent({ data: this.ui.description.val() });
                 var attributeObj = this.collection.toJSON();
                 if (this.collection.length === 1 && this.collection.first().get("name") === "") {
                     attributeObj = [];
@@ -240,7 +240,7 @@ define(['require',
                         "version": 1,
                         "typeVersion": "1.1",
                         "name": name.trim(),
-                        "description": description.trim(),
+                        "description": description ? description.trim() : "",
                         "attributeDefs": attributeObj
                     }]
                 };
diff --git a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js
index ff285068d..ad5e28e94 100644
--- a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js
+++ b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js
@@ -100,6 +100,32 @@ define(['require',
                         }
                     }
                 });
+                this.listenTo(this.searchVent, 'BusinessMetaAttribute:Edit', function() {
+                    _.each(that.model.attributes, function(obj) {
+                        if (obj.key) {
+                            if (obj.typeName === "string") {
+                                obj.value = Utils.sanitizeHtmlContent({ data: obj.value });
+                            }
+                            Utils.addCustomTextEditor({
+                                small: true,
+                                selector: "#" + obj.key,
+                                initialHide: false,
+                                callback: function(e) {
+                                    var key = $(e.target).data("key"),
+                                        businessMetadata = $(e.target).data("businessMetadata"),
+                                        typeName = $(e.target).data("typename"),
+                                        updateObj = that.model.toJSON();
+                                    if (_.isUndefinedNull(updateObj[key])) {
+                                        updateObj[key] = { value: null, typeName: typeName };
+                                    }
+                                    updateObj[key].value = Utils.sanitizeHtmlContent({ selector: "#" + obj.key });
+                                    that.model.set(updateObj);
+                                }
+                            });
+                            $("#" + obj.key).trumbowyg('html', obj.value);
+                        }
+                    });
+                });
                 this.$el.off("change", ".custom-col-1[data-id='value']>[data-key]").on("change", ".custom-col-1[data-id='value']>[data-key]", function(e) {
                     var key = $(this).data("key"),
                         businessMetadata = $(this).data("businessMetadata"),
@@ -176,7 +202,13 @@ define(['require',
                     }
                 }
                 if (typeName === "string" || typeName === "array<string>") {
-                    returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '></' + elType + '>';
+                    if (typeName === "string") {
+                        elType = "textarea";
+                        returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + "id =" + businessMetadata.replace(/ /g, "_") + "_" + key.replace(/ /g, "_") + '></' + elType + '>';
+                    } else {
+                        returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") +
+                            '></' + elType + '>';
+                    }
                 } else if (typeName === "boolean" || typeName === "array<boolean>") {
                     returnEL = '<select data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" class="form-control">' + (isMultiValued ? "" : '<option value="">--Select Value--</option>') + '<option value="true" ' + (!_.isUndefinedNull(val) && val == "true" ? "selected" : "") + '>true</option><option value="false" ' + (!_.isUndefinedNull(val) && val == "false" ? "selected" : "") + '>false</option></select>';
                 } else if (typeName === "date" || typeName === "array<date>") {
@@ -267,6 +299,30 @@ define(['require',
                     this.model.clear({ silent: true }).set(tempObj)
                 }
                 valEl.html(this.getAttrElement({ businessMetadata: key[0], key: key[1], val: hasModalData ? hasModalData : { typeName: key[2] } }));
+                if (key[2] === "string") {
+                    var that = this,
+                        selector = '#' +  key[0].replace(/ /g, "_") + "_" + key[1].replace(/ /g, "_");
+                    Utils.addCustomTextEditor({
+                        small: true,
+                        selector: selector,
+                        initialHide: false,
+                        callback: function(e) {
+                            var $parent = $(e.target),
+                                key = $parent.data("key"),
+                                businessMetadata = $parent.data("businessMetadata"),
+                                typeName = $parent.data("typename"),
+                                updateObj = that.model.toJSON();
+                            if (_.isUndefinedNull(updateObj[key])) {
+                                updateObj[key] = { value: null, typeName: typeName };
+                            }
+                            updateObj[key].value = Utils.sanitizeHtmlContent({ selector: selector });
+                            that.model.set(updateObj);
+                        }
+                    });
+                    if(hasModalData && hasModalData.value){
+                        $(selector).trumbowyg('html', hasModalData.value);
+                    }
+                }
                 if (manual === undefined) {
                     this.model.collection.trigger("selected:attr", e.currentTarget.value, this.model);
                 }
diff --git a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js
index 213e7cc01..7d66dc975 100644
--- a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js
+++ b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js
@@ -41,7 +41,8 @@ define([
                 editMode: this.editMode,
                 entity: this.entity,
                 businessMetadataCollection: this.businessMetadataCollection,
-                enumDefCollection: this.enumDefCollection
+                enumDefCollection: this.enumDefCollection,
+                searchVent: this.searchVent
             };
         },
         templateHelpers: function() {
@@ -69,13 +70,14 @@ define([
         },
         initialize: function(options) {
             var that = this;
-            _.extend(this, _.pick(options, "entity", "businessMetadataCollection", "enumDefCollection", "guid", "fetchCollection"));
+            _.extend(this, _.pick(options, "entity", "businessMetadataCollection", "enumDefCollection", "guid", "fetchCollection", "searchVent"));
             this.editMode = false;
             this.readOnlyEntity = Enums.entityStateReadOnly[this.entity.status];
             this.$("editBox").hide();
             this.actualCollection = new Backbone.Collection(
                 _.map(this.entity.businessAttributes, function(val, key) {
-                    var foundBusinessMetadata = that.businessMetadataCollection[key];
+                    var foundBusinessMetadata = that.businessMetadataCollection[key],
+                        businessMetadata = key;
                     if (foundBusinessMetadata) {
                         _.each(val, function(aVal, aKey) {
                             var foundAttr = _.find(foundBusinessMetadata, function(o) {
@@ -84,7 +86,10 @@ define([
                             if (foundAttr) {
                                 val[aKey] = { value: aVal, typeName: foundAttr.typeName };
                             }
-                        })
+                            if(foundAttr && foundAttr.typeName === "string"){
+                                val[aKey].key = businessMetadata.replace(/ /g, "_") + "_" + aKey.replace(/ /g, "_");;
+                            }
+                        });
                     }
                     return _.extend({}, val, { __internal_UI_businessMetadataName: key });
                 }));
@@ -124,6 +129,7 @@ define([
                 this.createNameElement();
             } else {
                 this.collection.trigger("reset");
+                this.searchVent.trigger("BusinessMetaAttribute:Edit");
             }
             this.panelOpenClose();
         },
@@ -154,6 +160,9 @@ define([
             this.$el.find('.custom-col-1[data-id="value"] [data-key]').each(function(el) {
                 var val = $(this).val(),
                     elIsSelect2 = $(this).hasClass("select2-hidden-accessible");
+                if (val) {
+                    val = Utils.sanitizeHtmlContent({ data: val });
+                }
                 if (_.isString(val)) {
                     val = val.trim();
                 }
@@ -165,6 +174,9 @@ define([
                         $(this).siblings(".select2").find(".select2-selection").attr("style", "border-color : red !important");
                     } else {
                         $(this).css("borderColor", "red");
+                        if($(this).parent().hasClass("small-texteditor")){
+                            $(this).parent().css("borderColor", "red");
+                        }
                     }
                 } else {
                     if (elIsSelect2) {
@@ -262,7 +274,7 @@ define([
                                 newVal = Utils.formatDate({ date: newVal, zone: false, dateFormat: Globals.dateFormat });
                             }
                         }
-                        attrLi += "<tr><td class='business-metadata-detail-attr-key'>" + _.escape(key) + " (" + _.escape(val.typeName) + ")</td><td>" + _.escape(newVal) + "</td></tr>";
+                        attrLi += "<tr><td class='business-metadata-detail-attr-key'>" + _.escape(key) + " (" + _.escape(val.typeName) + ")</td><td>" + ((val.typeName === "string") ? Utils.sanitizeHtmlContent({ data: newVal }) : _.escape(newVal)) + "</td></tr>";
                     }
                 });
                 li += that.associateAttributePanel(obj, attrLi);
diff --git a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
index b070c5509..02606067b 100644
--- a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
@@ -307,7 +307,7 @@ define(['require',
                 var longDescriptionContent = (data && data.longDescription) ? data.longDescription : "",
                     sanitizeLongDescriptionContent = "";
                 if (longDescriptionContent !== "") {
-                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent(longDescriptionContent);
+                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent({ data: longDescriptionContent });
                 }
                 //End
                 if (data) {
diff --git a/dashboardv2/public/js/views/tag/CreateTagLayoutView.js b/dashboardv2/public/js/views/tag/CreateTagLayoutView.js
index 476007a2c..a0b2104a4 100644
--- a/dashboardv2/public/js/views/tag/CreateTagLayoutView.js
+++ b/dashboardv2/public/js/views/tag/CreateTagLayoutView.js
@@ -84,7 +84,8 @@ define(['require',
             },
             bindEvents: function() {},
             onRender: function() {
-                var that = this;
+                var that = this,
+                    modalOkBtn;
                 this.$('.fontLoader').show();
                 if (this.create) {
                     this.tagCollectionList();
@@ -94,6 +95,19 @@ define(['require',
                 if (!('placeholder' in HTMLInputElement.prototype)) {
                     this.ui.createTagForm.find('input,textarea').placeholder();
                 }
+                modalOkBtn = function() {
+                    var editorContent = $(that.ui.description).trumbowyg('html'),
+                        okBtn = $('.modal').find('button.ok');
+                    okBtn.removeAttr("disabled");
+                    if (editorContent === "") {
+                        okBtn.prop('disabled', true);
+                    }
+                    if (that.description === editorContent) {
+                        okBtn.prop('disabled', true);
+                    }
+                };
+                Utils.addCustomTextEditor({ selector: this.ui.description, callback: modalOkBtn, small: false });
+                $(this.ui.description).trumbowyg('html', Utils.sanitizeHtmlContent({ data: this.description }));
                 that.hideLoader();
             },
             tagCollectionList: function() {
diff --git a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js b/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js
index be33e7c32..3b26f0e0e 100644
--- a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js
+++ b/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js
@@ -47,13 +47,18 @@ define(['require',
                 publishButton: '[data-id="publishButton"]',
                 superType: "[data-id='superType']",
                 subType: "[data-id='subType']",
-                entityType: "[data-id='entityType']"
+                entityType: "[data-id='entityType']",
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
                 var events = {};
                 events["click " + this.ui.addAttribute] = 'onClickAddTagAttributeBtn';
                 events["click " + this.ui.editButton] = 'onEditButton';
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description"));
+                };
                 return events;
             },
             /**
@@ -62,6 +67,7 @@ define(['require',
              */
             initialize: function(options) {
                 _.extend(this, _.pick(options, 'tag', 'collection', 'enumDefCollection'));
+                this.isTextTypeChecked = false;
             },
             bindEvents: function() {
                 this.listenTo(this.collection, 'reset', function() {
@@ -121,7 +127,7 @@ define(['require',
                     }
                 this.ui.title.html('<span>' + (Utils.getName(this.model.toJSON())) + '</span>');
                 if (this.model.get("description")) {
-                    this.ui.description.text(this.model.get("description"));
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description"));
                 }
                 if (attributeDefs) {
                     if (!_.isArray(attributeDefs)) {
diff --git a/dashboardv2/public/js/views/tag/TagLayoutView.js b/dashboardv2/public/js/views/tag/TagLayoutView.js
index f7af026b7..7de7aea14 100644
--- a/dashboardv2/public/js/views/tag/TagLayoutView.js
+++ b/dashboardv2/public/js/views/tag/TagLayoutView.js
@@ -403,7 +403,7 @@ define(['require',
                         }).open();
                     modal.$el.find('button.ok').attr("disabled", "true");
                     view.ui.tagName.on('keyup input', function(e) {
-                        view.ui.description.val($(this).val().replace(/\s+/g, ' '));
+                        $(view.ui.description).trumbowyg('html', $(this).val().replace(/\s+/g, ' '));
                     });
                     view.ui.description.on('input keydown', function(e) {
                         $(this).val($(this).val().replace(/\s+/g, ' '));
@@ -448,7 +448,7 @@ define(['require',
                     return;
                 }
                 this.name = ref.ui.tagName.val();
-                this.description = ref.ui.description.val();
+                this.description = Utils.sanitizeHtmlContent({ data: ref.ui.description.val() });
                 var superTypes = [];
                 if (ref.ui.parentTag.val() && ref.ui.parentTag.val()) {
                     superTypes = ref.ui.parentTag.val();
diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss
index fec5f6f02..1f4a786f5 100644
--- a/dashboardv3/public/css/scss/override.scss
+++ b/dashboardv3/public/css/scss/override.scss
@@ -567,7 +567,7 @@ div.columnmanager-dropdown-container {
     margin-right: 0px !important;
 }
 
-.glossary-longdescription-wrapper {
+.longdescription-wrapper {
     display: inline-block;
     height: 100px;
     background-color: #fff !important;
@@ -630,4 +630,10 @@ div.columnmanager-dropdown-container {
 
 .user-circle {
     display: inline;
+}
+
+.business-metadata-detail-attr {
+    ul {
+        list-style: disc
+    }
 }
\ No newline at end of file
diff --git a/dashboardv3/public/css/scss/texteditor.scss b/dashboardv3/public/css/scss/texteditor.scss
index 275bdcc3d..e05cf4d7d 100644
--- a/dashboardv3/public/css/scss/texteditor.scss
+++ b/dashboardv3/public/css/scss/texteditor.scss
@@ -19,14 +19,29 @@
 
 .trumbowyg {
     border-radius: 4px !important;
-    min-height: 150px !important;
+    min-height: 106px !important;
 
     .trumbowyg-button-pane {
-        background-color: #f6f7fb !important;
+        background: none;
+        border-bottom: none;
+        position: absolute;
+        bottom: 0px;
+
+        button {
+            transition: none;
+        }
+    }
+
+    .trumbowyg-button-pane-hidden {
+        display: none;
+    }
+
+    .trumbowyg-button-pane::after {
+        background: none !important;
     }
 
     .trumbowyg-editor {
-        min-height: 150px !important;
+        min-height: 70px !important;
         overflow-wrap: break-word;
     }
 
@@ -35,7 +50,19 @@
     }
 
     .trumbowyg-textarea {
-        min-height: 150px !important;
+        min-height: 106px !important;
+    }
+
+    .trumbowyg-button-pane .trumbowyg-button-group::after {
+        height: 25px;
+        vertical-align: middle;
+    }
+
+    .trumbowyg-button-pane button.trumbowyg-active,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):focus,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):hover {
+        background-color: #e8e9ee;
+        border-radius: 20px;
     }
 }
 
@@ -62,15 +89,31 @@
     width: 101px !important;
 }
 
-.trumbowyg-h1-dropdown-button{
+.trumbowyg-h1-dropdown-button {
     font-size: 36px !important;
 }
-.trumbowyg-h2-dropdown-button{
+
+.trumbowyg-h2-dropdown-button {
     font-size: 30px !important;
 }
-.trumbowyg-h3-dropdown-button{
+
+.trumbowyg-h3-dropdown-button {
     font-size: 24px !important;
 }
-.trumbowyg-h4-dropdown-button{
+
+.trumbowyg-h4-dropdown-button {
     font-size: 18px !important;
+}
+
+.small-texteditor {
+    .trumbowyg-button-pane button {
+        width: 25px !important;
+        height: 25px !important;
+    }
+    .trumbowyg-button-pane button.trumbowyg-active,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):focus,
+    .trumbowyg-button-pane button:not(.trumbowyg-disable):hover {
+        background-color: #e8e9ee;
+        border-radius: 20px;
+    }
 }
\ No newline at end of file
diff --git a/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js b/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js
index 7ef6d172e..fca766456 100644
--- a/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js
+++ b/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js
@@ -9,4 +9,4 @@
  *         Twitter : @AlexandreDemode
  *         Website : alex-d.fr
  */
-jQuery.trumbowyg={langs:{en:{viewHTML:"Plain Text",undo:"Undo",redo:"Redo",formatting:"Formatting",p:"Paragraph",blockquote:"Quote",code:"Code",header:"Header",bold:"Bold",italic:"Italic",strikethrough:"Strikethrough",underline:"Underline",strong:"Strong",em:"Emphasis",del:"Deleted",superscript:"Superscript",subscript:"Subscript",unorderedList:"Unordered list",orderedList:"Ordered list",insertImage:"Insert Image",link:"Link",createLink:"Insert link",unlink:"Remove link",justifyLeft:"Alig [...]
\ No newline at end of file
+jQuery.trumbowyg={langs:{en:{viewHTML:"Plain Text",undo:"Undo",redo:"Redo",formatting:"Formatting",p:"Paragraph",blockquote:"Quote",code:"Code",header:"Header",bold:"Bold",italic:"Italic",strikethrough:"Strikethrough",underline:"Underline",strong:"Strong",em:"Emphasis",del:"Deleted",superscript:"Superscript",subscript:"Subscript",unorderedList:"Unordered list",orderedList:"Ordered list",insertImage:"Insert Image",link:"Link",createLink:"Insert link",unlink:"Remove link",justifyLeft:"Alig [...]
\ No newline at end of file
diff --git a/dashboardv3/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html b/dashboardv3/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
index 3d316f688..aedb6dabe 100644
--- a/dashboardv3/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
+++ b/dashboardv3/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html
@@ -95,9 +95,12 @@
     <div class="form-group" data-id="stringLengthContainer">
         <div class="stringlength-container">
             <label class="control-label col-sm-3 required" for="name">Max length</label>
-            <div class="col-sm-8">
+            <div class="col-sm-6">
                 <input type="number" class="form-control stringLengthVal require" data-id="stringLength" placeholder="Maximum length">
             </div>
+            <label class="control-label">
+                <i class="fa fa-question-circle help-btn" title="<div>String length limit includes any HTML formatting tags used.</div>" data-html="true"></i>
+            </label>
         </div>
     </div>
     <div class="form-group entity-businessMetadata-selector">
diff --git a/dashboardv3/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html b/dashboardv3/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
index 2ad5ba5e0..a3eddc769 100644
--- a/dashboardv3/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html
@@ -23,7 +23,20 @@
     </div>
     <div class="tagDetail clearfix form-horizontal col-sm-12">
         <h1 class="title"><span data-id="title"></span></h1>
-        <p class="form-group col-sm-12" data-id="description"></p>
+        <div class="long-description-container form-group clearfix">
+            <span class="pull-left text-muted">Description:&nbsp;</span>
+            <div class="isTextTypeBtn-wrapper pull-right">
+                <span class="text-muted pull-left">Formatted</span>
+                <label class="switch pull-left">
+                    <input type="checkbox" class="switch-input" name="textType" value="text">
+                    <span class="switch-slider"></span>
+                </label>
+                <span class="text-muted">Plain</span>
+            </div>
+            <div class="longdescription-wrapper form-control col-sm-12">
+                <div class="long-description" name="longDescription" data-id="description" disabled></div>
+            </div>
+        </div>
     </div>
 </div>
 </div>
\ No newline at end of file
diff --git a/dashboardv3/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html b/dashboardv3/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
index a78614d15..5a43a7662 100644
--- a/dashboardv3/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html
@@ -31,7 +31,7 @@
     <div class="form-group">
         <label class="control-label col-sm-2" for="description">Description</label>
         <div class="col-sm-10">
-            <input class="form-control" data-id="description" value="{{description}}" placeholder="Description" />
+            <textarea class="form-control customTextEditor" data-id="description" value="{{description}}" placeholder="Description" ></textarea>
         </div>
     </div>
     {{/if}}
diff --git a/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html b/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
index 64e603135..5933d1d2f 100644
--- a/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
@@ -40,7 +40,7 @@
                 </label>
                 <span class="text-muted">Plain</span>
             </div>
-            <div class="glossary-longdescription-wrapper form-control">
+            <div class="longdescription-wrapper form-control">
                 <div class="long-description" name="longDescription" data-id="longDescription" disabled></div>
             </div>
         </div>
diff --git a/dashboardv3/public/js/templates/tag/CreateTagLayoutView_tmpl.html b/dashboardv3/public/js/templates/tag/CreateTagLayoutView_tmpl.html
index 27ea91247..28f0baa02 100644
--- a/dashboardv3/public/js/templates/tag/CreateTagLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/tag/CreateTagLayoutView_tmpl.html
@@ -30,7 +30,7 @@
     <div class="form-group">
         <label class="control-label col-sm-2 required" for="description">Description</label>
         <div class="col-sm-10">
-            <input class="form-control" data-id="description" value="{{description}}" placeholder="Description(required)" />
+            <textarea class="form-control customTextEditor" data-id="description" value="{{description}}" placeholder="Description(required)" ></textarea>
         </div>
     </div>
     {{#if create}}
diff --git a/dashboardv3/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html b/dashboardv3/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
index c999fe140..21f662877 100644
--- a/dashboardv3/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html
@@ -24,7 +24,20 @@
     <div class="tagDetail clearfix form-horizontal col-sm-12">
         <h1 class="title"><span data-id="title"></span></h1>
         <button type="button" data-id="editButton" class="btn btn-sm btn-action pull-right"><i class="fa fa-pencil"></i></button>
-        <p class="form-group col-sm-12" data-id="description"></p>
+        <div class="long-description-container form-group clearfix">
+            <span class="pull-left text-muted">Description:&nbsp;</span>
+            <div class="isTextTypeBtn-wrapper pull-right">
+                <span class="text-muted pull-left">Formatted</span>
+                <label class="switch pull-left">
+                    <input type="checkbox" class="switch-input" name="textType" value="text">
+                    <span class="switch-slider"></span>
+                </label>
+                <span class="text-muted">Plain</span>
+            </div>
+            <div class="longdescription-wrapper form-control col-sm-12">
+                <div class="long-description" name="longDescription" data-id="description" disabled></div>
+            </div>
+        </div>
         <div class="superType form-group col-sm-12" style="display:none">
             <label class="control-label-sm-pr pull-left">Direct super-classifications:</label>
             <div data-id="superType" class="btn-inline">
diff --git a/dashboardv3/public/js/utils/CommonViewFunction.js b/dashboardv3/public/js/utils/CommonViewFunction.js
index 7aacb9887..7d8f03d2e 100644
--- a/dashboardv3/public/js/utils/CommonViewFunction.js
+++ b/dashboardv3/public/js/utils/CommonViewFunction.js
@@ -715,12 +715,13 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
             //Below condition is added for sanitizing the longDescription text against XSS attack.
             if (model) {
                 var longDescriptionContent = isGlossaryView ? model.get('longDescription') : model.longDescription,
-                    sanitizeLongDescriptionContent;
+                    sanitizeLongDescriptionContent = "";
                 if (longDescriptionContent) {
-                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent(longDescriptionContent)
+                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent({ data: longDescriptionContent });
                     isGlossaryView ? model.set("longDescription", sanitizeLongDescriptionContent) : model.longDescription = sanitizeLongDescriptionContent;
                 }
             }
+            //End
         }
         require([
             'views/glossary/CreateEditCategoryTermLayoutView',
@@ -745,38 +746,22 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
                 "okCloses": false,
                 "okText": model ? "Update" : "Create",
                 "allowCancel": true,
-                "width": "765px"
+                "width": "640px"
             }).open();
             modal.$el.find('input[data-id=shortDescription]').on('input keydown', function(e) {
                 $(this).val($(this).val().replace(/\s+/g, ' '));
             });
             modal.$el.find('button.ok').attr("disabled", "true");
             var longDescriptionEditor = modal.$el.find('textarea[data-id=longDescription]'),
-                okBtn = modal.$el.find('button.ok');
-            longDescriptionEditor.trumbowyg({
-                btns: [
-                    ['formatting'],
-                    ['strong', 'em', 'underline', 'del'],
-                    ['link'],
-                    ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
-                    ['unorderedList', 'orderedList'],
-                    ['viewHTML']
-                ],
-                removeformatPasted: true,
-                urlProtocol: true,
-                defaultLinkTarget: '_blank'
-            }).on('tbwchange', function() {
-                okBtn.removeAttr("disabled");
-            });
+                okBtn = modal.$el.find('button.ok'),
+                modalOkBtn = function() {
+                    okBtn.removeAttr("disabled");
+                };
+            Utils.addCustomTextEditor({ selector: longDescriptionEditor, callback: modalOkBtn, initialHide: false });
             modal.on('ok', function() {
                 modal.$el.find('button.ok').showButtonLoader();
                 //Below condition is added for sanitizing the longDescription text against XSS attack.
-                var editorContent, cleanContent;
-                editorContent = longDescriptionEditor.trumbowyg('html');
-                if (editorContent !== "") {
-                    cleanContent = Utils.sanitizeHtmlContent(editorContent);
-                    longDescriptionEditor.trumbowyg('html', cleanContent);
-                }
+                longDescriptionEditor.trumbowyg('html', Utils.sanitizeHtmlContent({ selector: longDescriptionEditor }));
                 //End
                 CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, "modal": modal }, options));
             });
@@ -785,6 +770,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
                 if (options.onModalClose) {
                     options.onModalClose()
                 }
+                longDescriptionEditor.trumbowyg('closeModal');
             });
         });
     }
diff --git a/dashboardv3/public/js/utils/Helper.js b/dashboardv3/public/js/utils/Helper.js
index 164beac57..71101a74f 100644
--- a/dashboardv3/public/js/utils/Helper.js
+++ b/dashboardv3/public/js/utils/Helper.js
@@ -134,6 +134,12 @@ define(['require',
     $("body").on('click', '.btn', function() {
         $(this).blur();
     });
+    $('body').on('click', function(e) {
+        if ($(e.target).hasClass('trumbowyg-editor-hidden')) {
+            $('.trumbowyg').find('.trumbowyg-button-pane').removeClass('trumbowyg-button-pane-hidden');
+            $('.trumbowyg').css('border', '1px solid #8fa5b1');
+        }
+    });
     $('body').on('keyup input', '.modal-body', function(e) {
         var target = e.target,
             isGlossary = (e.target.dataset.id === "searchTerm" || e.target.dataset.id === "searchCategory") ? true : false; // assign term/category modal
diff --git a/dashboardv3/public/js/utils/Utils.js b/dashboardv3/public/js/utils/Utils.js
index d4db9f4b9..0d8722fa9 100644
--- a/dashboardv3/public/js/utils/Utils.js
+++ b/dashboardv3/public/js/utils/Utils.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, DOMPurify) {
+define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'DOMPurify', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm', 'trumbowyg'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal, DOMPurify) {
     'use strict';
 
     var Utils = {};
@@ -964,14 +964,7 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
         }
         return dateValue;
     }
-    //-----------------------------------------DOMPurify--------------------------------------
-    //This below function expects string that needs to be sanitize against XSS attack.
-    Utils.sanitizeHtmlContent = function(string) {
-        if (string) {
-            return DOMPurify.sanitize(string, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] });
-        }
-    }
-    //----------------------------------------------------------------------------------------
+
     //------------------------------------------------idleTimeout-----------------------------
     $.fn.idleTimeout = function(userRuntimeConfig) {
 
@@ -1237,5 +1230,68 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
     };
 
     //------------------------------------------------
+
+    //--------------------------------------Custom Text Editor-----------------------------------//
+    Utils.addCustomTextEditor = function(options) {
+        var selector = options.selector ? options.selector : ".customTextEditor",
+            defaultBtns = [
+                ['formatting'],
+                ['strong', 'em', 'underline', 'del'],
+                ['link'],
+                ['unorderedList', 'orderedList'],
+                ['viewHTML']
+            ],
+            smallTextEditorBtn = [
+                ['strong', 'em', 'underline', 'del'],
+                ['link'],
+                ['unorderedList', 'orderedList'],
+            ],
+            customBtnDefs = {
+                formatting: {
+                    dropdown: ['p', 'h1', 'h2', 'h3', 'h4'],
+                    ico: 'p'
+                }
+            },
+            $btnPane, $parent;
+        $(selector).trumbowyg({
+            btns: options.small ? smallTextEditorBtn : defaultBtns,
+            autogrow: true,
+            removeformatPasted: true,
+            urlProtocol: true,
+            defaultLinkTarget: '_blank',
+            btnsDef: options.small ? {} : customBtnDefs
+        }).on('tbwinit', function() {
+            $btnPane = $(this).parent().find('.trumbowyg-button-pane');
+            $parent = $(this).parent();
+            if (options.small) {
+                $parent.addClass('small-texteditor');
+            }
+            if (!options.initialHide) {
+                $btnPane.addClass('trumbowyg-button-pane-hidden');
+                $parent.css('border', '1px solid #e8e9ee');
+            }
+        }).on('tbwblur', function(e) {
+            $btnPane.addClass('trumbowyg-button-pane-hidden');
+            $parent.css('border', '1px solid #e8e9ee');
+        }).on('tbwfocus', function(e) {
+            $btnPane.removeClass('trumbowyg-button-pane-hidden');
+            $parent.css('border', '1px solid #8fa5b1');
+        }).on('tbwchange', function(e) {
+            options.callback ? options.callback(e) : null;
+        }).on('tbwmodalopen', function(e) {
+            $('input[name="title"], input[name="target"]').parent().css('display', 'none');
+        });
+    }
+
+    Utils.sanitizeHtmlContent = function(options) {
+        var editorContent, cleanedContent;
+        editorContent = options.selector ? $(options.selector).trumbowyg('html') : options.data;
+        if (options && editorContent) {
+            cleanedContent = DOMPurify.sanitize(editorContent, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] });
+        }
+        return cleanedContent;
+    }
+    //-----------------------------------------END---------------------//
+
     return Utils;
 });
diff --git a/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js b/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
index ee5b84bdf..0921d4371 100644
--- a/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
+++ b/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js
@@ -33,7 +33,8 @@ define(['require',
             ui: {
                 title: '[data-id="title"]',
                 description: '[data-id="description"]',
-                backButton: '[data-id="backButton"]'
+                backButton: '[data-id="backButton"]',
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
@@ -41,6 +42,10 @@ define(['require',
                 events["click " + this.ui.backButton] = function() {
                     Utils.backButtonClick();
                 };
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.renderDetail();
+                };
                 return events;
             },
             /**
@@ -49,6 +54,7 @@ define(['require',
              */
             initialize: function(options) {
                 _.extend(this, _.pick(options, 'model'));
+                this.isTextTypeChecked = false;
             },
             onRender: function() {
                 this.renderDetail();
@@ -56,7 +62,7 @@ define(['require',
             renderDetail: function() {
                 this.ui.title.html('<span>' + this.model.get('name') + '</span>');
                 if (this.model.get('description')) {
-                    this.ui.description.text(this.model.get('description'));
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get('description')) : this.ui.description.html(this.model.get('description'));
                 }
             }
         });
diff --git a/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js b/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
index 80932ce51..2e8d7c10c 100644
--- a/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
+++ b/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js
@@ -215,6 +215,7 @@ define(['require',
                         isNewBusinessMetadata: isNewBusinessMetadata
                     });
                     that.RModal.show(that.view);
+                    Utils.addCustomTextEditor({ small: false });
                 });
             },
             renderTableLayoutView: function() {
@@ -296,7 +297,11 @@ define(['require',
                         editable: false,
                         formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                             fromRaw: function(rawValue, model) {
-                                return _.escape(model.get('description'));
+                                var description = model.get('description');
+                                if (description.length > 50) {
+                                    description = description.substr(0, 50) + "...";
+                                }
+                                return description;
                             }
                         })
                     },
diff --git a/dashboardv3/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js b/dashboardv3/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
index 21bb663ab..165b99500 100644
--- a/dashboardv3/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
+++ b/dashboardv3/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js
@@ -223,7 +223,7 @@ define(['require',
                 };
                 this.loaderStatus(true);
                 var name = this.ui.name.val(),
-                    description = this.ui.description.val();
+                    description = Utils.sanitizeHtmlContent({ data: this.ui.description.val() });
                 var attributeObj = this.collection.toJSON();
                 if (this.collection.length === 1 && this.collection.first().get("name") === "") {
                     attributeObj = [];
@@ -240,7 +240,7 @@ define(['require',
                         "version": 1,
                         "typeVersion": "1.1",
                         "name": name.trim(),
-                        "description": description.trim(),
+                        "description": description ? description.trim() : "",
                         "attributeDefs": attributeObj
                     }]
                 };
diff --git a/dashboardv3/public/js/views/entity/EntityBusinessMetaDataItemView.js b/dashboardv3/public/js/views/entity/EntityBusinessMetaDataItemView.js
index 913cc0faf..2fb835e26 100644
--- a/dashboardv3/public/js/views/entity/EntityBusinessMetaDataItemView.js
+++ b/dashboardv3/public/js/views/entity/EntityBusinessMetaDataItemView.js
@@ -100,6 +100,32 @@ define(['require',
                         }
                     }
                 });
+                this.listenTo(this.searchVent, 'BusinessMetaAttribute:Edit', function() {
+                    _.each(that.model.attributes, function(obj) {
+                        if (obj.key) {
+                            if (obj.typeName === "string") {
+                                obj.value = Utils.sanitizeHtmlContent({ data: obj.value });
+                            }
+                            Utils.addCustomTextEditor({
+                                small: true,
+                                selector: "#" + obj.key,
+                                initialHide: false,
+                                callback: function(e) {
+                                    var key = $(e.target).data("key"),
+                                        businessMetadata = $(e.target).data("businessMetadata"),
+                                        typeName = $(e.target).data("typename"),
+                                        updateObj = that.model.toJSON();
+                                    if (_.isUndefinedNull(updateObj[key])) {
+                                        updateObj[key] = { value: null, typeName: typeName };
+                                    }
+                                    updateObj[key].value = Utils.sanitizeHtmlContent({ selector: "#" + obj.key });
+                                    that.model.set(updateObj);
+                                }
+                            });
+                            $("#" + obj.key).trumbowyg('html', obj.value);
+                        }
+                    });
+                });
                 this.$el.off("change", ".custom-col-1[data-id='value']>[data-key]").on("change", ".custom-col-1[data-id='value']>[data-key]", function(e) {
                     var key = $(this).data("key"),
                         businessMetadata = $(this).data("businessMetadata"),
@@ -177,8 +203,14 @@ define(['require',
                     }
                 }
                 if (typeName === "string" || typeName === "array<string>") {
-                    returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '></' + elType + '>';
-                } else if (typeName === "boolean" || typeName === "array<boolean>") {
+                    if (typeName === "string") {
+                        elType = "textarea";
+                        returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + "id =" + businessMetadata.replace(/ /g, "_") + "_" + key.replace(/ /g, "_") + '></' + elType + '>';
+                    } else {
+                        returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true"  placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") +
+                            '></' + elType + '>';
+                    }
+                }  else if (typeName === "boolean" || typeName === "array<boolean>") {
                     returnEL = '<select data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" class="form-control">' + (isMultiValued ? "" : '<option value="">--Select Value--</option>') + '<option value="true" ' + (!_.isUndefinedNull(val) && val == "true" ? "selected" : "") + '>true</option><option value="false" ' + (!_.isUndefinedNull(val) && val == "false" ? "selected" : "") + '>false</option></select>';
                 } else if (typeName === "date" || typeName === "array<date>") {
                     returnEL = '<' + (isMultiValued ? "textarea" : "input") + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '"data-multi="' + isMultiValued + '" data-type="date" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '>' + (isMultiValued === true && !_.isUndefinedNull(val) ? val : "") + (isMultiValued ? "</textarea>" : "");
@@ -268,6 +300,30 @@ define(['require',
                     this.model.clear({ silent: true }).set(tempObj)
                 }
                 valEl.html(this.getAttrElement({ businessMetadata: key[0], key: key[1], val: hasModalData ? hasModalData : { typeName: key[2] } }));
+                if (key[2] === "string") {
+                    var that = this,
+                        selector = '#' +  key[0].replace(/ /g, "_") + "_" + key[1].replace(/ /g, "_");
+                    Utils.addCustomTextEditor({
+                        small: true,
+                        selector: selector,
+                        initialHide: false,
+                        callback: function(e) {
+                            var $parent = $(e.target),
+                                key = $parent.data("key"),
+                                businessMetadata = $parent.data("businessMetadata"),
+                                typeName = $parent.data("typename"),
+                                updateObj = that.model.toJSON();
+                            if (_.isUndefinedNull(updateObj[key])) {
+                                updateObj[key] = { value: null, typeName: typeName };
+                            }
+                            updateObj[key].value = Utils.sanitizeHtmlContent({ selector: selector });
+                            that.model.set(updateObj);
+                        }
+                    });
+                    if(hasModalData && hasModalData.value){
+                        $(selector).trumbowyg('html', hasModalData.value);
+                    }
+                }
                 if (manual === undefined) {
                     this.model.collection.trigger("selected:attr", e.currentTarget.value, this.model);
                 }
diff --git a/dashboardv3/public/js/views/entity/EntityBusinessMetaDataView.js b/dashboardv3/public/js/views/entity/EntityBusinessMetaDataView.js
index 81db8935e..cb023bab2 100644
--- a/dashboardv3/public/js/views/entity/EntityBusinessMetaDataView.js
+++ b/dashboardv3/public/js/views/entity/EntityBusinessMetaDataView.js
@@ -41,7 +41,8 @@ define([
                 editMode: this.editMode,
                 entity: this.entity,
                 businessMetadataCollection: this.businessMetadataCollection,
-                enumDefCollection: this.enumDefCollection
+                enumDefCollection: this.enumDefCollection,
+                searchVent: this.searchVent
             };
         },
         templateHelpers: function() {
@@ -69,13 +70,14 @@ define([
         },
         initialize: function(options) {
             var that = this;
-            _.extend(this, _.pick(options, "entity", "businessMetadataCollection", "enumDefCollection", "guid", "fetchCollection"));
+            _.extend(this, _.pick(options, "entity", "businessMetadataCollection", "enumDefCollection", "guid", "fetchCollection", "searchVent"));
             this.editMode = false;
             this.readOnlyEntity = Enums.entityStateReadOnly[this.entity.status];
             this.$("editBox").hide();
             this.actualCollection = new Backbone.Collection(
                 _.map(this.entity.businessAttributes, function(val, key) {
-                    var foundBusinessMetadata = that.businessMetadataCollection[key];
+                    var foundBusinessMetadata = that.businessMetadataCollection[key],
+                        businessMetadata = key;
                     if (foundBusinessMetadata) {
                         _.each(val, function(aVal, aKey) {
                             var foundAttr = _.find(foundBusinessMetadata, function(o) {
@@ -84,7 +86,10 @@ define([
                             if (foundAttr) {
                                 val[aKey] = { value: aVal, typeName: foundAttr.typeName };
                             }
-                        })
+                            if (foundAttr && foundAttr.typeName === "string") {
+                                val[aKey].key = businessMetadata.replace(/ /g, "_") + "_" + aKey.replace(/ /g, "_");
+                            }
+                        });
                     }
                     return _.extend({}, val, { __internal_UI_businessMetadataName: key });
                 }));
@@ -124,6 +129,7 @@ define([
                 this.createNameElement();
             } else {
                 this.collection.trigger("reset");
+                this.searchVent.trigger("BusinessMetaAttribute:Edit");
             }
             this.panelOpenClose();
         },
@@ -154,6 +160,9 @@ define([
             this.$el.find('.custom-col-1[data-id="value"] [data-key]').each(function(el) {
                 var val = $(this).val(),
                     elIsSelect2 = $(this).hasClass("select2-hidden-accessible");
+                if (val) {
+                    val = Utils.sanitizeHtmlContent({ data: val });
+                }
                 if (_.isString(val)) {
                     val = val.trim();
                 }
@@ -165,6 +174,9 @@ define([
                         $(this).siblings(".select2").find(".select2-selection").attr("style", "border-color : red !important");
                     } else {
                         $(this).css("borderColor", "red");
+                        if($(this).parent().hasClass("small-texteditor")){
+                            $(this).parent().css("borderColor", "red");
+                        }
                     }
                 } else {
                     if (elIsSelect2) {
@@ -261,9 +273,8 @@ define([
                             if (val.typeName === "date") {
                                 newVal = Utils.formatDate({ date: newVal, zone: false, dateFormat: Globals.dateFormat });
                             }
-
                         }
-                        attrLi += "<tr><td class='business-metadata-detail-attr-key'>" + _.escape(key) + " (" + _.escape(val.typeName) + ")</td><td>" + _.escape(newVal) + "</td></tr>";
+                        attrLi += "<tr><td class='business-metadata-detail-attr-key'>" + _.escape(key) + " (" + _.escape(val.typeName) + ")</td><td>" + ((val.typeName === "string") ? Utils.sanitizeHtmlContent({ data: newVal }) : _.escape(newVal)) + "</td></tr>";
                     }
                 });
                 li += that.associateAttributePanel(obj, attrLi);
diff --git a/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js b/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
index 845ace1c9..019cd9d3f 100644
--- a/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
+++ b/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
@@ -321,7 +321,7 @@ define(['require',
                 var longDescriptionContent = (data && data.longDescription) ? data.longDescription : "",
                     sanitizeLongDescriptionContent = "";
                 if (longDescriptionContent !== "") {
-                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent(longDescriptionContent);
+                    sanitizeLongDescriptionContent = Utils.sanitizeHtmlContent({ data: longDescriptionContent });
                 }
                 //End
                 if (data) {
diff --git a/dashboardv3/public/js/views/search/tree/ClassificationTreeLayoutView.js b/dashboardv3/public/js/views/search/tree/ClassificationTreeLayoutView.js
index e31260d40..1883dfbd7 100644
--- a/dashboardv3/public/js/views/search/tree/ClassificationTreeLayoutView.js
+++ b/dashboardv3/public/js/views/search/tree/ClassificationTreeLayoutView.js
@@ -687,7 +687,7 @@ define([
                     }).open();
                 modal.$el.find("button.ok").attr("disabled", "true");
                 view.ui.tagName.on('keyup input', function(e) {
-                    view.ui.description.val($(this).val().replace(/\s+/g, ' '));
+                    $(view.ui.description).trumbowyg('html', $(this).val().replace(/\s+/g, ' '));
                 });
                 view.ui.description.on('input keydown', function(e) {
                     $(this).val($(this).val().replace(/\s+/g, ' '));
@@ -732,7 +732,7 @@ define([
             }
 
             var name = ref.ui.tagName.val(),
-                description = ref.ui.description.val(),
+                description = Utils.sanitizeHtmlContent({ data: ref.ui.description.val() }),
                 superTypes = [],
                 parentTagVal = ref.ui.parentTag.val();
             if (parentTagVal && parentTagVal.length) {
diff --git a/dashboardv3/public/js/views/tag/CreateTagLayoutView.js b/dashboardv3/public/js/views/tag/CreateTagLayoutView.js
index 476007a2c..a0b2104a4 100644
--- a/dashboardv3/public/js/views/tag/CreateTagLayoutView.js
+++ b/dashboardv3/public/js/views/tag/CreateTagLayoutView.js
@@ -84,7 +84,8 @@ define(['require',
             },
             bindEvents: function() {},
             onRender: function() {
-                var that = this;
+                var that = this,
+                    modalOkBtn;
                 this.$('.fontLoader').show();
                 if (this.create) {
                     this.tagCollectionList();
@@ -94,6 +95,19 @@ define(['require',
                 if (!('placeholder' in HTMLInputElement.prototype)) {
                     this.ui.createTagForm.find('input,textarea').placeholder();
                 }
+                modalOkBtn = function() {
+                    var editorContent = $(that.ui.description).trumbowyg('html'),
+                        okBtn = $('.modal').find('button.ok');
+                    okBtn.removeAttr("disabled");
+                    if (editorContent === "") {
+                        okBtn.prop('disabled', true);
+                    }
+                    if (that.description === editorContent) {
+                        okBtn.prop('disabled', true);
+                    }
+                };
+                Utils.addCustomTextEditor({ selector: this.ui.description, callback: modalOkBtn, small: false });
+                $(this.ui.description).trumbowyg('html', Utils.sanitizeHtmlContent({ data: this.description }));
                 that.hideLoader();
             },
             tagCollectionList: function() {
diff --git a/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js b/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js
index 52ff0431d..2a22d3212 100644
--- a/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js
+++ b/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js
@@ -48,7 +48,8 @@ define(['require',
                 superType: "[data-id='superType']",
                 subType: "[data-id='subType']",
                 entityType: "[data-id='entityType']",
-                backButton: '[data-id="backButton"]'
+                backButton: '[data-id="backButton"]',
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
@@ -58,6 +59,10 @@ define(['require',
                 events["click " + this.ui.backButton] = function() {
                     Utils.backButtonClick();
                 };
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description"));
+                };
                 return events;
             },
             /**
@@ -66,6 +71,7 @@ define(['require',
              */
             initialize: function(options) {
                 _.extend(this, _.pick(options, 'tag', 'collection', 'enumDefCollection'));
+                this.isTextTypeChecked = false;
             },
             bindEvents: function() {
                 this.listenTo(this.collection, 'reset', function() {
@@ -125,7 +131,7 @@ define(['require',
                     }
                 this.ui.title.html('<span>' + (Utils.getName(this.model.toJSON())) + '</span>');
                 if (this.model.get("description")) {
-                    this.ui.description.text(this.model.get("description"));
+                    this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description"));
                 }
                 if (attributeDefs) {
                     if (!_.isArray(attributeDefs)) {