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>
|
||||
|
||||
<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 }
|
||||
)
|
||||
|
@ -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 }
|
||||
)
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user