From 779db0104be864dc0a3f18b8faf4dba485a68354 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:15:01 +0530 Subject: [PATCH] Nc Feat: Allow inline edit rich text field in form view (#7974) * feat(nc-gui): allow inline edit rich text field in form view setup * fix(nc-gui): rich text link options width issue * fix(nc-gui): form view title, description on focus bg color issue * fix(nc-gui): form view rich text field shift tab focus out issue * fix(nc-gui): set max height of rich text field in form view to 240px * fix(nc-gui): rich text full mode options visibility issue * chore(nc-gui): lint --- packages/nc-gui/components/cell/RichText.vue | 47 ++++++++++++++----- .../components/cell/RichText/LinkOptions.vue | 22 +++++++-- packages/nc-gui/components/cell/TextArea.vue | 10 +++- .../nc-gui/components/smartsheet/Form.vue | 18 ++++--- .../index/[typeOrId]/form/[viewId]/index.vue | 18 +++++-- 5 files changed, 83 insertions(+), 32 deletions(-) diff --git a/packages/nc-gui/components/cell/RichText.vue b/packages/nc-gui/components/cell/RichText.vue index 4bc2c87660..f3a4aabaec 100644 --- a/packages/nc-gui/components/cell/RichText.vue +++ b/packages/nc-gui/components/cell/RichText.vue @@ -10,7 +10,7 @@ import Placeholder from '@tiptap/extension-placeholder' import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item' import { Link } from '@/helpers/dbTiptapExtensions/links' import type { RichTextBubbleMenuOptions } from '#imports' -import { IsExpandedFormOpenInj, IsFormInj, IsGridInj, ReadonlyInj, RowHeightInj } from '#imports' +import { IsExpandedFormOpenInj, IsFormInj, IsGridInj, IsSurveyFormInj, ReadonlyInj, RowHeightInj } from '#imports' const props = withDefaults( defineProps<{ @@ -26,13 +26,14 @@ const props = withDefaults( hiddenBubbleMenuOptions?: RichTextBubbleMenuOptions[] }>(), { + isFormField: false, hiddenBubbleMenuOptions: () => [], }, ) -const emits = defineEmits(['update:value']) +const emits = defineEmits(['update:value', 'focus', 'blur']) -const { hiddenBubbleMenuOptions } = toRefs(props) +const { isFormField, hiddenBubbleMenuOptions } = toRefs(props) const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! @@ -44,8 +45,12 @@ const isForm = inject(IsFormInj, ref(false)) const isGrid = inject(IsGridInj, ref(false)) +const isSurveyForm = inject(IsSurveyFormInj, ref(false)) + const isFocused = ref(false) +const keys = useMagicKeys() + const turndownService = new TurndownService({}) turndownService.addRule('lineBreak', { @@ -124,7 +129,7 @@ const vModel = useVModel(props, 'value', emits, { defaultValue: '' }) const tiptapExtensions = [ StarterKit.configure({ - heading: props.isFormField ? false : undefined, + heading: isFormField.value ? false : undefined, }), TaskList, TaskItem.configure({ @@ -145,16 +150,18 @@ const editor = useEditor({ .turndown(editor.getHTML().replaceAll(/
<\/p>/g, '
'))
.replaceAll(/\n\n
\n\n/g, '
\n\n')
- vModel.value = props.isFormField && markdown === '
' ? '' : markdown
+ vModel.value = isFormField.value && markdown === '
' ? '' : markdown
},
editable: !props.readOnly,
autofocus: props.autofocus,
onFocus: () => {
isFocused.value = true
+ emits('focus')
},
onBlur: (e) => {
if (!(e?.event?.relatedTarget as HTMLElement)?.closest('.bubble-menu, .nc-textarea-rich-editor')) {
isFocused.value = false
+ emits('blur')
}
},
})
@@ -185,13 +192,19 @@ const setEditorContent = (contentMd: any, focusEndOfDoc?: boolean) => {
}, 100)
}
+const onFocusWrapper = () => {
+ if (isForm.value && !isFormField.value && !props.readOnly && !keys.shift.value) {
+ editor.value?.chain().focus().run()
+ }
+}
+
if (props.syncValueChange) {
watch([vModel, editor], () => {
setEditorContent(vModel.value)
})
}
-if (props.isFormField) {
+if (isFormField.value) {
watch([props, editor], () => {
if (props.readOnly) {
editor.value?.setEditable(false)
@@ -206,7 +219,7 @@ watch(editorDom, () => {
setEditorContent(vModel.value, true)
- if (props.isFormField) return
+ if ((isForm.value && !isSurveyForm.value) || isFormField.value) return
// Focus editor after editor is mounted
setTimeout(() => {
editor.value?.chain().focus().run()
@@ -220,6 +233,7 @@ useEventListener(
const targetEl = e?.relatedTarget as HTMLElement
if (targetEl?.classList?.contains('tiptap') || !targetEl?.closest('.bubble-menu, .nc-textarea-rich-editor')) {
isFocused.value = false
+ emits('blur')
}
},
true,
@@ -228,7 +242,7 @@ useEventListener(