ATLAS-4471 : UI: Add text editor for long description fields

Signed-off-by: Pinal Shah <pinal.shah@freestoneinfotech.com>
This commit is contained in:
Farhan Khan 2022-01-07 18:20:08 +05:30 committed by Pinal Shah
parent fdb3ab85b6
commit c0f318f18f
26 changed files with 2199 additions and 28 deletions

View File

@ -341,7 +341,8 @@ pre {
}
.long-description {
width: 85%;
width: 100%;
overflow-wrap: break-word;
cursor: default !important;
background-color: transparent !important;
}

View File

@ -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;
}

View File

@ -36,4 +36,6 @@
@import "wizard.scss";
@import "business-metadata.scss";
@import "stats.scss";
@import "override.scss";
@import "override.scss";
@import "trumbowyg.scss";
@import "texteditor.scss";

View File

@ -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;
}

View File

@ -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);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -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'
},
/**

View File

@ -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}}

View File

@ -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() {

View File

@ -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;
});
});

View File

@ -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);

View File

@ -340,7 +340,8 @@ pre {
}
.long-description {
width: 85%;
width: 100%;
overflow-wrap: break-word;
cursor: default !important;
background-color: transparent !important;
}

View File

@ -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;
}

View File

@ -37,4 +37,6 @@
@import "business-metadata.scss";
@import "stats.scss";
@import "override.scss";
@import "leftsidebar.scss";
@import "leftsidebar.scss";
@import "trumbowyg.scss";
@import "texteditor.scss";

View File

@ -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;
}

View File

@ -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);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -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'
},
/**

View File

@ -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}}

View File

@ -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() {

View File

@ -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;
});
});

View File

@ -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);