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 c0f318f ATLAS-4471 : UI: Add text editor for long description fields
c0f318f is described below
commit c0f318f18ff621a4fe88fd49f3d2fad8468d2de4
Author: Farhan Khan <[email protected]>
AuthorDate: Fri Jan 7 18:20:08 2022 +0530
ATLAS-4471 : UI: Add text editor for long description fields
Signed-off-by: Pinal Shah <[email protected]>
---
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: </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: </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: </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);