From 7fc72831919b277ec41d665c5300d3e28aa89e70 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Thu, 27 Jun 2024 15:14:32 +0300 Subject: [PATCH] copy and paste fields --- app/javascript/template_builder/area.vue | 10 ++++- app/javascript/template_builder/builder.vue | 44 +++++++++++++++++++ .../template_builder/contenteditable.vue | 10 ++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/app/javascript/template_builder/area.vue b/app/javascript/template_builder/area.vue index 143d8986..df12de07 100644 --- a/app/javascript/template_builder/area.vue +++ b/app/javascript/template_builder/area.vue @@ -527,7 +527,15 @@ export default { this.save() }, onPaste (e) { - e.target.innerText = (e.clipboardData || window.clipboardData).getData('text/plain') + const text = (e.clipboardData || window.clipboardData).getData('text/plain') + + const selection = window.getSelection() + + if (selection.rangeCount) { + selection.deleteFromDocument() + selection.getRangeAt(0).insertNode(document.createTextNode(text)) + selection.collapseToEnd() + } }, onResizeCell (e) { if (e.target.id === 'mask') { diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index dcfdb788..feff4160 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -513,6 +513,7 @@ export default { selectedSubmitter: null, showDrawField: false, drawField: null, + copiedArea: null, drawFieldType: null, drawOption: null, dragField: null @@ -747,6 +748,14 @@ export default { event.preventDefault() this.undo() + } else if ((event.ctrlKey || event.metaKey) && event.key === 'c' && document.activeElement === document.body) { + event.preventDefault() + + this.copiedArea = this.selectedAreaRef?.value + } else if ((event.ctrlKey || event.metaKey) && event.key === 'v' && this.copiedArea && document.activeElement === document.body) { + event.preventDefault() + + this.pasteField() } }, removeArea (area) { @@ -760,6 +769,39 @@ export default { this.save() }, + pasteField () { + const field = this.template.fields.find((f) => f.areas?.includes(this.copiedArea)) + const currentArea = this.selectedAreaRef?.value || this.copiedArea + + if (field && currentArea) { + const area = { + ...JSON.parse(JSON.stringify(this.copiedArea)), + attachment_uuid: currentArea.attachment_uuid, + page: currentArea.page, + x: currentArea.x, + y: currentArea.y + currentArea.h * 1.3 + } + + if (['radio', 'multiple'].includes(field.type)) { + this.copiedArea.option_uuid ||= field.options[0].uuid + area.option_uuid = v4() + + field.options.push({ uuid: area.option_uuid }) + + field.areas.push(area) + } else { + this.template.fields.push({ + ...JSON.parse(JSON.stringify(field)), + uuid: v4(), + areas: [area] + }) + } + + this.selectedAreaRef.value = area + + this.save() + } + }, pushUndo () { const stringData = JSON.stringify(this.template) @@ -990,6 +1032,8 @@ export default { } this.save() + + document.activeElement?.blur() }, updateFromUpload (data) { this.template.schema.push(...data.schema) diff --git a/app/javascript/template_builder/contenteditable.vue b/app/javascript/template_builder/contenteditable.vue index 00c2cad8..9b478694 100644 --- a/app/javascript/template_builder/contenteditable.vue +++ b/app/javascript/template_builder/contenteditable.vue @@ -99,7 +99,15 @@ export default { }, methods: { onPaste (e) { - e.target.innerText = (e.clipboardData || window.clipboardData).getData('text/plain') + const text = (e.clipboardData || window.clipboardData).getData('text/plain') + + const selection = window.getSelection() + + if (selection.rangeCount) { + selection.deleteFromDocument() + selection.getRangeAt(0).insertNode(document.createTextNode(text)) + selection.collapseToEnd() + } }, selectContent () { const el = this.$refs.contenteditable