fix: Avoid editor formatting issues when a canned response is edited (#5533)

This commit is contained in:
Nithin David Thomas 2022-10-01 03:33:33 +05:30 committed by GitHub
parent 7b54990ae6
commit 705d06ac3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 57 deletions

View file

@ -28,7 +28,7 @@ import {
suggestionsPlugin,
triggerCharacters,
} from '@chatwoot/prosemirror-schema/src/mentions/plugin';
import { EditorState } from 'prosemirror-state';
import { EditorState, Selection } from 'prosemirror-state';
import { defaultMarkdownParser } from 'prosemirror-markdown';
import { wootWriterSetup } from '@chatwoot/prosemirror-schema';
@ -61,23 +61,28 @@ export default {
mixins: [eventListenerMixins],
props: {
value: { type: String, default: '' },
editorId: { type: String, default: '' },
placeholder: { type: String, default: '' },
isPrivate: { type: Boolean, default: false },
isFormatMode: { type: Boolean, default: false },
enableSuggestions: { type: Boolean, default: true },
},
data() {
return {
lastValue: null,
showUserMentions: false,
showCannedMenu: false,
mentionSearchKey: '',
cannedSearchTerm: '',
editorView: null,
range: null,
state: undefined,
};
},
computed: {
contentFromEditor() {
return addMentionsToMarkdownSerializer(
defaultMarkdownSerializer
).serialize(this.editorView.state.doc);
},
plugins() {
if (!this.enableSuggestions) {
return [];
@ -102,7 +107,6 @@ export default {
onExit: () => {
this.mentionSearchKey = '';
this.showUserMentions = false;
this.editorView = null;
return false;
},
onKeyDown: ({ event }) => {
@ -131,7 +135,6 @@ export default {
onExit: () => {
this.cannedSearchTerm = '';
this.showCannedMenu = false;
this.editorView = null;
return false;
},
onKeyDown: ({ event }) => {
@ -149,28 +152,33 @@ export default {
this.$emit('toggle-canned-menu', !this.isPrivate && updatedValue);
},
value(newValue = '') {
if (newValue !== this.lastValue) {
const { tr } = this.state;
if (this.isFormatMode) {
this.state = createState(
newValue,
this.placeholder,
this.plugins,
this.isFormatMode
);
} else {
tr.insertText(newValue, 0, tr.doc.content.size);
this.state = this.view.state.apply(tr);
}
this.view.updateState(this.state);
if (newValue !== this.contentFromEditor) {
this.reloadState();
}
},
editorId() {
this.reloadState();
},
isPrivate() {
this.reloadState();
},
},
created() {
this.state = createState(this.value, this.placeholder, this.plugins);
},
mounted() {
this.view = new EditorView(this.$refs.editor, {
this.createEditorView();
this.editorView.updateState(this.state);
this.focusEditorInputField();
},
methods: {
reloadState() {
this.state = createState(this.value, this.placeholder, this.plugins);
this.editorView.updateState(this.state);
this.focusEditorInputField();
},
createEditorView() {
this.editorView = new EditorView(this.$refs.editor, {
state: this.state,
dispatchTransaction: tx => {
this.state = this.state.apply(tx);
@ -194,9 +202,7 @@ export default {
},
},
});
this.focusEditorInputField();
},
methods: {
handleKeyEvents(e) {
if (hasPressedAltAndPKey(e)) {
this.focusEditorInputField();
@ -206,47 +212,59 @@ export default {
}
},
focusEditorInputField() {
this.$refs.editor.querySelector('div.ProseMirror-woot-style').focus();
const { tr } = this.editorView.state;
const selection = Selection.atEnd(tr.doc);
this.editorView.dispatch(tr.setSelection(selection));
this.editorView.focus();
},
insertMentionNode(mentionItem) {
if (!this.view) {
if (!this.editorView) {
return null;
}
const node = this.view.state.schema.nodes.mention.create({
const node = this.editorView.state.schema.nodes.mention.create({
userId: mentionItem.key,
userFullName: mentionItem.label,
});
const tr = this.view.state.tr.replaceWith(
const tr = this.editorView.state.tr.replaceWith(
this.range.from,
this.range.to,
node
);
this.state = this.view.state.apply(tr);
this.state = this.editorView.state.apply(tr);
return this.emitOnChange();
},
insertCannedResponse(cannedItem) {
if (!this.view) {
if (!this.editorView) {
return null;
}
const tr = this.view.state.tr.insertText(
const tr = this.editorView.state.tr.insertText(
cannedItem,
this.range.from,
this.range.to
);
this.state = this.view.state.apply(tr);
return this.emitOnChange();
this.state = this.editorView.state.apply(tr);
this.emitOnChange();
// Hacky fix for #5501
this.state = createState(
this.contentFromEditor,
this.placeholder,
this.plugins
);
this.editorView.updateState(this.state);
return false;
},
emitOnChange() {
this.view.updateState(this.state);
this.lastValue = addMentionsToMarkdownSerializer(
defaultMarkdownSerializer
).serialize(this.state.doc);
this.$emit('input', this.lastValue);
this.editorView.updateState(this.state);
this.$emit('input', this.contentFromEditor);
},
hideMentions() {
this.showUserMentions = false;
},

View file

@ -56,6 +56,7 @@
<woot-message-editor
v-else
v-model="message"
:editor-id="editorStateId"
class="input"
:is-private="isOnPrivateNote"
:placeholder="messagePlaceHolder"
@ -429,6 +430,13 @@ export default {
profilePath() {
return frontendURL(`accounts/${this.accountId}/profile/settings`);
},
conversationId() {
return this.currentChat.id;
},
editorStateId() {
const key = `draft-${this.conversationIdByRoute}-${this.replyType}`;
return key;
},
},
watch: {
currentChat(conversation) {

View file

@ -1,6 +1,7 @@
export const LOCAL_STORAGE_KEYS = {
DISMISSED_UPDATES: 'dismissedUpdates',
WIDGET_BUILDER: 'widgetBubble_',
DRAFT_MESSAGES: 'draftMessages',
};
export const LocalStorage = {

View file

@ -46,6 +46,7 @@ export default {
return {
articleTitle: '',
articleContent: '',
saveArticle: () => {},
};
},
mounted() {