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

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


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new f4a1a66  ATLAS-4471 : UI: Add text editor for long description fields
f4a1a66 is described below

commit f4a1a66ebd17481368edf168e36b474f2a9d4fa7
Author: Farhan Khan <farhan.k...@cloudera.com>
AuthorDate: Fri Jan 7 18:20:08 2022 +0530

    ATLAS-4471 : UI: Add text editor for long description fields
    
    Signed-off-by: Pinal Shah <pinal.s...@freestoneinfotech.com>
    (cherry picked from commit c0f318f18ff621a4fe88fd49f3d2fad8468d2de4)
---
 dashboardv2/public/css/scss/common.scss            |   3 +-
 dashboardv2/public/css/scss/override.scss          |  26 +
 dashboardv2/public/css/scss/style.scss             |   4 +-
 dashboardv2/public/css/scss/texteditor.scss        |  76 ++
 dashboardv2/public/css/scss/trumbowyg.scss         | 889 +++++++++++++++++++++
 .../public/js/external_lib/dompurify/purify.min.js |   3 +
 .../public/js/external_lib/trumbowyg/trumbowyg.js  |  12 +
 .../public/js/external_lib/trumbowyg/ui/icons.svg  |   1 +
 dashboardv2/public/js/main.js                      |  11 +-
 .../glossary/GlossaryDetailLayoutView_tmpl.html    |  14 +-
 dashboardv2/public/js/utils/CommonViewFunction.js  |  45 +-
 dashboardv2/public/js/utils/Utils.js               |  12 +-
 .../js/views/glossary/GlossaryDetailLayoutView.js  |  16 +-
 dashboardv3/public/css/scss/common.scss            |   3 +-
 dashboardv3/public/css/scss/override.scss          |  27 +
 dashboardv3/public/css/scss/style.scss             |   4 +-
 dashboardv3/public/css/scss/texteditor.scss        |  76 ++
 dashboardv3/public/css/scss/trumbowyg.scss         | 889 +++++++++++++++++++++
 .../public/js/external_lib/dompurify/purify.min.js |   3 +
 .../public/js/external_lib/trumbowyg/trumbowyg.js  |  12 +
 .../public/js/external_lib/trumbowyg/ui/icons.svg  |   1 +
 dashboardv3/public/js/main.js                      |  11 +-
 .../glossary/GlossaryDetailLayoutView_tmpl.html    |  16 +-
 dashboardv3/public/js/utils/CommonViewFunction.js  |  44 +-
 dashboardv3/public/js/utils/Utils.js               |  12 +-
 .../js/views/glossary/GlossaryDetailLayoutView.js  |  17 +-
 26 files changed, 2199 insertions(+), 28 deletions(-)

diff --git a/dashboardv2/public/css/scss/common.scss 
b/dashboardv2/public/css/scss/common.scss
index 5bf8b61..5e7ffef 100644
--- a/dashboardv2/public/css/scss/common.scss
+++ b/dashboardv2/public/css/scss/common.scss
@@ -341,7 +341,8 @@ pre {
 }
 
 .long-description {
-    width: 85%;
+    width: 100%;
+    overflow-wrap: break-word;
     cursor: default !important;
     background-color: transparent !important;
 }
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/override.scss 
b/dashboardv2/public/css/scss/override.scss
index 94548ff..f98c7fc 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -569,6 +569,32 @@ div.columnmanager-dropdown-container {
     padding-top: 20px;
 }
 
+.long-description-container {
+    margin-right: 0px !important;
+}
+
+.glossary-longdescription-wrapper {
+    display: inline-block;
+    height: 100px;
+    background-color: #fff !important;
+    overflow: auto;
+    margin-top: 8px;
+    width: 100%;
+
+    ul {
+        list-style: disc !important;
+    }
+}
+
+.isTextTypeBtn-wrapper {
+    display: inline-block;
+    line-height: 22px;
+
+    .switch {
+        margin-bottom: 0px;
+    }
+}
+
 .select2-container--default .select2-search--inline .select2-search__field {
     width: 100% !important;
 }
diff --git a/dashboardv2/public/css/scss/style.scss 
b/dashboardv2/public/css/scss/style.scss
index 9f4482c..a56c0af 100644
--- a/dashboardv2/public/css/scss/style.scss
+++ b/dashboardv2/public/css/scss/style.scss
@@ -36,4 +36,6 @@
 @import "wizard.scss";
 @import "business-metadata.scss";
 @import "stats.scss";
-@import "override.scss";
\ No newline at end of file
+@import "override.scss";
+@import "trumbowyg.scss";
+@import "texteditor.scss";
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/texteditor.scss 
b/dashboardv2/public/css/scss/texteditor.scss
new file mode 100644
index 0000000..275bdcc
--- /dev/null
+++ b/dashboardv2/public/css/scss/texteditor.scss
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/* texteditor */
+
+.trumbowyg {
+    border-radius: 4px !important;
+    min-height: 150px !important;
+
+    .trumbowyg-button-pane {
+        background-color: #f6f7fb !important;
+    }
+
+    .trumbowyg-editor {
+        min-height: 150px !important;
+        overflow-wrap: break-word;
+    }
+
+    ul {
+        list-style: disc !important;
+    }
+
+    .trumbowyg-textarea {
+        min-height: 150px !important;
+    }
+}
+
+.trumbowyg-modal-submit,
+.trumbowyg-modal-reset {
+    border: 1px #37bb9b solid !important;
+    color: #37bb9b !important;
+    border-radius: 4px !important;
+    font-size: 14px !important;
+    background-color: transparent !important;
+}
+
+.trumbowyg-modal-submit:hover,
+.trumbowyg-modal-reset:hover {
+    background-color: #37bb9b !important;
+    color: #fff !important;
+}
+
+.trumbowyg-modal-box label .trumbowyg-input-infos span {
+    color: #686868 !important;
+}
+
+.trumbowyg-viewHTML-button {
+    width: 101px !important;
+}
+
+.trumbowyg-h1-dropdown-button{
+    font-size: 36px !important;
+}
+.trumbowyg-h2-dropdown-button{
+    font-size: 30px !important;
+}
+.trumbowyg-h3-dropdown-button{
+    font-size: 24px !important;
+}
+.trumbowyg-h4-dropdown-button{
+    font-size: 18px !important;
+}
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/trumbowyg.scss 
b/dashboardv2/public/css/scss/trumbowyg.scss
new file mode 100644
index 0000000..a5463ea
--- /dev/null
+++ b/dashboardv2/public/css/scss/trumbowyg.scss
@@ -0,0 +1,889 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/* trumbowyg */
+
+/**
+ * Trumbowyg v2.24.0 - A lightweight WYSIWYG editor
+ * Default stylesheet for Trumbowyg editor
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ *         Twitter : @AlexandreDemode
+ *         Website : alex-d.fr
+ */
+
+$light-color: #ecf0f1 !default;
+$dark-color: #222 !default;
+
+$modal-submit-color: #2ecc71 !default;
+$modal-reset-color: #EEE !default;
+
+$transition-duration: 150ms !default;
+$slow-transition-duration: 300ms !default;
+
+#trumbowyg-icons {
+    overflow: hidden;
+    visibility: hidden;
+    height: 0;
+    width: 0;
+
+    svg {
+        height: 0;
+        width: 0;
+    }
+}
+
+.trumbowyg-box,
+.trumbowyg-modal {
+
+    *,
+    *::before,
+    *::after {
+        box-sizing: border-box;
+    }
+
+    svg {
+        width: 17px;
+        height: 100%;
+        fill: $dark-color;
+    }
+}
+
+.trumbowyg-box,
+.trumbowyg-editor {
+    display: block;
+    position: relative;
+    border: 1px solid #DDD;
+    width: 100%;
+    min-height: 300px;
+}
+
+.trumbowyg-box .trumbowyg-editor {
+    margin: 0 auto;
+}
+
+.trumbowyg-box.trumbowyg-fullscreen {
+    background: #FEFEFE;
+    border: none !important;
+}
+
+.trumbowyg-editor,
+.trumbowyg-textarea {
+    position: relative;
+    box-sizing: border-box;
+    padding: 20px;
+    min-height: 300px;
+    width: 100%;
+    border-style: none;
+    resize: none;
+    outline: none;
+    overflow: auto;
+    user-select: text; // Avoid issues on iOS
+
+    &.trumbowyg-autogrow-on-enter {
+        transition: height $slow-transition-duration ease-out;
+    }
+}
+
+.trumbowyg-box-blur .trumbowyg-editor {
+
+    *,
+    &::before {
+        color: transparent !important;
+        text-shadow: 0 0 7px #333;
+
+        @media screen and (min-width: 0 \0) {
+            color: rgba(200, 200, 200, 0.6) !important;
+        }
+
+        @supports (-ms-accelerator:true) {
+            color: rgba(200, 200, 200, 0.6) !important;
+        }
+    }
+
+    img,
+    hr {
+        opacity: 0.2;
+    }
+}
+
+.trumbowyg-textarea {
+    position: relative;
+    display: block;
+    overflow: auto;
+    border: none;
+    font-size: 14px;
+    font-family: "Inconsolata", "Consolas", "Courier", "Courier New", 
sans-serif;
+    line-height: 18px;
+}
+
+.trumbowyg-box.trumbowyg-editor-visible {
+    .trumbowyg-textarea {
+        height: 1px !important;
+        width: 25%;
+        min-height: 0 !important;
+        padding: 0 !important;
+        background: none;
+        opacity: 0 !important;
+    }
+}
+
+.trumbowyg-box.trumbowyg-editor-hidden {
+    .trumbowyg-textarea {
+        display: block;
+        margin-bottom: 1px;
+    }
+
+    .trumbowyg-editor {
+        display: none;
+    }
+}
+
+.trumbowyg-box.trumbowyg-disabled {
+    .trumbowyg-textarea {
+        opacity: 0.8;
+        background: none;
+    }
+}
+
+.trumbowyg-editor[contenteditable=true]:empty:not(:focus)::before {
+    content: attr(placeholder);
+    color: #999;
+    pointer-events: none;
+    white-space: break-spaces;
+}
+
+.trumbowyg-button-pane {
+    width: 100%;
+    min-height: 36px;
+    background: $light-color;
+    border-bottom: 1px solid darken($light-color, 7%);
+    margin: 0;
+    padding: 0 5px;
+    position: relative;
+    list-style-type: none;
+    line-height: 10px;
+    backface-visibility: hidden;
+    z-index: 11;
+
+    &::after {
+        content: " ";
+        display: block;
+        position: absolute;
+        top: 36px;
+        left: 0;
+        right: 0;
+        width: 100%;
+        height: 1px;
+        background: darken($light-color, 7%);
+    }
+
+    .trumbowyg-button-group {
+        display: inline-block;
+
+        .trumbowyg-fullscreen-button svg {
+            color: transparent;
+        }
+
+        &::after {
+            content: " ";
+            display: inline-block;
+            width: 1px;
+            background: darken($light-color, 7%);
+            margin: 0 5px;
+            height: 35px;
+            vertical-align: top;
+        }
+
+        &:last-child::after {
+            content: none;
+        }
+    }
+
+    button {
+        display: inline-block;
+        position: relative;
+        width: 35px;
+        height: 35px;
+        padding: 1px 6px !important;
+        margin-bottom: 1px;
+        overflow: hidden;
+        border: none;
+        cursor: pointer;
+        background: none;
+        vertical-align: middle;
+        transition: background-color $transition-duration, opacity 
$transition-duration;
+
+        &.trumbowyg-textual-button {
+            width: auto;
+            line-height: 35px;
+            user-select: none;
+        }
+    }
+
+    &.trumbowyg-disable 
button:not(.trumbowyg-not-disable):not(.trumbowyg-active),
+    button.trumbowyg-disable,
+    .trumbowyg-disabled & 
button:not(.trumbowyg-not-disable):not(.trumbowyg-viewHTML-button) {
+        opacity: 0.2;
+        cursor: default;
+        pointer-events: none;
+    }
+
+    &.trumbowyg-disable,
+    .trumbowyg-disabled & {
+        .trumbowyg-button-group::before {
+            background: darken($light-color, 3%);
+        }
+    }
+
+    button:not(.trumbowyg-disable):hover,
+    button:not(.trumbowyg-disable):focus,
+    button.trumbowyg-active {
+        background-color: #FFF;
+        outline: none;
+    }
+
+    .trumbowyg-open-dropdown {
+        &::after {
+            display: block;
+            content: " ";
+            position: absolute;
+            top: 25px;
+            right: 3px;
+            height: 0;
+            width: 0;
+            border: 3px solid transparent;
+            border-top-color: #555;
+        }
+
+        &.trumbowyg-textual-button {
+            padding-left: 10px !important;
+            padding-right: 18px !important;
+
+            &::after {
+                top: 17px;
+                right: 7px;
+            }
+        }
+    }
+
+    .trumbowyg-right {
+        float: right;
+    }
+}
+
+.trumbowyg-dropdown {
+    max-width: 300px;
+    max-height: 250px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    white-space: nowrap;
+    border: 1px solid $light-color;
+    padding: 5px 0;
+    border-top: none;
+    background: #FFF;
+    margin-left: -1px;
+    box-shadow: rgba(0, 0, 0, .1) 0 2px 3px;
+    z-index: 12;
+
+    button {
+        display: block;
+        width: 100%;
+        height: 35px;
+        line-height: 35px;
+        text-decoration: none;
+        background: #FFF;
+        padding: 0 20px 0 10px;
+        color: #333 !important;
+        border: none;
+        cursor: pointer;
+        text-align: left;
+        font-size: 15px;
+        transition: all $transition-duration;
+
+        &:hover,
+        &:focus {
+            background: $light-color;
+        }
+
+        svg {
+            float: left;
+            margin-right: 14px;
+        }
+    }
+}
+
+/* Modal box */
+.trumbowyg-modal {
+    position: absolute;
+    top: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    max-width: 520px;
+    width: 100%;
+    height: 350px;
+    z-index: 12;
+    overflow: hidden;
+    backface-visibility: hidden;
+}
+
+.trumbowyg-modal-box {
+    position: absolute;
+    top: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    max-width: 500px;
+    width: calc(100% - 20px);
+    padding-bottom: 45px;
+    z-index: 1;
+    background-color: #FFF;
+    text-align: center;
+    font-size: 14px;
+    box-shadow: rgba(0, 0, 0, .2) 0 2px 3px;
+    backface-visibility: hidden;
+
+    .trumbowyg-modal-title {
+        font-size: 24px;
+        font-weight: bold;
+        margin: 0 0 20px;
+        padding: 15px 0 13px;
+        display: block;
+        border-bottom: 1px solid #EEE;
+        color: #333;
+        background: lighten($light-color, 5%);
+    }
+
+    .trumbowyg-progress {
+        width: 100%;
+        height: 3px;
+        position: absolute;
+        top: 58px;
+
+        .trumbowyg-progress-bar {
+            background: #2BC06A;
+            width: 0;
+            height: 100%;
+            transition: width $transition-duration linear;
+        }
+    }
+
+    label {
+        display: block;
+        position: relative;
+        margin: 15px 12px;
+        height: 29px;
+        line-height: 29px;
+        overflow: hidden;
+
+        .trumbowyg-input-infos {
+            display: block;
+            text-align: left;
+            height: 25px;
+            line-height: 25px;
+            transition: all 150ms;
+
+            span {
+                display: block;
+                color: darken($light-color, 45%);
+                background-color: lighten($light-color, 5%);
+                border: 1px solid #DEDEDE;
+                padding: 0 7px;
+                width: 150px;
+            }
+
+            span.trumbowyg-msg-error {
+                color: #e74c3c;
+            }
+        }
+
+        &.trumbowyg-input-error {
+
+            input,
+            textarea {
+                border: 1px solid #e74c3c;
+            }
+
+            .trumbowyg-input-infos {
+                margin-top: -27px;
+            }
+        }
+
+        input {
+            position: absolute;
+            top: 0;
+            right: 0;
+            height: 27px;
+            line-height: 27px;
+            border: 1px solid #DEDEDE;
+            background: #fff;
+            font-size: 14px;
+            max-width: 330px;
+            width: 70%;
+            padding: 0 7px;
+            transition: all $transition-duration;
+
+            &:hover,
+            &:focus {
+                outline: none;
+                border: 1px solid #95a5a6;
+            }
+
+            &:focus {
+                background: lighten($light-color, 5%);
+            }
+        }
+
+        input[type="checkbox"] {
+            left: 6px;
+            top: 6px;
+            right: auto;
+            height: 16px;
+            width: 16px;
+
+            +.trumbowyg-input-infos span {
+                width: auto;
+                padding-left: 25px;
+            }
+        }
+    }
+
+    .error {
+        margin-top: 25px;
+        display: block;
+        color: red;
+    }
+
+    .trumbowyg-modal-button {
+        position: absolute;
+        bottom: 10px;
+        right: 0;
+        text-decoration: none;
+        color: #FFF;
+        display: block;
+        width: 100px;
+        height: 35px;
+        line-height: 33px;
+        margin: 0 10px;
+        background-color: #333;
+        border: none;
+        cursor: pointer;
+        font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif;
+        font-size: 16px;
+        transition: all $transition-duration;
+
+        &.trumbowyg-modal-submit {
+            right: 110px;
+            background: darken($modal-submit-color, 3%);
+
+            &:hover,
+            &:focus {
+                background: lighten($modal-submit-color, 5%);
+                outline: none;
+            }
+
+            &:active {
+                background: darken($modal-submit-color, 10%);
+            }
+        }
+
+        &.trumbowyg-modal-reset {
+            color: #555;
+            background: darken($modal-reset-color, 3%);
+
+            &:hover,
+            &:focus {
+                background: lighten($modal-reset-color, 5%);
+                outline: none;
+            }
+
+            &:active {
+                background: darken($modal-reset-color, 10%);
+            }
+        }
+    }
+}
+
+.trumbowyg-overlay {
+    position: absolute;
+    background-color: rgba(255, 255, 255, 0.5);
+    height: 100%;
+    width: 100%;
+    left: 0;
+    display: none;
+    top: 0;
+    z-index: 10;
+}
+
+/**
+ * Fullscreen
+ */
+body.trumbowyg-body-fullscreen {
+    overflow: hidden;
+}
+
+.trumbowyg-fullscreen {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    z-index: 99999;
+
+    &.trumbowyg-box,
+    .trumbowyg-editor {
+        border: none;
+    }
+
+    .trumbowyg-editor,
+    .trumbowyg-textarea {
+        height: calc(100% - 37px) !important;
+        overflow: auto;
+    }
+
+    .trumbowyg-overlay {
+        height: 100% !important;
+    }
+
+    .trumbowyg-button-group .trumbowyg-fullscreen-button svg {
+        color: $dark-color;
+        fill: transparent;
+    }
+}
+
+.trumbowyg-editor {
+
+    object,
+    embed,
+    video,
+    img {
+        max-width: 100%;
+    }
+
+    video,
+    img {
+        height: auto;
+    }
+
+    img {
+        cursor: move;
+    }
+
+    canvas:focus {
+        outline: none;
+    }
+
+    /*
+     * lset for resetCss option
+     */
+    &.trumbowyg-reset-css {
+        background: #FEFEFE !important;
+        font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif !important;
+        font-size: 14px !important;
+        line-height: 1.45em !important;
+        color: #333;
+
+        a {
+            color: #15c !important;
+            text-decoration: underline !important;
+        }
+
+        div,
+        p,
+        ul,
+        ol,
+        blockquote {
+            box-shadow: none !important;
+            background: none !important;
+            margin: 0 !important;
+            margin-bottom: 15px !important;
+            line-height: 1.4em !important;
+            font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif 
!important;
+            font-size: 14px !important;
+            border: none;
+        }
+
+        iframe,
+        object,
+        hr {
+            margin-bottom: 15px !important;
+        }
+
+        blockquote {
+            margin-left: 32px !important;
+            font-style: italic !important;
+            color: #555;
+        }
+
+        ul {
+            list-style: disc;
+        }
+
+        ol {
+            list-style: decimal;
+        }
+
+        ul,
+        ol {
+            padding-left: 20px !important;
+        }
+
+        ul ul,
+        ol ol,
+        ul ol,
+        ol ul {
+            border: none;
+            margin: 2px !important;
+            padding: 0 !important;
+            padding-left: 24px !important;
+        }
+
+        hr {
+            display: block;
+            height: 1px;
+            border: none;
+            border-top: 1px solid #CCC;
+        }
+
+        h1,
+        h2,
+        h3,
+        h4 {
+            color: #111;
+            background: none;
+            margin: 0 !important;
+            padding: 0 !important;
+            font-weight: bold;
+        }
+
+        h1 {
+            font-size: 32px !important;
+            line-height: 38px !important;
+            margin-bottom: 20px !important;
+        }
+
+        h2 {
+            font-size: 26px !important;
+            line-height: 34px !important;
+            margin-bottom: 15px !important;
+        }
+
+        h3 {
+            font-size: 22px !important;
+            line-height: 28px !important;
+            margin-bottom: 7px !important;
+        }
+
+        h4 {
+            font-size: 16px !important;
+            line-height: 22px !important;
+            margin-bottom: 7px !important;
+        }
+    }
+}
+
+.trumbowyg-dropdown button svg {
+    display: none;
+}
+
+/*
+ * Dark theme
+ */
+.trumbowyg-dark {
+    .trumbowyg-textarea {
+        background: #111;
+        color: #ddd;
+    }
+
+    .trumbowyg-box {
+        border: 1px solid lighten($dark-color, 7%);
+
+        &.trumbowyg-fullscreen {
+            background: #111;
+        }
+
+        &.trumbowyg-box-blur .trumbowyg-editor {
+
+            *,
+            &::before {
+                text-shadow: 0 0 7px #ccc;
+
+                @media screen and (min-width: 0 \0) {
+                    color: rgba(20, 20, 20, 0.6) !important;
+                }
+
+                @supports (-ms-accelerator:true) {
+                    color: rgba(20, 20, 20, 0.6) !important;
+                }
+            }
+        }
+
+        svg {
+            fill: $light-color;
+            color: $light-color;
+        }
+    }
+
+    .trumbowyg-button-pane {
+        background-color: $dark-color;
+        border-bottom-color: lighten($dark-color, 7%);
+
+        &::after {
+            background: lighten($dark-color, 7%);
+        }
+
+        .trumbowyg-button-group:not(:empty) {
+            &::after {
+                background-color: lighten($dark-color, 7%);
+            }
+
+            .trumbowyg-fullscreen-button svg {
+                color: transparent;
+            }
+        }
+
+        &.trumbowyg-disable {
+            .trumbowyg-button-group::after {
+                background-color: lighten($dark-color, 3%);
+            }
+        }
+
+        button:not(.trumbowyg-disable):hover,
+        button:not(.trumbowyg-disable):focus,
+        button.trumbowyg-active {
+            background-color: #333;
+        }
+
+        .trumbowyg-open-dropdown::after {
+            border-top-color: #fff;
+        }
+    }
+
+    .trumbowyg-fullscreen {
+        .trumbowyg-button-pane .trumbowyg-button-group:not(:empty) 
.trumbowyg-fullscreen-button svg {
+            color: $light-color;
+            fill: transparent;
+        }
+    }
+
+    .trumbowyg-dropdown {
+        border-color: $dark-color;
+        background: #333;
+        box-shadow: rgba(0, 0, 0, .3) 0 2px 3px;
+
+        button {
+            background: #333;
+            color: #fff !important;
+
+            &:hover,
+            &:focus {
+                background: $dark-color;
+            }
+        }
+    }
+
+    // Modal box
+    .trumbowyg-modal-box {
+        background-color: $dark-color;
+
+        .trumbowyg-modal-title {
+            border-bottom: 1px solid #555;
+            color: #fff;
+            background: lighten($dark-color, 10%);
+        }
+
+        label {
+            display: block;
+            position: relative;
+            margin: 15px 12px;
+            height: 27px;
+            line-height: 27px;
+            overflow: hidden;
+
+            .trumbowyg-input-infos {
+                span {
+                    color: #eee;
+                    background-color: lighten($dark-color, 5%);
+                    border-color: $dark-color;
+                }
+
+                span.trumbowyg-msg-error {
+                    color: #e74c3c;
+                }
+            }
+
+            &.trumbowyg-input-error {
+
+                input,
+                textarea {
+                    border-color: #e74c3c;
+                }
+            }
+
+            input {
+                border-color: $dark-color;
+                color: #eee;
+                background: #333;
+
+                &:hover,
+                &:focus {
+                    border-color: lighten($dark-color, 25%);
+                }
+
+                &:focus {
+                    background-color: lighten($dark-color, 5%);
+                }
+            }
+        }
+
+        .trumbowyg-modal-button {
+            &.trumbowyg-modal-submit {
+                background: darken($modal-submit-color, 20%);
+
+                &:hover,
+                &:focus {
+                    background: darken($modal-submit-color, 10%);
+                }
+
+                &:active {
+                    background: darken($modal-submit-color, 25%);
+                }
+            }
+
+            &.trumbowyg-modal-reset {
+                background: #333;
+                color: #ccc;
+
+                &:hover,
+                &:focus {
+                    background: #444;
+                }
+
+                &:active {
+                    background: #111;
+                }
+            }
+        }
+    }
+
+    .trumbowyg-overlay {
+        background-color: rgba(15, 15, 15, 0.6);
+    }
+}
\ No newline at end of file
diff --git a/dashboardv2/public/js/external_lib/dompurify/purify.min.js 
b/dashboardv2/public/js/external_lib/dompurify/purify.min.js
new file mode 100644
index 0000000..602e48e
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/dompurify/purify.min.js
@@ -0,0 +1,3 @@
+/*! @license DOMPurify 2.3.4 | (c) Cure53 and other contributors | Released 
under the Apache license 2.0 and Mozilla Public License 2.0 | 
github.com/cure53/DOMPurify/blob/2.3.4/LICENSE */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof 
module?module.exports=t():"function"==typeof 
define&&define.amd?define(t):(e=e||self).DOMPurify=t()}(this,(function(){"use 
strict";var 
e=Object.hasOwnProperty,t=Object.setPrototypeOf,n=Object.isFrozen,r=Object.getPrototypeOf,o=Object.getOwnPropertyDescriptor,i=Object.freeze,a=Object.seal,l=Object.create,c="undefined"!=typeof
 Reflect&&Reflect,s=c.apply,u=c.construct;s||(s=function(e,t,n){return 
e.apply(t,n)}),i||(i=function(e){r [...]
+//# sourceMappingURL=purify.min.js.map
diff --git a/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js 
b/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js
new file mode 100644
index 0000000..7ef6d17
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/trumbowyg/trumbowyg.js
@@ -0,0 +1,12 @@
+/** Trumbowyg v2.24.0 - A lightweight WYSIWYG editor - 
alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / 
alex-d.fr */
+/**
+ * Trumbowyg v2.24.0 - A lightweight WYSIWYG editor
+ * Trumbowyg core file
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ *         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
diff --git a/dashboardv2/public/js/external_lib/trumbowyg/ui/icons.svg 
b/dashboardv2/public/js/external_lib/trumbowyg/ui/icons.svg
new file mode 100644
index 0000000..e7d0dfc
--- /dev/null
+++ b/dashboardv2/public/js/external_lib/trumbowyg/ui/icons.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink";><symbol id="trumbowyg-blockquote" 
viewBox="0 0 72 72"><path d="M21.3 31.9h-.6c.8-1.2 1.9-2.2 3.4-3.2 2.1-1.4 
5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2.4 1.4-4.3 3.1-5.8 4.9-2.3 
2.7-3.7 5.7-4.5 8.5-.8 2.8-1 5.4-1 7.5 0 2.3.3 4 .4 4.8 0 .1.1.3.1.4 1.2 5.4 
6.1 9.5 11.9 9.5 6.7 0 12.2-5.4 12.2-12.2s-5.5-12-12.2-12zM49.5 31.9h-.6c.8-1.2 
1.9-2.2 3.4-3.2 2.1-1.4 5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2 [...]
\ No newline at end of file
diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js
index f2ea1d8..603e5ec 100644
--- a/dashboardv2/public/js/main.js
+++ b/dashboardv2/public/js/main.js
@@ -133,6 +133,13 @@ require.config({
         },
         'jquery-steps': {
             'deps': ['jquery']
+        },
+        'DOMPurify': {
+            'exports': 'DOMPurify'
+        },
+        'trumbowyg': {
+            'deps': ['jquery'],
+            'exports': 'trumbowyg'
         }
     },
 
@@ -179,7 +186,9 @@ require.config({
         'jquery-steps': 'libs/jquery-steps/jquery.steps.min',
         'dropzone': 'libs/dropzone/js/dropzone-amd-module',
         'lossless-json': 'libs/lossless-json/lossless-json',
-        'store': 'external_lib/idealTimeout/store.min'
+        'store': 'external_lib/idealTimeout/store.min',
+        'DOMPurify': 'external_lib/dompurify/purify.min',
+        'trumbowyg': 'external_lib/trumbowyg/trumbowyg'
     },
 
     /**
diff --git 
a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
index b81f749..c8b55f7 100644
--- 
a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
+++ 
b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
@@ -27,10 +27,18 @@
                 <p data-id="shortDescription"></p>
             </div>
         </div>
-        <div class="form-group clearfix">
+        <div class="long-description-container form-group clearfix">
             <span class="pull-left text-muted">Long Description:&nbsp;</span>
-            <div>
-                <textarea class="form-control long-description" 
name="longDescription" data-id="longDescription" disabled></textarea>
+            <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="glossary-longdescription-wrapper form-control 
col-sm-12">
+                <div class="long-description" name="longDescription" 
data-id="longDescription" disabled></div>
             </div>
         </div>
         {{#if isTermView}}
diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js 
b/dashboardv2/public/js/utils/CommonViewFunction.js
index f7400c2..eb3a515 100644
--- a/dashboardv2/public/js/utils/CommonViewFunction.js
+++ b/dashboardv2/public/js/utils/CommonViewFunction.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 
'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, 
Utils, Modal, Messages, Enums, moment, Globals) {
+define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 
'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, 
Utils, Modal, Messages, Enums, moment, Globals, momentTimezone) {
     'use strict';
 
     var CommonViewFunction = {};
@@ -691,12 +691,23 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
             var model = options.model,
                 isTermView = options.isTermView,
                 isGlossaryView = options.isGlossaryView,
-                collection = options.collection
+                collection = options.collection;
+            //Below condition is added for sanitizing the longDescription text 
against XSS attack.
+            if (model) {
+                var longDescriptionContent = isGlossaryView ? 
model.get('longDescription') : model.longDescription,
+                    sanitizeLongDescriptionContent;
+                if (longDescriptionContent) {
+                    sanitizeLongDescriptionContent = 
Utils.sanitizeHtmlContent(longDescriptionContent);
+                    isGlossaryView ? model.set("longDescription", 
sanitizeLongDescriptionContent) : model.longDescription = 
sanitizeLongDescriptionContent;
+                }
+            }
+            //End
         }
         require([
             'views/glossary/CreateEditCategoryTermLayoutView',
             'views/glossary/CreateEditGlossaryLayoutView',
-            'modules/Modal'
+            'modules/Modal',
+            'trumbowyg'
         ], function(CreateEditCategoryTermLayoutView, 
CreateEditGlossaryLayoutView, Modal) {
             var view = null,
                 title = null;
@@ -714,14 +725,40 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
                 "cancelText": "Cancel",
                 "okCloses": false,
                 "okText": model ? "Update" : "Create",
-                "allowCancel": true
+                "allowCancel": true,
+                "width": "765px"
             }).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");
+            });
             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);
+                }
+                //End
                 
CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, 
"modal": modal }, options));
             });
             modal.on('closeModal', function() {
diff --git a/dashboardv2/public/js/utils/Utils.js 
b/dashboardv2/public/js/utils/Utils.js
index f2498d8..f3126db 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', 'moment-timezone', 
'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, 
Messages, Enums, moment, store, Modal) {
+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) {
     'use strict';
 
     var Utils = {};
@@ -952,6 +952,14 @@ 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) {
 
@@ -1222,4 +1230,4 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
 
     //------------------------------------------------
     return Utils;
-});
\ No newline at end of file
+});
diff --git a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js 
b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
index 0a13162..b070c55 100644
--- a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
@@ -70,6 +70,7 @@ define(['require',
                 removeTag: '[data-id="removeTagTerm"]',
                 tagClick: '[data-id="tagClickTerm"]',
                 addTag: '[data-id="addTagTerm"]',
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
@@ -168,6 +169,10 @@ define(['require',
                 events["click " + this.ui.addTerm] = 'onClickAddTermBtn';
                 events["click " + this.ui.addCategory] = 'onClickAddTermBtn';
                 events["click " + this.ui.addTag] = 'onClickAddTagBtn';
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.renderDetails(this.data);
+                };
                 return events;
             },
             /**
@@ -186,6 +191,7 @@ define(['require',
                     }
                 }
                 this.selectedTermAttribute = null;
+                this.isTextTypeChecked = false;
             },
             onRender: function() {
                 this.$('.fontLoader-relative').show();
@@ -297,10 +303,18 @@ define(['require',
             },
             renderDetails: function(data) {
                 Utils.hideTitleLoader(this.$('.fontLoader'), this.ui.details);
+                //Below condition is added for sanitizing the longDescription 
text against XSS attack.
+                var longDescriptionContent = (data && data.longDescription) ? 
data.longDescription : "",
+                    sanitizeLongDescriptionContent = "";
+                if (longDescriptionContent !== "") {
+                    sanitizeLongDescriptionContent = 
Utils.sanitizeHtmlContent(longDescriptionContent);
+                }
+                //End
                 if (data) {
+                    var longDescriptionValue = longDescriptionContent ? 
sanitizeLongDescriptionContent : "";
                     this.ui.title.text(data.name || data.displayText || 
data.qualifiedName);
                     this.ui.shortDescription.text(data.shortDescription ? 
data.shortDescription : "");
-                    this.ui.longDescription.text(data.longDescription ? 
data.longDescription : "");
+                    this.isTextTypeChecked ? 
this.ui.longDescription.text(longDescriptionValue) : 
this.ui.longDescription.html(longDescriptionValue);
                     this.generateCategories(data.categories);
                     this.generateTerm(data.terms);
                     this.generateTag(data.classifications);
diff --git a/dashboardv3/public/css/scss/common.scss 
b/dashboardv3/public/css/scss/common.scss
index 9310e20..c13c47c 100644
--- a/dashboardv3/public/css/scss/common.scss
+++ b/dashboardv3/public/css/scss/common.scss
@@ -340,7 +340,8 @@ pre {
 }
 
 .long-description {
-    width: 85%;
+    width: 100%;
+    overflow-wrap: break-word;
     cursor: default !important;
     background-color: transparent !important;
 }
\ No newline at end of file
diff --git a/dashboardv3/public/css/scss/override.scss 
b/dashboardv3/public/css/scss/override.scss
index fb3604d..fec5f6f 100644
--- a/dashboardv3/public/css/scss/override.scss
+++ b/dashboardv3/public/css/scss/override.scss
@@ -562,6 +562,33 @@ div.columnmanager-dropdown-container {
     padding-top: 20px;
 }
 
+.long-description-container,
+.short-description-container {
+    margin-right: 0px !important;
+}
+
+.glossary-longdescription-wrapper {
+    display: inline-block;
+    height: 100px;
+    background-color: #fff !important;
+    overflow: auto;
+    margin-top: 8px;
+    width: 100%;
+
+    ul {
+        list-style: disc !important;
+    }
+}
+
+.isTextTypeBtn-wrapper {
+    display: inline-block;
+    line-height: 22px;
+
+    .switch {
+        margin-bottom: 0px;
+    }
+}
+
 .select2-container--default .select2-search--inline .select2-search__field {
     width: 100% !important;
 }
diff --git a/dashboardv3/public/css/scss/style.scss 
b/dashboardv3/public/css/scss/style.scss
index 37d5458..53e8385 100644
--- a/dashboardv3/public/css/scss/style.scss
+++ b/dashboardv3/public/css/scss/style.scss
@@ -37,4 +37,6 @@
 @import "business-metadata.scss";
 @import "stats.scss";
 @import "override.scss";
-@import "leftsidebar.scss";
\ No newline at end of file
+@import "leftsidebar.scss";
+@import "trumbowyg.scss";
+@import "texteditor.scss";
\ No newline at end of file
diff --git a/dashboardv3/public/css/scss/texteditor.scss 
b/dashboardv3/public/css/scss/texteditor.scss
new file mode 100644
index 0000000..275bdcc
--- /dev/null
+++ b/dashboardv3/public/css/scss/texteditor.scss
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/* texteditor */
+
+.trumbowyg {
+    border-radius: 4px !important;
+    min-height: 150px !important;
+
+    .trumbowyg-button-pane {
+        background-color: #f6f7fb !important;
+    }
+
+    .trumbowyg-editor {
+        min-height: 150px !important;
+        overflow-wrap: break-word;
+    }
+
+    ul {
+        list-style: disc !important;
+    }
+
+    .trumbowyg-textarea {
+        min-height: 150px !important;
+    }
+}
+
+.trumbowyg-modal-submit,
+.trumbowyg-modal-reset {
+    border: 1px #37bb9b solid !important;
+    color: #37bb9b !important;
+    border-radius: 4px !important;
+    font-size: 14px !important;
+    background-color: transparent !important;
+}
+
+.trumbowyg-modal-submit:hover,
+.trumbowyg-modal-reset:hover {
+    background-color: #37bb9b !important;
+    color: #fff !important;
+}
+
+.trumbowyg-modal-box label .trumbowyg-input-infos span {
+    color: #686868 !important;
+}
+
+.trumbowyg-viewHTML-button {
+    width: 101px !important;
+}
+
+.trumbowyg-h1-dropdown-button{
+    font-size: 36px !important;
+}
+.trumbowyg-h2-dropdown-button{
+    font-size: 30px !important;
+}
+.trumbowyg-h3-dropdown-button{
+    font-size: 24px !important;
+}
+.trumbowyg-h4-dropdown-button{
+    font-size: 18px !important;
+}
\ No newline at end of file
diff --git a/dashboardv3/public/css/scss/trumbowyg.scss 
b/dashboardv3/public/css/scss/trumbowyg.scss
new file mode 100644
index 0000000..a5463ea
--- /dev/null
+++ b/dashboardv3/public/css/scss/trumbowyg.scss
@@ -0,0 +1,889 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/* trumbowyg */
+
+/**
+ * Trumbowyg v2.24.0 - A lightweight WYSIWYG editor
+ * Default stylesheet for Trumbowyg editor
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ *         Twitter : @AlexandreDemode
+ *         Website : alex-d.fr
+ */
+
+$light-color: #ecf0f1 !default;
+$dark-color: #222 !default;
+
+$modal-submit-color: #2ecc71 !default;
+$modal-reset-color: #EEE !default;
+
+$transition-duration: 150ms !default;
+$slow-transition-duration: 300ms !default;
+
+#trumbowyg-icons {
+    overflow: hidden;
+    visibility: hidden;
+    height: 0;
+    width: 0;
+
+    svg {
+        height: 0;
+        width: 0;
+    }
+}
+
+.trumbowyg-box,
+.trumbowyg-modal {
+
+    *,
+    *::before,
+    *::after {
+        box-sizing: border-box;
+    }
+
+    svg {
+        width: 17px;
+        height: 100%;
+        fill: $dark-color;
+    }
+}
+
+.trumbowyg-box,
+.trumbowyg-editor {
+    display: block;
+    position: relative;
+    border: 1px solid #DDD;
+    width: 100%;
+    min-height: 300px;
+}
+
+.trumbowyg-box .trumbowyg-editor {
+    margin: 0 auto;
+}
+
+.trumbowyg-box.trumbowyg-fullscreen {
+    background: #FEFEFE;
+    border: none !important;
+}
+
+.trumbowyg-editor,
+.trumbowyg-textarea {
+    position: relative;
+    box-sizing: border-box;
+    padding: 20px;
+    min-height: 300px;
+    width: 100%;
+    border-style: none;
+    resize: none;
+    outline: none;
+    overflow: auto;
+    user-select: text; // Avoid issues on iOS
+
+    &.trumbowyg-autogrow-on-enter {
+        transition: height $slow-transition-duration ease-out;
+    }
+}
+
+.trumbowyg-box-blur .trumbowyg-editor {
+
+    *,
+    &::before {
+        color: transparent !important;
+        text-shadow: 0 0 7px #333;
+
+        @media screen and (min-width: 0 \0) {
+            color: rgba(200, 200, 200, 0.6) !important;
+        }
+
+        @supports (-ms-accelerator:true) {
+            color: rgba(200, 200, 200, 0.6) !important;
+        }
+    }
+
+    img,
+    hr {
+        opacity: 0.2;
+    }
+}
+
+.trumbowyg-textarea {
+    position: relative;
+    display: block;
+    overflow: auto;
+    border: none;
+    font-size: 14px;
+    font-family: "Inconsolata", "Consolas", "Courier", "Courier New", 
sans-serif;
+    line-height: 18px;
+}
+
+.trumbowyg-box.trumbowyg-editor-visible {
+    .trumbowyg-textarea {
+        height: 1px !important;
+        width: 25%;
+        min-height: 0 !important;
+        padding: 0 !important;
+        background: none;
+        opacity: 0 !important;
+    }
+}
+
+.trumbowyg-box.trumbowyg-editor-hidden {
+    .trumbowyg-textarea {
+        display: block;
+        margin-bottom: 1px;
+    }
+
+    .trumbowyg-editor {
+        display: none;
+    }
+}
+
+.trumbowyg-box.trumbowyg-disabled {
+    .trumbowyg-textarea {
+        opacity: 0.8;
+        background: none;
+    }
+}
+
+.trumbowyg-editor[contenteditable=true]:empty:not(:focus)::before {
+    content: attr(placeholder);
+    color: #999;
+    pointer-events: none;
+    white-space: break-spaces;
+}
+
+.trumbowyg-button-pane {
+    width: 100%;
+    min-height: 36px;
+    background: $light-color;
+    border-bottom: 1px solid darken($light-color, 7%);
+    margin: 0;
+    padding: 0 5px;
+    position: relative;
+    list-style-type: none;
+    line-height: 10px;
+    backface-visibility: hidden;
+    z-index: 11;
+
+    &::after {
+        content: " ";
+        display: block;
+        position: absolute;
+        top: 36px;
+        left: 0;
+        right: 0;
+        width: 100%;
+        height: 1px;
+        background: darken($light-color, 7%);
+    }
+
+    .trumbowyg-button-group {
+        display: inline-block;
+
+        .trumbowyg-fullscreen-button svg {
+            color: transparent;
+        }
+
+        &::after {
+            content: " ";
+            display: inline-block;
+            width: 1px;
+            background: darken($light-color, 7%);
+            margin: 0 5px;
+            height: 35px;
+            vertical-align: top;
+        }
+
+        &:last-child::after {
+            content: none;
+        }
+    }
+
+    button {
+        display: inline-block;
+        position: relative;
+        width: 35px;
+        height: 35px;
+        padding: 1px 6px !important;
+        margin-bottom: 1px;
+        overflow: hidden;
+        border: none;
+        cursor: pointer;
+        background: none;
+        vertical-align: middle;
+        transition: background-color $transition-duration, opacity 
$transition-duration;
+
+        &.trumbowyg-textual-button {
+            width: auto;
+            line-height: 35px;
+            user-select: none;
+        }
+    }
+
+    &.trumbowyg-disable 
button:not(.trumbowyg-not-disable):not(.trumbowyg-active),
+    button.trumbowyg-disable,
+    .trumbowyg-disabled & 
button:not(.trumbowyg-not-disable):not(.trumbowyg-viewHTML-button) {
+        opacity: 0.2;
+        cursor: default;
+        pointer-events: none;
+    }
+
+    &.trumbowyg-disable,
+    .trumbowyg-disabled & {
+        .trumbowyg-button-group::before {
+            background: darken($light-color, 3%);
+        }
+    }
+
+    button:not(.trumbowyg-disable):hover,
+    button:not(.trumbowyg-disable):focus,
+    button.trumbowyg-active {
+        background-color: #FFF;
+        outline: none;
+    }
+
+    .trumbowyg-open-dropdown {
+        &::after {
+            display: block;
+            content: " ";
+            position: absolute;
+            top: 25px;
+            right: 3px;
+            height: 0;
+            width: 0;
+            border: 3px solid transparent;
+            border-top-color: #555;
+        }
+
+        &.trumbowyg-textual-button {
+            padding-left: 10px !important;
+            padding-right: 18px !important;
+
+            &::after {
+                top: 17px;
+                right: 7px;
+            }
+        }
+    }
+
+    .trumbowyg-right {
+        float: right;
+    }
+}
+
+.trumbowyg-dropdown {
+    max-width: 300px;
+    max-height: 250px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    white-space: nowrap;
+    border: 1px solid $light-color;
+    padding: 5px 0;
+    border-top: none;
+    background: #FFF;
+    margin-left: -1px;
+    box-shadow: rgba(0, 0, 0, .1) 0 2px 3px;
+    z-index: 12;
+
+    button {
+        display: block;
+        width: 100%;
+        height: 35px;
+        line-height: 35px;
+        text-decoration: none;
+        background: #FFF;
+        padding: 0 20px 0 10px;
+        color: #333 !important;
+        border: none;
+        cursor: pointer;
+        text-align: left;
+        font-size: 15px;
+        transition: all $transition-duration;
+
+        &:hover,
+        &:focus {
+            background: $light-color;
+        }
+
+        svg {
+            float: left;
+            margin-right: 14px;
+        }
+    }
+}
+
+/* Modal box */
+.trumbowyg-modal {
+    position: absolute;
+    top: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    max-width: 520px;
+    width: 100%;
+    height: 350px;
+    z-index: 12;
+    overflow: hidden;
+    backface-visibility: hidden;
+}
+
+.trumbowyg-modal-box {
+    position: absolute;
+    top: 0;
+    left: 50%;
+    transform: translateX(-50%);
+    max-width: 500px;
+    width: calc(100% - 20px);
+    padding-bottom: 45px;
+    z-index: 1;
+    background-color: #FFF;
+    text-align: center;
+    font-size: 14px;
+    box-shadow: rgba(0, 0, 0, .2) 0 2px 3px;
+    backface-visibility: hidden;
+
+    .trumbowyg-modal-title {
+        font-size: 24px;
+        font-weight: bold;
+        margin: 0 0 20px;
+        padding: 15px 0 13px;
+        display: block;
+        border-bottom: 1px solid #EEE;
+        color: #333;
+        background: lighten($light-color, 5%);
+    }
+
+    .trumbowyg-progress {
+        width: 100%;
+        height: 3px;
+        position: absolute;
+        top: 58px;
+
+        .trumbowyg-progress-bar {
+            background: #2BC06A;
+            width: 0;
+            height: 100%;
+            transition: width $transition-duration linear;
+        }
+    }
+
+    label {
+        display: block;
+        position: relative;
+        margin: 15px 12px;
+        height: 29px;
+        line-height: 29px;
+        overflow: hidden;
+
+        .trumbowyg-input-infos {
+            display: block;
+            text-align: left;
+            height: 25px;
+            line-height: 25px;
+            transition: all 150ms;
+
+            span {
+                display: block;
+                color: darken($light-color, 45%);
+                background-color: lighten($light-color, 5%);
+                border: 1px solid #DEDEDE;
+                padding: 0 7px;
+                width: 150px;
+            }
+
+            span.trumbowyg-msg-error {
+                color: #e74c3c;
+            }
+        }
+
+        &.trumbowyg-input-error {
+
+            input,
+            textarea {
+                border: 1px solid #e74c3c;
+            }
+
+            .trumbowyg-input-infos {
+                margin-top: -27px;
+            }
+        }
+
+        input {
+            position: absolute;
+            top: 0;
+            right: 0;
+            height: 27px;
+            line-height: 27px;
+            border: 1px solid #DEDEDE;
+            background: #fff;
+            font-size: 14px;
+            max-width: 330px;
+            width: 70%;
+            padding: 0 7px;
+            transition: all $transition-duration;
+
+            &:hover,
+            &:focus {
+                outline: none;
+                border: 1px solid #95a5a6;
+            }
+
+            &:focus {
+                background: lighten($light-color, 5%);
+            }
+        }
+
+        input[type="checkbox"] {
+            left: 6px;
+            top: 6px;
+            right: auto;
+            height: 16px;
+            width: 16px;
+
+            +.trumbowyg-input-infos span {
+                width: auto;
+                padding-left: 25px;
+            }
+        }
+    }
+
+    .error {
+        margin-top: 25px;
+        display: block;
+        color: red;
+    }
+
+    .trumbowyg-modal-button {
+        position: absolute;
+        bottom: 10px;
+        right: 0;
+        text-decoration: none;
+        color: #FFF;
+        display: block;
+        width: 100px;
+        height: 35px;
+        line-height: 33px;
+        margin: 0 10px;
+        background-color: #333;
+        border: none;
+        cursor: pointer;
+        font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif;
+        font-size: 16px;
+        transition: all $transition-duration;
+
+        &.trumbowyg-modal-submit {
+            right: 110px;
+            background: darken($modal-submit-color, 3%);
+
+            &:hover,
+            &:focus {
+                background: lighten($modal-submit-color, 5%);
+                outline: none;
+            }
+
+            &:active {
+                background: darken($modal-submit-color, 10%);
+            }
+        }
+
+        &.trumbowyg-modal-reset {
+            color: #555;
+            background: darken($modal-reset-color, 3%);
+
+            &:hover,
+            &:focus {
+                background: lighten($modal-reset-color, 5%);
+                outline: none;
+            }
+
+            &:active {
+                background: darken($modal-reset-color, 10%);
+            }
+        }
+    }
+}
+
+.trumbowyg-overlay {
+    position: absolute;
+    background-color: rgba(255, 255, 255, 0.5);
+    height: 100%;
+    width: 100%;
+    left: 0;
+    display: none;
+    top: 0;
+    z-index: 10;
+}
+
+/**
+ * Fullscreen
+ */
+body.trumbowyg-body-fullscreen {
+    overflow: hidden;
+}
+
+.trumbowyg-fullscreen {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    z-index: 99999;
+
+    &.trumbowyg-box,
+    .trumbowyg-editor {
+        border: none;
+    }
+
+    .trumbowyg-editor,
+    .trumbowyg-textarea {
+        height: calc(100% - 37px) !important;
+        overflow: auto;
+    }
+
+    .trumbowyg-overlay {
+        height: 100% !important;
+    }
+
+    .trumbowyg-button-group .trumbowyg-fullscreen-button svg {
+        color: $dark-color;
+        fill: transparent;
+    }
+}
+
+.trumbowyg-editor {
+
+    object,
+    embed,
+    video,
+    img {
+        max-width: 100%;
+    }
+
+    video,
+    img {
+        height: auto;
+    }
+
+    img {
+        cursor: move;
+    }
+
+    canvas:focus {
+        outline: none;
+    }
+
+    /*
+     * lset for resetCss option
+     */
+    &.trumbowyg-reset-css {
+        background: #FEFEFE !important;
+        font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif !important;
+        font-size: 14px !important;
+        line-height: 1.45em !important;
+        color: #333;
+
+        a {
+            color: #15c !important;
+            text-decoration: underline !important;
+        }
+
+        div,
+        p,
+        ul,
+        ol,
+        blockquote {
+            box-shadow: none !important;
+            background: none !important;
+            margin: 0 !important;
+            margin-bottom: 15px !important;
+            line-height: 1.4em !important;
+            font-family: "Trebuchet MS", Helvetica, Verdana, sans-serif 
!important;
+            font-size: 14px !important;
+            border: none;
+        }
+
+        iframe,
+        object,
+        hr {
+            margin-bottom: 15px !important;
+        }
+
+        blockquote {
+            margin-left: 32px !important;
+            font-style: italic !important;
+            color: #555;
+        }
+
+        ul {
+            list-style: disc;
+        }
+
+        ol {
+            list-style: decimal;
+        }
+
+        ul,
+        ol {
+            padding-left: 20px !important;
+        }
+
+        ul ul,
+        ol ol,
+        ul ol,
+        ol ul {
+            border: none;
+            margin: 2px !important;
+            padding: 0 !important;
+            padding-left: 24px !important;
+        }
+
+        hr {
+            display: block;
+            height: 1px;
+            border: none;
+            border-top: 1px solid #CCC;
+        }
+
+        h1,
+        h2,
+        h3,
+        h4 {
+            color: #111;
+            background: none;
+            margin: 0 !important;
+            padding: 0 !important;
+            font-weight: bold;
+        }
+
+        h1 {
+            font-size: 32px !important;
+            line-height: 38px !important;
+            margin-bottom: 20px !important;
+        }
+
+        h2 {
+            font-size: 26px !important;
+            line-height: 34px !important;
+            margin-bottom: 15px !important;
+        }
+
+        h3 {
+            font-size: 22px !important;
+            line-height: 28px !important;
+            margin-bottom: 7px !important;
+        }
+
+        h4 {
+            font-size: 16px !important;
+            line-height: 22px !important;
+            margin-bottom: 7px !important;
+        }
+    }
+}
+
+.trumbowyg-dropdown button svg {
+    display: none;
+}
+
+/*
+ * Dark theme
+ */
+.trumbowyg-dark {
+    .trumbowyg-textarea {
+        background: #111;
+        color: #ddd;
+    }
+
+    .trumbowyg-box {
+        border: 1px solid lighten($dark-color, 7%);
+
+        &.trumbowyg-fullscreen {
+            background: #111;
+        }
+
+        &.trumbowyg-box-blur .trumbowyg-editor {
+
+            *,
+            &::before {
+                text-shadow: 0 0 7px #ccc;
+
+                @media screen and (min-width: 0 \0) {
+                    color: rgba(20, 20, 20, 0.6) !important;
+                }
+
+                @supports (-ms-accelerator:true) {
+                    color: rgba(20, 20, 20, 0.6) !important;
+                }
+            }
+        }
+
+        svg {
+            fill: $light-color;
+            color: $light-color;
+        }
+    }
+
+    .trumbowyg-button-pane {
+        background-color: $dark-color;
+        border-bottom-color: lighten($dark-color, 7%);
+
+        &::after {
+            background: lighten($dark-color, 7%);
+        }
+
+        .trumbowyg-button-group:not(:empty) {
+            &::after {
+                background-color: lighten($dark-color, 7%);
+            }
+
+            .trumbowyg-fullscreen-button svg {
+                color: transparent;
+            }
+        }
+
+        &.trumbowyg-disable {
+            .trumbowyg-button-group::after {
+                background-color: lighten($dark-color, 3%);
+            }
+        }
+
+        button:not(.trumbowyg-disable):hover,
+        button:not(.trumbowyg-disable):focus,
+        button.trumbowyg-active {
+            background-color: #333;
+        }
+
+        .trumbowyg-open-dropdown::after {
+            border-top-color: #fff;
+        }
+    }
+
+    .trumbowyg-fullscreen {
+        .trumbowyg-button-pane .trumbowyg-button-group:not(:empty) 
.trumbowyg-fullscreen-button svg {
+            color: $light-color;
+            fill: transparent;
+        }
+    }
+
+    .trumbowyg-dropdown {
+        border-color: $dark-color;
+        background: #333;
+        box-shadow: rgba(0, 0, 0, .3) 0 2px 3px;
+
+        button {
+            background: #333;
+            color: #fff !important;
+
+            &:hover,
+            &:focus {
+                background: $dark-color;
+            }
+        }
+    }
+
+    // Modal box
+    .trumbowyg-modal-box {
+        background-color: $dark-color;
+
+        .trumbowyg-modal-title {
+            border-bottom: 1px solid #555;
+            color: #fff;
+            background: lighten($dark-color, 10%);
+        }
+
+        label {
+            display: block;
+            position: relative;
+            margin: 15px 12px;
+            height: 27px;
+            line-height: 27px;
+            overflow: hidden;
+
+            .trumbowyg-input-infos {
+                span {
+                    color: #eee;
+                    background-color: lighten($dark-color, 5%);
+                    border-color: $dark-color;
+                }
+
+                span.trumbowyg-msg-error {
+                    color: #e74c3c;
+                }
+            }
+
+            &.trumbowyg-input-error {
+
+                input,
+                textarea {
+                    border-color: #e74c3c;
+                }
+            }
+
+            input {
+                border-color: $dark-color;
+                color: #eee;
+                background: #333;
+
+                &:hover,
+                &:focus {
+                    border-color: lighten($dark-color, 25%);
+                }
+
+                &:focus {
+                    background-color: lighten($dark-color, 5%);
+                }
+            }
+        }
+
+        .trumbowyg-modal-button {
+            &.trumbowyg-modal-submit {
+                background: darken($modal-submit-color, 20%);
+
+                &:hover,
+                &:focus {
+                    background: darken($modal-submit-color, 10%);
+                }
+
+                &:active {
+                    background: darken($modal-submit-color, 25%);
+                }
+            }
+
+            &.trumbowyg-modal-reset {
+                background: #333;
+                color: #ccc;
+
+                &:hover,
+                &:focus {
+                    background: #444;
+                }
+
+                &:active {
+                    background: #111;
+                }
+            }
+        }
+    }
+
+    .trumbowyg-overlay {
+        background-color: rgba(15, 15, 15, 0.6);
+    }
+}
\ No newline at end of file
diff --git a/dashboardv3/public/js/external_lib/dompurify/purify.min.js 
b/dashboardv3/public/js/external_lib/dompurify/purify.min.js
new file mode 100644
index 0000000..602e48e
--- /dev/null
+++ b/dashboardv3/public/js/external_lib/dompurify/purify.min.js
@@ -0,0 +1,3 @@
+/*! @license DOMPurify 2.3.4 | (c) Cure53 and other contributors | Released 
under the Apache license 2.0 and Mozilla Public License 2.0 | 
github.com/cure53/DOMPurify/blob/2.3.4/LICENSE */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof 
module?module.exports=t():"function"==typeof 
define&&define.amd?define(t):(e=e||self).DOMPurify=t()}(this,(function(){"use 
strict";var 
e=Object.hasOwnProperty,t=Object.setPrototypeOf,n=Object.isFrozen,r=Object.getPrototypeOf,o=Object.getOwnPropertyDescriptor,i=Object.freeze,a=Object.seal,l=Object.create,c="undefined"!=typeof
 Reflect&&Reflect,s=c.apply,u=c.construct;s||(s=function(e,t,n){return 
e.apply(t,n)}),i||(i=function(e){r [...]
+//# sourceMappingURL=purify.min.js.map
diff --git a/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js 
b/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js
new file mode 100644
index 0000000..7ef6d17
--- /dev/null
+++ b/dashboardv3/public/js/external_lib/trumbowyg/trumbowyg.js
@@ -0,0 +1,12 @@
+/** Trumbowyg v2.24.0 - A lightweight WYSIWYG editor - 
alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / 
alex-d.fr */
+/**
+ * Trumbowyg v2.24.0 - A lightweight WYSIWYG editor
+ * Trumbowyg core file
+ * ------------------------
+ * @link http://alex-d.github.io/Trumbowyg
+ * @license MIT
+ * @author Alexandre Demode (Alex-D)
+ *         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
diff --git a/dashboardv3/public/js/external_lib/trumbowyg/ui/icons.svg 
b/dashboardv3/public/js/external_lib/trumbowyg/ui/icons.svg
new file mode 100644
index 0000000..e7d0dfc
--- /dev/null
+++ b/dashboardv3/public/js/external_lib/trumbowyg/ui/icons.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink";><symbol id="trumbowyg-blockquote" 
viewBox="0 0 72 72"><path d="M21.3 31.9h-.6c.8-1.2 1.9-2.2 3.4-3.2 2.1-1.4 
5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2.4 1.4-4.3 3.1-5.8 4.9-2.3 
2.7-3.7 5.7-4.5 8.5-.8 2.8-1 5.4-1 7.5 0 2.3.3 4 .4 4.8 0 .1.1.3.1.4 1.2 5.4 
6.1 9.5 11.9 9.5 6.7 0 12.2-5.4 12.2-12.2s-5.5-12-12.2-12zM49.5 31.9h-.6c.8-1.2 
1.9-2.2 3.4-3.2 2.1-1.4 5-2.7 9.2-3.3l-1.4-8.9c-4.7.7-8.5 2.1-11.7 4-2 [...]
\ No newline at end of file
diff --git a/dashboardv3/public/js/main.js b/dashboardv3/public/js/main.js
index 97e177c..008fbb2 100644
--- a/dashboardv3/public/js/main.js
+++ b/dashboardv3/public/js/main.js
@@ -162,6 +162,13 @@ require.config({
         },
         'jquery-steps': {
             'deps': ['jquery']
+        },
+        'DOMPurify': {
+            'exports': 'DOMPurify'
+        },
+        'trumbowyg': {
+            'deps': ['jquery'],
+            'exports': 'trumbowyg'
         }
     },
 
@@ -208,7 +215,9 @@ require.config({
         'jquery-steps': 'libs/jquery-steps/jquery.steps.min',
         'dropzone': 'libs/dropzone/js/dropzone-amd-module',
         'lossless-json': 'libs/lossless-json/lossless-json',
-        'store': 'external_lib/idealTimeout/store.min'
+        'store': 'external_lib/idealTimeout/store.min',
+        'DOMPurify': 'external_lib/dompurify/purify.min',
+        'trumbowyg': 'external_lib/trumbowyg/trumbowyg'
     },
 
     /**
diff --git 
a/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html 
b/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
index 23a5d84..64e6031 100644
--- 
a/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
+++ 
b/dashboardv3/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
@@ -24,16 +24,24 @@
     <div data-id="details" class="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>
-        <div class="form-group col-sm-12">
+        <div class="form-group short-description-container">
             <span class="pull-left text-muted">Short Description:&nbsp;</span>
             <div class="pull-left">
                 <p data-id="shortDescription"></p>
             </div>
         </div>
-        <div class="form-group col-sm-12">
+        <div class="form-group long-description-container">
             <span class="pull-left text-muted">Long Description:&nbsp;</span>
-            <div>
-                <textarea class="form-control long-description" 
name="longDescription" data-id="longDescription" disabled></textarea>
+            <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="glossary-longdescription-wrapper form-control">
+                <div class="long-description" name="longDescription" 
data-id="longDescription" disabled></div>
             </div>
         </div>
         {{#if isTermView}}
diff --git a/dashboardv3/public/js/utils/CommonViewFunction.js 
b/dashboardv3/public/js/utils/CommonViewFunction.js
index 07954c0..418bc7f 100644
--- a/dashboardv3/public/js/utils/CommonViewFunction.js
+++ b/dashboardv3/public/js/utils/CommonViewFunction.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 
'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, 
Utils, Modal, Messages, Enums, moment, Globals) {
+define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 
'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, 
Utils, Modal, Messages, Enums, moment, Globals, momentTimezone) {
     'use strict';
 
     var CommonViewFunction = {};
@@ -711,12 +711,22 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
             var model = options.model,
                 isTermView = options.isTermView,
                 isGlossaryView = options.isGlossaryView,
-                collection = options.collection
+                collection = options.collection;
+            //Below condition is added for sanitizing the longDescription text 
against XSS attack.
+            if (model) {
+                var longDescriptionContent = isGlossaryView ? 
model.get('longDescription') : model.longDescription,
+                    sanitizeLongDescriptionContent;
+                if (longDescriptionContent) {
+                    sanitizeLongDescriptionContent = 
Utils.sanitizeHtmlContent(longDescriptionContent)
+                    isGlossaryView ? model.set("longDescription", 
sanitizeLongDescriptionContent) : model.longDescription = 
sanitizeLongDescriptionContent;
+                }
+            }
         }
         require([
             'views/glossary/CreateEditCategoryTermLayoutView',
             'views/glossary/CreateEditGlossaryLayoutView',
-            'modules/Modal'
+            'modules/Modal',
+            'trumbowyg'
         ], function(CreateEditCategoryTermLayoutView, 
CreateEditGlossaryLayoutView, Modal) {
             var view = null,
                 title = null;
@@ -734,14 +744,40 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
                 "cancelText": "Cancel",
                 "okCloses": false,
                 "okText": model ? "Update" : "Create",
-                "allowCancel": true
+                "allowCancel": true,
+                "width": "765px"
             }).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");
+            });
             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);
+                }
+                //End
                 
CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, 
"modal": modal }, options));
             });
             modal.on('closeModal', function() {
diff --git a/dashboardv3/public/js/utils/Utils.js 
b/dashboardv3/public/js/utils/Utils.js
index c3122fc..d4db9f4 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', 'moment-timezone', 
'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, 
Messages, Enums, moment, store, Modal) {
+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) {
     'use strict';
 
     var Utils = {};
@@ -964,6 +964,14 @@ 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) {
 
@@ -1230,4 +1238,4 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
 
     //------------------------------------------------
     return Utils;
-});
\ No newline at end of file
+});
diff --git a/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js 
b/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
index 79622dc..845ace1 100644
--- a/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
+++ b/dashboardv3/public/js/views/glossary/GlossaryDetailLayoutView.js
@@ -70,7 +70,8 @@ define(['require',
                 removeTag: '[data-id="removeTagTerm"]',
                 tagClick: '[data-id="tagClickTerm"]',
                 addTag: '[data-id="addTagTerm"]',
-                backButton: '[data-id="backButton"]'
+                backButton: '[data-id="backButton"]',
+                textType: '[name="textType"]'
             },
             /** ui events hash */
             events: function() {
@@ -174,6 +175,10 @@ define(['require',
                 events["click " + this.ui.addTerm] = 'onClickAddTermBtn';
                 events["click " + this.ui.addCategory] = 'onClickAddTermBtn';
                 events["click " + this.ui.addTag] = 'onClickAddTagBtn';
+                events["change " + this.ui.textType] = function(e) {
+                    this.isTextTypeChecked = !this.isTextTypeChecked;
+                    this.renderDetails(this.data);
+                };
                 return events;
             },
             /**
@@ -312,10 +317,18 @@ define(['require',
             },
             renderDetails: function(data) {
                 Utils.hideTitleLoader(this.$('.fontLoader'), this.ui.details);
+                //Below condition is added for sanitizing the longDescription 
text against XSS attack.
+                var longDescriptionContent = (data && data.longDescription) ? 
data.longDescription : "",
+                    sanitizeLongDescriptionContent = "";
+                if (longDescriptionContent !== "") {
+                    sanitizeLongDescriptionContent = 
Utils.sanitizeHtmlContent(longDescriptionContent);
+                }
+                //End
                 if (data) {
+                    var longDescriptionValue = longDescriptionContent ? 
sanitizeLongDescriptionContent : "";
                     this.ui.title.text(data.name || data.displayText || 
data.qualifiedName);
                     this.ui.shortDescription.text(data.shortDescription ? 
data.shortDescription : "");
-                    this.ui.longDescription.text(data.longDescription ? 
data.longDescription : "");
+                    this.isTextTypeChecked ? 
this.ui.longDescription.text(longDescriptionValue) : 
this.ui.longDescription.html(longDescriptionValue);
                     this.generateCategories(data.categories);
                     this.generateTerm(data.terms);
                     this.generateTag(data.classifications);

Reply via email to