Enhance Process Flow Components with Recursive Update Prevention
- Updated HtmlNodeConfiguration.vue and ScriptNodeConfiguration.vue to prevent recursive updates when props change by introducing a flag and utilizing nextTick for state management. - Improved keyboard shortcut handling in index.vue to block shortcuts when modals are open or when input elements are focused, enhancing user experience during process building.
This commit is contained in:
parent
597a443453
commit
312e555361
@ -362,7 +362,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onMounted } from 'vue'
|
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||||
|
|
||||||
// Props and emits
|
// Props and emits
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -489,6 +489,9 @@ const getMockValueForType = (type) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a flag to prevent recursive updates
|
||||||
|
const isUpdatingFromProps = ref(false)
|
||||||
|
|
||||||
const emitUpdate = () => {
|
const emitUpdate = () => {
|
||||||
emit('update', localNodeData.value)
|
emit('update', localNodeData.value)
|
||||||
}
|
}
|
||||||
@ -498,6 +501,7 @@ watch(
|
|||||||
() => props.nodeData,
|
() => props.nodeData,
|
||||||
(newData) => {
|
(newData) => {
|
||||||
if (newData && Object.keys(newData).length > 0) {
|
if (newData && Object.keys(newData).length > 0) {
|
||||||
|
isUpdatingFromProps.value = true
|
||||||
localNodeData.value = {
|
localNodeData.value = {
|
||||||
label: newData.label || 'HTML Node',
|
label: newData.label || 'HTML Node',
|
||||||
description: newData.description || '',
|
description: newData.description || '',
|
||||||
@ -509,6 +513,10 @@ watch(
|
|||||||
allowVariableAccess: newData.allowVariableAccess !== undefined ? newData.allowVariableAccess : true,
|
allowVariableAccess: newData.allowVariableAccess !== undefined ? newData.allowVariableAccess : true,
|
||||||
autoRefresh: newData.autoRefresh || false
|
autoRefresh: newData.autoRefresh || false
|
||||||
}
|
}
|
||||||
|
// Reset the flag after the update
|
||||||
|
nextTick(() => {
|
||||||
|
isUpdatingFromProps.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true }
|
{ immediate: true, deep: true }
|
||||||
@ -518,7 +526,10 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
localNodeData,
|
localNodeData,
|
||||||
() => {
|
() => {
|
||||||
emitUpdate()
|
// Only emit if we're not currently updating from props
|
||||||
|
if (!isUpdatingFromProps.value) {
|
||||||
|
emitUpdate()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
@ -232,7 +232,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch, nextTick } from 'vue'
|
||||||
|
|
||||||
// Props and emits
|
// Props and emits
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -348,11 +348,15 @@ const emitUpdate = () => {
|
|||||||
emit('update', localNodeData.value)
|
emit('update', localNodeData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a flag to prevent recursive updates
|
||||||
|
const isUpdatingFromProps = ref(false)
|
||||||
|
|
||||||
// Watch for prop changes
|
// Watch for prop changes
|
||||||
watch(
|
watch(
|
||||||
() => props.nodeData,
|
() => props.nodeData,
|
||||||
(newData) => {
|
(newData) => {
|
||||||
if (newData && Object.keys(newData).length > 0) {
|
if (newData && Object.keys(newData).length > 0) {
|
||||||
|
isUpdatingFromProps.value = true
|
||||||
localNodeData.value = {
|
localNodeData.value = {
|
||||||
label: newData.label || 'Script Task',
|
label: newData.label || 'Script Task',
|
||||||
description: newData.description || '',
|
description: newData.description || '',
|
||||||
@ -363,6 +367,10 @@ watch(
|
|||||||
continueOnError: newData.continueOnError || false,
|
continueOnError: newData.continueOnError || false,
|
||||||
errorVariable: newData.errorVariable || 'scriptError'
|
errorVariable: newData.errorVariable || 'scriptError'
|
||||||
}
|
}
|
||||||
|
// Reset the flag after the update
|
||||||
|
nextTick(() => {
|
||||||
|
isUpdatingFromProps.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true }
|
{ immediate: true, deep: true }
|
||||||
@ -372,7 +380,10 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
localNodeData,
|
localNodeData,
|
||||||
() => {
|
() => {
|
||||||
emitUpdate()
|
// Only emit if we're not currently updating from props
|
||||||
|
if (!isUpdatingFromProps.value) {
|
||||||
|
emitUpdate()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
@ -553,9 +553,66 @@ const pasteElements = async () => {
|
|||||||
|
|
||||||
// Keyboard shortcuts for panel toggles and copy/paste
|
// Keyboard shortcuts for panel toggles and copy/paste
|
||||||
const handleKeyboardShortcuts = (event) => {
|
const handleKeyboardShortcuts = (event) => {
|
||||||
// Only handle shortcuts when no input is focused
|
// Check if any modal is open - if so, don't handle process builder shortcuts
|
||||||
if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
|
const isModalOpen = showFormConfigModal.value ||
|
||||||
return;
|
showApiConfigModal.value ||
|
||||||
|
showGatewayConfigModal.value ||
|
||||||
|
showBusinessRuleConfigModal.value ||
|
||||||
|
showNotificationConfigModal.value ||
|
||||||
|
showScriptConfigModal.value ||
|
||||||
|
showHtmlConfigModal.value ||
|
||||||
|
showSubprocessConfigModal.value ||
|
||||||
|
showTemplatesModal.value ||
|
||||||
|
showProcessSettings.value ||
|
||||||
|
showProcessHistoryModal.value ||
|
||||||
|
showExportModal.value ||
|
||||||
|
showUnsavedChangesModal.value;
|
||||||
|
|
||||||
|
if (isModalOpen) {
|
||||||
|
// Debug logging (can be removed in production)
|
||||||
|
if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
|
||||||
|
console.log('🔒 Process builder shortcuts blocked - modal is open');
|
||||||
|
}
|
||||||
|
return; // Let the modal handle its own keyboard shortcuts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target is an input element or code editor
|
||||||
|
const target = event.target;
|
||||||
|
const isInputElement = target.tagName === 'INPUT' ||
|
||||||
|
target.tagName === 'TEXTAREA' ||
|
||||||
|
target.tagName === 'SELECT' ||
|
||||||
|
target.contentEditable === 'true' ||
|
||||||
|
target.closest('.CodeMirror') !== null ||
|
||||||
|
target.closest('.cm-editor') !== null ||
|
||||||
|
target.closest('.cm-content') !== null ||
|
||||||
|
target.closest('.cm-cursor') !== null ||
|
||||||
|
target.closest('.cm-line') !== null ||
|
||||||
|
target.closest('.formkit-input') !== null ||
|
||||||
|
target.closest('.formkit-textarea') !== null ||
|
||||||
|
target.closest('[contenteditable="true"]') !== null ||
|
||||||
|
target.closest('.rs-code-mirror') !== null ||
|
||||||
|
target.closest('[data-cm-editor]') !== null;
|
||||||
|
|
||||||
|
if (isInputElement) {
|
||||||
|
// Debug logging (can be removed in production)
|
||||||
|
if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
|
||||||
|
console.log('🔒 Process builder shortcuts blocked - input element detected:', target.tagName, target.className);
|
||||||
|
}
|
||||||
|
return; // Let the input element handle its own keyboard shortcuts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional check: if the target is inside any modal, don't handle process builder shortcuts
|
||||||
|
const isInsideModal = target.closest('.rs-modal') !== null ||
|
||||||
|
target.closest('.modal') !== null ||
|
||||||
|
target.closest('[role="dialog"]') !== null ||
|
||||||
|
target.closest('.vue-flow__modal') !== null;
|
||||||
|
|
||||||
|
if (isInsideModal) {
|
||||||
|
// Debug logging (can be removed in production)
|
||||||
|
if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
|
||||||
|
console.log('🔒 Process builder shortcuts blocked - inside modal');
|
||||||
|
}
|
||||||
|
return; // Let the modal handle its own keyboard shortcuts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl/Cmd + 1: Toggle left panel
|
// Ctrl/Cmd + 1: Toggle left panel
|
||||||
@ -579,12 +636,20 @@ const handleKeyboardShortcuts = (event) => {
|
|||||||
// Ctrl/Cmd + C: Copy selected elements
|
// Ctrl/Cmd + C: Copy selected elements
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
|
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
// Debug logging (can be removed in production)
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('📋 Process builder copy shortcut triggered');
|
||||||
|
}
|
||||||
copySelectedElements();
|
copySelectedElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl/Cmd + V: Paste elements
|
// Ctrl/Cmd + V: Paste elements
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
|
if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
// Debug logging (can be removed in production)
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('📋 Process builder paste shortcut triggered');
|
||||||
|
}
|
||||||
pasteElements();
|
pasteElements();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user