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:
Md Afiq Iskandar 2025-07-28 09:49:53 +08:00
parent 597a443453
commit 312e555361
3 changed files with 94 additions and 7 deletions

View File

@ -362,7 +362,7 @@ document.addEventListener('DOMContentLoaded', function() {
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { ref, computed, watch, onMounted, nextTick } from 'vue'
// Props and emits
const props = defineProps({
@ -489,6 +489,9 @@ const getMockValueForType = (type) => {
}
}
// Add a flag to prevent recursive updates
const isUpdatingFromProps = ref(false)
const emitUpdate = () => {
emit('update', localNodeData.value)
}
@ -498,6 +501,7 @@ watch(
() => props.nodeData,
(newData) => {
if (newData && Object.keys(newData).length > 0) {
isUpdatingFromProps.value = true
localNodeData.value = {
label: newData.label || 'HTML Node',
description: newData.description || '',
@ -509,6 +513,10 @@ watch(
allowVariableAccess: newData.allowVariableAccess !== undefined ? newData.allowVariableAccess : true,
autoRefresh: newData.autoRefresh || false
}
// Reset the flag after the update
nextTick(() => {
isUpdatingFromProps.value = false
})
}
},
{ immediate: true, deep: true }
@ -518,7 +526,10 @@ watch(
watch(
localNodeData,
() => {
emitUpdate()
// Only emit if we're not currently updating from props
if (!isUpdatingFromProps.value) {
emitUpdate()
}
},
{ deep: true }
)

View File

@ -232,7 +232,7 @@
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { ref, computed, watch, nextTick } from 'vue'
// Props and emits
const props = defineProps({
@ -348,11 +348,15 @@ const emitUpdate = () => {
emit('update', localNodeData.value)
}
// Add a flag to prevent recursive updates
const isUpdatingFromProps = ref(false)
// Watch for prop changes
watch(
() => props.nodeData,
(newData) => {
if (newData && Object.keys(newData).length > 0) {
isUpdatingFromProps.value = true
localNodeData.value = {
label: newData.label || 'Script Task',
description: newData.description || '',
@ -363,6 +367,10 @@ watch(
continueOnError: newData.continueOnError || false,
errorVariable: newData.errorVariable || 'scriptError'
}
// Reset the flag after the update
nextTick(() => {
isUpdatingFromProps.value = false
})
}
},
{ immediate: true, deep: true }
@ -372,7 +380,10 @@ watch(
watch(
localNodeData,
() => {
emitUpdate()
// Only emit if we're not currently updating from props
if (!isUpdatingFromProps.value) {
emitUpdate()
}
},
{ deep: true }
)

View File

@ -553,9 +553,66 @@ const pasteElements = async () => {
// Keyboard shortcuts for panel toggles and copy/paste
const handleKeyboardShortcuts = (event) => {
// Only handle shortcuts when no input is focused
if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
return;
// Check if any modal is open - if so, don't handle process builder shortcuts
const isModalOpen = showFormConfigModal.value ||
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
@ -579,12 +636,20 @@ const handleKeyboardShortcuts = (event) => {
// Ctrl/Cmd + C: Copy selected elements
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
event.preventDefault();
// Debug logging (can be removed in production)
if (process.env.NODE_ENV === 'development') {
console.log('📋 Process builder copy shortcut triggered');
}
copySelectedElements();
}
// Ctrl/Cmd + V: Paste elements
if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
event.preventDefault();
// Debug logging (can be removed in production)
if (process.env.NODE_ENV === 'development') {
console.log('📋 Process builder paste shortcut triggered');
}
pasteElements();
}
};