Skip to main content

aa

<template>
<v-dialogv-model="dialog"transition="dialog-bottom-transition"fullscreen>
<v-card>
<DrowEditor :close="close" :recevData="recevData" :imageUrl="imageUrl" />
</v-card>
</v-dialog>
<divclass="control-section mg_auto">
<divclass="sample-container">
<divclass="default-section">
<!-- <v-btn @click="onClickDrow">Drow</v-btn> -->

<form
          :id="'myForm' + uniqueId"
class="form-vertical richtexteditor_box"
>
<ejs-richtexteditor
            :toolbarClick="toolbarClick"
            :id="'book_mention_integration_' + uniqueId"
ref="rteObj"
name="defaultRTE"
            :quickToolbarSettings="quickToolbarSettings"
height="1124"
            :insertImageSettings="insertImageSettings"
            :toolbarSettings="toolbarSettings"
v-model="objModel.html"
            :change="createdTextEditor"
            :allowEditing="false"
            :readonly="readonly"
            :enabled="!readonly"
            :enableTabKey="true"
            @blur="onBlur"
            @created="focusEditor"
            :created="onCreate"
            :imageUploadSuccess="imageUploadSuccess"
            :afterImageDelete="afterImageDelete"
enterKey="DIV"
saveInterval="9000"
            :pasteCleanupSettings="pasteCleanupSettings"
>
</ejs-richtexteditor>
<divclass="error-element"></div>
</form>
</div>
</div>
</div>
</template>
<script>
import {
RichTextEditorComponent,
Toolbar,
Link,
Image,
HtmlEditor,
QuickToolbar,
EmojiPicker,
PasteCleanup,
Table,
Video,
Audio,
NodeSelection,
} from"@syncfusion/ej2-vue-richtexteditor";
import { getImageURL } from"@/api/todo";
import { FormValidator } from"@syncfusion/ej2-inputs";
import { DropDownButton } from"@syncfusion/ej2-vue-splitbuttons";
importDrowEditorfrom"./DrowEditor.vue";
import { PAGE_UPLOAD_ATTACHMENT } from"@/store/actions/confluence";
consthostUrl = import.meta.env.VITE_USER_ROOT_API;
exportdefault {
name:"BookRichTextEditor",
components: {
"ejs-richtexteditor":RichTextEditorComponent,
DrowEditor,
  },
props: {
propName: {
type:String,
required:true,
    },
objModel: {
type:Object,
required:true,
    },
isRequired: {
type:Boolean,
required:false,
default:true,
    },
users: {
type:Array,
required:false,
    },
isMention: {
type:Boolean,
required:false,
Default:false,
    },
readonly: {
type:Boolean,
required:false,
default:false,
    },
  },
// emits: ["update:modelValue"],
provide: {
richtexteditor: [
Toolbar,
Link,
Image,
QuickToolbar,
HtmlEditor,
PasteCleanup,
Table,
Video,
Audio,
EmojiPicker,
    ],
  },
// provide: {
//   richtexteditor: [
//     Toolbar,
//     Link,
//     Image,
//     Count,
//     HtmlEditor,
//     QuickToolbar,
//     EmojiPicker,
//   ],
// },
data() {
return {
pasteCleanupSettings: {
plainText:true,
      },
imageUrl:"",
dialog:false,
proxy:this,
customBtn:null,
insertImageSettings: {
saveFormat:"blob",
saveUrl:
hostUrl +
"/api/v1/task/editor-attachment/" +
this.$store.getters.getSelectedCompanyId,
removeUrl:hostUrl + "/api/v1/task/delete-editor-attachment",
path:hostUrl + "/api/v1/download/",
      },
selection:newNodeSelection(),
ranges:null,
uniqueId:Math.random().toString(36).substr(2, 9),
value:"",
getImageURL:getImageURL,
dropButton:DropDownButton,
selectedUserIndex: -1,
quickToolbarSettings: {
image: [
"Replace",
"Align",
"Caption",
"Remove",
"InsertLink",
"OpenImageLink",
"-",
"EditImageLink",
"RemoveImageLink",
"Display",
"AltText",
"Dimension",
          {
tooltipText:"Edit Image",
template:
'<button class="e-tbar-btn e-btn" id="imageEditor"><span class="e-btn-icon e-icons e-rte-image-editor"></span></button>',
          },
        ],
link: ["Open", "Edit", "UnLink"],
text: [
"Bold",
"Italic",
"Underline",
"FontColor",
"BackgroundColor",
"Alignments",
"-",
"FontSize",
"FontName",
"Formats",
"OrderedList",
"UnorderedList",
"FormatPainter",
        ],
      },
items1: [
        {
text:"Information",
        },
        {
text:"Warning",
        },
        {
text:"Success",
        },
        {
text:"Danger",
        },
      ],
toolbarSettings: {
enableFloating:false,
items: [
"Bold",
"Italic",
"Underline",
"StrikeThrough",
"FontName",
"FontSize",
"FontColor",
"BackgroundColor",
"LowerCase",
"UpperCase",
"|",
"Formats",
"Alignments",
"Blockquote",
"OrderedList",
"UnorderedList",
"Outdent",
"Indent",
"|",
"CreateLink",
"Image",
"CreateTable",
"|",
"EmojiPicker",
"|",
"ClearFormat",
"Print",
"SourceCode",
"|",
"Undo",
"Redo",
          {
tooltipText:"Insert Symbol",
template:
'<button class="e-tbar-btn e-btn" tabindex="-1" id="drop"  style="width:100%">Callouts</button>',
          },
          {
tooltipText:"Insert Diagram",
template:
'<button class="e-tbar-btn e-btn" tabindex="-1" id="custom_tbar"  style="width:100%"><div class="e-tbar-btn-text" style="font-weight: 400;">Add Diagram</div></button>',
          },
        ],
      },
    };
  },
computed: {},
watch: {},
created() {},
mounted() {
// this.focusEditor();
  },
beforeUnmount() {
//
  },
methods: {
onCreate() {
this.proxy = this;
// initialize DropDownList component
this.dropButton = newDropDownButton({
items:this.items1,
content:"CallOuts",
select:this.select,
      });
// render initialized DropDownList
this.dropButton.appendTo("#drop");
this.customBtn = document.getElementById("custom_tbar");
constpage = this;
this.customBtn.onclick = function (event) {
event.preventDefault();
page.onClickDrow();
      };
    },
select:function (args) {
varrte = this.$refs.rteObj.ej2Instances;
consttext = rte.getSelection() ? rte.getSelection() : "Enter text";
if (args.item.text == "Information") {
rte.executeCommand("insertHTML", `<p class='callout info'>${text}</p>`);
      } elseif (args.item.text == "Warning") {
rte.executeCommand(
"insertHTML",
`<p class='callout warning'>${text}</p>`
        );
      } elseif (args.item.text == "Success") {
rte.executeCommand(
"insertHTML",
`<p class='callout success'>${text}</p>`
        );
      } else {
rte.executeCommand(
"insertHTML",
`<p class='callout danger'>${text}</p>`
        );
      }
    },
// focusEditor() {
//   this.$nextTick(() => {
//     const rteInstance = this.$refs.rteObj.ej2Instances;
//     rteInstance.focusIn();
//     const editorElement = rteInstance.contentModule.getEditPanel();
//     const editorText = editorElement.textContent || editorElement.innerText;
//     if (editorText.trim().length > 0) {
//       // If there's text, move cursor to the end
//       const range = document.createRange();
//       const sel = window.getSelection();
//       range.selectNodeContents(editorElement);
//       range.collapse(false);
//       sel.removeAllRanges();
//       sel.addRange(range);
//     } else {
//       // If no text, move cursor to the start
//       const range = document.createRange();
//       const sel = window.getSelection();
//       range.selectNodeContents(editorElement);
//       range.collapse(true);
//       sel.removeAllRanges();
//       sel.addRange(range);
//     }
//   });
// },
onBlur() {
//   this.$emit("blurFunction");
    },
createdTextEditor() {
if (this.isRequired) {
varoption = {
rules: {
defaultRTE: {
required:true,
minLength: [3, "The field is required"],
            },
          },
customPlacement: (element, errorElement) => {
document.querySelector(".error-element").appendChild(errorElement);
          },
        };
newFormValidator("#myForm" + this.uniqueId, option);
      }
    },
onChange(e) {
// console.log("on Chawngeweeew11v -", e);
// console.log("onChan ge1-", this.$refs.rteObj.ej2Instances);
    },
imageUploadSuccess(args) {
args.file.name = args.e.srcElement.response;
    },
afterImageDelete(args) {
constbaseUrl = hostUrl + "/api/v1/download/";
constfilePath = args.src.replace(baseUrl, "").trim();
this.objModel.imagePath.push(filePath);
// this.$store
//   .dispatch(TASK_DELETE_ATTACHMENT, {
//     isText: false,
//     url: encodeURIComponent(filePath),
//   })
//   .then(() => {
//     // page.loading = false;
//     // if (page.$store.getters.getTaskStatus !== "success") return;
//     // page.refresh();
//   });
    },
onClickDrow() {
this.dialog = true;
    },
close() {
this.dialog = false;
    },
asyncrecevData(imgurl, isEdit = false) {
// console.log("Sssssssssssssssssss", imgurl);
constfile = awaitthis.base64ToFile(imgurl, "drow.png");
consturl = awaitthis.handleFilesUpload(file);
constserverImg = hostUrl + "/api/v1/download/" + (awaiturl);
if (isEdit) {
this.$refs.rteObj.ej2Instances.executeCommand("insertImage", {
url:serverImg,
cssClass:"e-rte-image e-imgleft drawio",
        });
setTimeout(() => {
constinsertedImage = document.querySelector(
".e-rte-image.e-imgleft.drawio"
          ); // Select the newly inserted image based on class
if (insertedImage) {
insertedImage.id = "drawio " + newDate().getTime(); // Set the desired ID
// console.log("Image updated with ID:", insertedImage);
          } else {
console.error("Image not found");
          }
        }, 0);
      } else {
this.$refs.rteObj.ej2Instances.executeCommand("insertImage", {
url:serverImg,
cssClass:"e-rte-image e-imgleft drawio",
selection:this.saveSelection,
        });
      }
this.$refs.rteObj.ej2Instances.formatter.saveData();
this.$refs.rteObj.ej2Instances.formatter.enableUndo(
this.$refs.rteObj.ej2Instances
      );
this.$refs.rteObj.ej2Instances.focusIn();
// rteInstance.focusIn();
    },
asynchandleFilesUpload(e) {
letpage = this;
letattachmentFiles = e;
returnawaitpage.$store
        .dispatch(PAGE_UPLOAD_ATTACHMENT, {
id:this.$store.getters.getSelectedCompanyId,
attachmentFiles:attachmentFiles,
        })
        .then(async (response) => {
returnawaitresponse;
// page.loading = false;
// page.refresh();
// if (page.$store.getters.getTaskStatus !== "success") return;
// if (e.target.files) {
//   page.$refs.files.value = "";
// }
        });
    },
// Function to decode Base64 string and convert it to a File object
asyncbase64ToFile(base64String, fileName) {
consttimestamp = newDate().toISOString().replace(/[:.-]/g, "");
constnewFileName = `${fileName.replace(
/\.[^/.]+$/,
""
      )}_${timestamp}.${fileName.split(".").pop()}`;
// Separate the metadata from the Base64 data
const [metadata, data] = base64String.split(",");
// Extract MIME type from metadata
constmimeType = metadata.match(/:(.*?);/)[1];
// Decode Base64 data into a binary string
constbinaryData = awaitatob(data);
// Convert binary string to a Uint8Array (array of bytes)
constbyteNumbers = Uint8Array.from(binaryData, (char) =>
char.charCodeAt(0)
      );
// Create and return a File object
returnnewFile([byteNumbers], newFileName, { type:mimeType });
    },
toolbarClick(args) {
if (args.item.tooltipText === "Edit Image") {
this.range = this.selection.getRange(document);
this.saveSelection = this.selection.save(this.range, document);
// this.$refs.dialogObj.show();
// this.$refs.defaultRTE.ej2Instances.quickToolbarModule.imageQTBar.hidePopup();
varselectNodes =
this.$refs.rteObj.ej2Instances.formatter.editorManager.nodeSelection.getNodeCollection(
this.range
          );
if (!selectNodes[0].classList.value.includes("drawio")) {
alert("you can't edit this image ");
return;
        }
// console.log(selectNodes[0].src);
// this.imageUrl = selectNodes[0].src;
this.imageUrl = selectNodes[0].src;
this.$refs.rteObj.ej2Instances.quickToolbarModule.imageQTBar.hidePopup();
this.onClickDrow();
// document.getElementById("image").value = selectNodes[0].src;
// this.imageELement = selectNodes[0];
      }
    },
  },
};
</script>
<style>
@import"../../../node_modules/@syncfusion/ej2-base/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-inputs/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-lists/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-popups/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-buttons/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-navigations/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css";
@import"../../../node_modules/@syncfusion/ej2-vue-richtexteditor/styles/material.css";
.e-dropdownbase.e-list-item.e-active,
.e-dropdownbase.e-list-item.e-active.e-hover {
background-color: #0d6efd;
border-color: #fff;
color: #fff;
}
.e-dropdownbase.e-content {
overflow: auto;
position: relative;
}
.e-dropdownbase {
border-color: #dee2e6;
}
.e-list-item.e-hover {
background-color: #dee2e6;
}
.e-mention.e-popup {
background: #fff;
border: 0;
box-shadow: 02px3px1pxrgba(0, 0, 0, 0.21);
margin-top: 2px;
position: absolute;
z-index: 9999!important;
}
.error-element {
margin-top: 5px;
}
.v-theme--dark.sample-container.form-vertical.e-richtexteditor,
.v-theme--dark
.sample-container
.form-vertical
.e-richtexteditor
.e-toolbar-wrapper,
.v-theme--dark.e-toolbar.e-toolbar-items,
.v-theme--dark.e-toolbar.e-toolbar-item.e-tbar-btn,
.v-theme--dark.e-richtexteditor.e-rte-toolbar.e-toolbar-item.e-icons,
.v-theme--dark.e-toolbar,
.v-theme--dark.e-toolbar.e-hor-nav,
.v-theme--dark.e-richtexteditor.e-rte-content,
.v-theme--dark.e-richtexteditor.e-source-content,
.v-theme--dark.e-toolbar.e-extended-toolbar.e-toolbar-pop,
.v-theme--dark
.e-toolbar.e-extended-toolbar
.e-toolbar-extended
.e-toolbar-item.e-overlay,
.v-theme--dark
.e-toolbar.e-extended-toolbar
.e-toolbar-extended
.e-toolbar-item
.e-tbar-btn {
background: rgb(var(--v-theme-surface));
color: #ffff!important;
}
.v-theme--dark.e-toolbar.e-popup-down-icon.e-icons,
.v-theme--dark.e-toolbar.e-popup-up-icon.e-icons {
color: #ffff!important;
}
.v-theme--dark.e-richtexteditor.e-rte-tb-expand {
border: 1pxsolidwhite!important;
}
.v-theme--dark.e-richtexteditor.e-rte-tb-expand.e-rte-content,
.v-theme--dark.e-richtexteditor.e-rte-tb-expand.e-source-content {
border-bottom: 1pxsolid#ffff;
border-top: 1pxsolid#ffff;
}
/* test */
.e-rte-contentul,
.e-rte-contentol {
margin-left: 20px!important;
}
.e-rte-quick-popup.e-rte-quick-toolbar.e-rte-image-editor::before {
content: "\e81e";
}
.e-richtexteditor {
padding-bottom: 30px!important;
}
.e-rte-container {
border: 0px!important;
}
.richtexteditor_box.richtexteditor_box {
border: 1px#dddsolid!important;
background-color: #fff!important;
}
/* :root {
  --rte-visual-lines: 5;
  --rte-line-height: 1.2em;
}
.richtexteditor_box .e-richtexteditor .e-rte-content::after,
.richtexteditor_box .e-richtexteditor .e-content::after,
.richtexteditor_box .e-richtexteditor .e-editable::after,
.richtexteditor_box .e-richtexteditor .e-source-content::after,
.e-richtexteditor .e-rte-content::after {
  content: "";
  display: block;
  height: calc(var(--rte-line-height) * var(--rte-visual-lines));
  pointer-events: none;
  user-select: none;
} */
.e-richtexteditor.e-content::after {
/* content: ""; */
display: block;
height: calc(1.2em * 5);
pointer-events: none;
user-select: none;
}
/* keep list indent behaviour */
</style>