mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-01-24 05:21:02 -08:00
fix: not able to open prompt editor by click prompt tree
This commit is contained in:
parent
c825dc5eab
commit
bdd2496be2
11 changed files with 214 additions and 108 deletions
|
|
@ -23,7 +23,6 @@ export const previewActionsMiddleware: StateCreator<AgentChatStoreType, [], [],
|
|||
previewDialogOpen: false,
|
||||
previewDialogBaseMode: 'preview',
|
||||
lastUpdated: null,
|
||||
expandedArrayItems: new Map(),
|
||||
formFieldsToScrollTo: [],
|
||||
});
|
||||
},
|
||||
|
|
@ -35,34 +34,6 @@ export const previewActionsMiddleware: StateCreator<AgentChatStoreType, [], [],
|
|||
setFormFieldsToScrollTo: (fieldPaths: string[]) => {
|
||||
set({ formFieldsToScrollTo: fieldPaths });
|
||||
},
|
||||
setArrayItemExpanded: (itemId: string, expanded: boolean) => {
|
||||
const { expandedArrayItems } = get();
|
||||
const newMap = new Map(expandedArrayItems);
|
||||
if (expanded) {
|
||||
newMap.set(itemId, true);
|
||||
} else {
|
||||
newMap.delete(itemId);
|
||||
}
|
||||
set({ expandedArrayItems: newMap });
|
||||
},
|
||||
isArrayItemExpanded: (itemId: string) => {
|
||||
const { expandedArrayItems } = get();
|
||||
return expandedArrayItems.get(itemId) ?? false;
|
||||
},
|
||||
expandPathToTarget: (targetPath: string[]) => {
|
||||
const { expandedArrayItems } = get();
|
||||
const newMap = new Map(expandedArrayItems);
|
||||
|
||||
// For a path like ['prompts', 'system', 'children', 'default-main']
|
||||
// We need to expand each ID that represents an array item: 'system' and 'default-main'
|
||||
for (let index = 1; index < targetPath.length; index += 1) {
|
||||
if (targetPath[index]) {
|
||||
newMap.set(targetPath[index], true);
|
||||
}
|
||||
}
|
||||
|
||||
set({ expandedArrayItems: newMap });
|
||||
},
|
||||
|
||||
updatePreviewProgress: (progress: number, step: string, currentPlugin?: string) => {
|
||||
set({
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ export const useAgentChatStore = create<AgentChatStoreType>()((set, get, api) =>
|
|||
previewResult: null,
|
||||
lastUpdated: null,
|
||||
formFieldsToScrollTo: [],
|
||||
expandedArrayItems: new Map(),
|
||||
};
|
||||
|
||||
// Merge all actions and initial state
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ export interface PreviewDialogState {
|
|||
} | null;
|
||||
lastUpdated: Date | null;
|
||||
formFieldsToScrollTo: string[];
|
||||
expandedArrayItems: Map<string, boolean>;
|
||||
}
|
||||
|
||||
// Basic actions interface
|
||||
|
|
@ -159,25 +158,6 @@ export interface PreviewActions {
|
|||
*/
|
||||
setFormFieldsToScrollTo: (fieldPaths: string[]) => void;
|
||||
|
||||
/**
|
||||
* Sets the expansion state of a specific array item by its ID
|
||||
* @param itemId The unique ID of the array item
|
||||
* @param expanded Whether the item should be expanded
|
||||
*/
|
||||
setArrayItemExpanded: (itemId: string, expanded: boolean) => void;
|
||||
|
||||
/**
|
||||
* Checks if a specific array item is expanded by its ID
|
||||
* @param itemId The unique ID of the array item
|
||||
*/
|
||||
isArrayItemExpanded: (itemId: string) => boolean;
|
||||
|
||||
/**
|
||||
* Expands all parent paths leading to a target field
|
||||
* @param targetPath The target field path to expand to
|
||||
*/
|
||||
expandPathToTarget: (targetPath: string[]) => void;
|
||||
|
||||
/**
|
||||
* Updates preview progress state
|
||||
* @param progress Progress value from 0 to 1
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { useShallow } from 'zustand/react/shallow';
|
|||
import { AgentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
|
||||
import { useAgentChatStore } from '../../../Agent/store/agentChatStore/index';
|
||||
import { PromptConfigForm } from './PromptConfigForm';
|
||||
import { useArrayFieldStore } from './PromptConfigForm/store/arrayFieldStore';
|
||||
|
||||
// Lazy load Monaco Editor only when needed
|
||||
const MonacoEditor = lazy(async () => await import('@monaco-editor/react'));
|
||||
|
|
@ -34,14 +35,16 @@ export const EditView: FC<EditViewProps> = ({
|
|||
const [editorMode, setEditorMode] = useState<'form' | 'code'>('form');
|
||||
const [monacoInitialized, setMonacoInitialized] = useState(false);
|
||||
|
||||
const { formFieldsToScrollTo, setFormFieldsToScrollTo, expandPathToTarget } = useAgentChatStore(
|
||||
const { formFieldsToScrollTo, setFormFieldsToScrollTo } = useAgentChatStore(
|
||||
useShallow((state) => ({
|
||||
formFieldsToScrollTo: state.formFieldsToScrollTo,
|
||||
setFormFieldsToScrollTo: state.setFormFieldsToScrollTo,
|
||||
expandPathToTarget: state.expandPathToTarget,
|
||||
})),
|
||||
);
|
||||
|
||||
// Use a stable reference for expandItemsByPath
|
||||
const expandItemsByPath = useArrayFieldStore(useCallback((state) => state.expandItemsByPath, []));
|
||||
|
||||
const {
|
||||
loading: agentFrameworkConfigLoading,
|
||||
config: agentFrameworkConfig,
|
||||
|
|
@ -52,26 +55,66 @@ export const EditView: FC<EditViewProps> = ({
|
|||
agentId: agent?.id,
|
||||
});
|
||||
|
||||
// Use a ref to track if we're currently processing a scroll request
|
||||
const isProcessingScrollReference = React.useRef(false);
|
||||
const savedPathReference = React.useRef<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (formFieldsToScrollTo.length > 0 && editorMode === 'form') {
|
||||
expandPathToTarget(formFieldsToScrollTo);
|
||||
if (formFieldsToScrollTo.length > 0 && editorMode === 'form' && agentFrameworkConfig && !isProcessingScrollReference.current) {
|
||||
// Mark as processing and save the path
|
||||
isProcessingScrollReference.current = true;
|
||||
savedPathReference.current = [...formFieldsToScrollTo];
|
||||
const savedPath = savedPathReference.current;
|
||||
|
||||
// Clear formFieldsToScrollTo - but don't let the cleanup cancel our timeouts
|
||||
setFormFieldsToScrollTo([]);
|
||||
|
||||
// Path format: ['prompts', 'system', 'child-id', 'child-id'] or ['prompts', 'system']
|
||||
// - savedPath[0]: top-level key (prompts, plugins, response)
|
||||
// - savedPath[1]: parent item id
|
||||
// - savedPath[2+]: nested child item ids (if present)
|
||||
|
||||
// Step 1: Expand the top-level item first
|
||||
setTimeout(() => {
|
||||
const topLevelKey = savedPath[0];
|
||||
if (savedPath.length > 1) {
|
||||
const firstItemId = savedPath[1];
|
||||
expandItemsByPath(topLevelKey, [firstItemId]);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Step 2: After the parent expands and children render, expand nested items
|
||||
// If path has more than 2 elements, we have nested children to expand
|
||||
const hasNestedChildren = savedPath.length > 2;
|
||||
if (hasNestedChildren) {
|
||||
setTimeout(() => {
|
||||
const topLevelKey = savedPath[0];
|
||||
const firstItemId = savedPath[1];
|
||||
const topLevelArray = agentFrameworkConfig[topLevelKey as keyof typeof agentFrameworkConfig];
|
||||
if (Array.isArray(topLevelArray)) {
|
||||
const parentIndex = topLevelArray.findIndex((item: unknown) => {
|
||||
const data = item as Record<string, unknown> | null;
|
||||
return data?.id === firstItemId || data?.caption === firstItemId || data?.title === firstItemId;
|
||||
});
|
||||
|
||||
if (parentIndex !== -1) {
|
||||
const nestedFieldPath = `${topLevelKey}_${parentIndex}_children`;
|
||||
// Get the nested item IDs (from savedPath[2] onwards)
|
||||
const nestedItemIds = savedPath.slice(2);
|
||||
expandItemsByPath(nestedFieldPath, nestedItemIds);
|
||||
}
|
||||
}
|
||||
}, 300); // Longer delay to wait for nested array to render
|
||||
}
|
||||
|
||||
const scrollTimeout = setTimeout(() => {
|
||||
const targetId = formFieldsToScrollTo[formFieldsToScrollTo.length - 1];
|
||||
// Step 3: Scroll to the target element (after nested items have expanded)
|
||||
const scrollDelay = hasNestedChildren ? 500 : 200;
|
||||
setTimeout(() => {
|
||||
const targetId = savedPath[savedPath.length - 1];
|
||||
|
||||
// Find input element whose value exactly matches the target ID
|
||||
const targetElement = document.querySelector(`input[value="${targetId}"]`);
|
||||
if (targetElement) {
|
||||
// Expand parent accordions
|
||||
let current = targetElement.parentElement;
|
||||
while (current) {
|
||||
const accordion = current.querySelector('[aria-expanded="false"]');
|
||||
if (accordion instanceof HTMLElement) {
|
||||
accordion.click();
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
|
||||
// Scroll to element and highlight
|
||||
setTimeout(() => {
|
||||
if (targetElement instanceof HTMLElement) {
|
||||
|
|
@ -84,15 +127,12 @@ export const EditView: FC<EditViewProps> = ({
|
|||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
setFormFieldsToScrollTo([]);
|
||||
}, 100);
|
||||
|
||||
return () => {
|
||||
clearTimeout(scrollTimeout);
|
||||
};
|
||||
|
||||
// Mark processing as complete
|
||||
isProcessingScrollReference.current = false;
|
||||
}, scrollDelay);
|
||||
}
|
||||
}, [formFieldsToScrollTo, editorMode, setFormFieldsToScrollTo, expandPathToTarget]);
|
||||
}, [formFieldsToScrollTo, editorMode, expandItemsByPath, agentFrameworkConfig, setFormFieldsToScrollTo]);
|
||||
|
||||
const { getPreviewPromptResult } = useAgentChatStore(
|
||||
useShallow((state) => ({
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ interface ArrayFieldActions {
|
|||
cleanupField: (fieldPath: string) => void;
|
||||
/** Register move callbacks for an item */
|
||||
registerMoveCallbacks: (fieldPath: string, itemIndex: number, callbacks: ItemMoveCallbacks) => void;
|
||||
/** Expand items along a path by their IDs (caption field) */
|
||||
expandItemsByPath: (fieldPath: string, itemIds: string[]) => void;
|
||||
/** Reset all state */
|
||||
reset: () => void;
|
||||
}
|
||||
|
|
@ -67,11 +69,20 @@ export const useArrayFieldStore = create<ArrayFieldState & ArrayFieldActions>()(
|
|||
...initialState,
|
||||
|
||||
setItemExpanded: (fieldPath, itemIndex, expanded) => {
|
||||
console.log('[arrayFieldStore] setItemExpanded called', {
|
||||
fieldPath,
|
||||
itemIndex,
|
||||
expanded,
|
||||
});
|
||||
set((state) => {
|
||||
if (!state.expandedStates[fieldPath]) {
|
||||
state.expandedStates[fieldPath] = [];
|
||||
}
|
||||
state.expandedStates[fieldPath][itemIndex] = expanded;
|
||||
console.log('[arrayFieldStore] expandedStates updated', {
|
||||
fieldPath,
|
||||
newExpandedStates: state.expandedStates[fieldPath],
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -195,6 +206,34 @@ export const useArrayFieldStore = create<ArrayFieldState & ArrayFieldActions>()(
|
|||
});
|
||||
},
|
||||
|
||||
expandItemsByPath: (fieldPath, itemIds) => {
|
||||
set((state) => {
|
||||
const items = state.itemsData[fieldPath];
|
||||
if (!items || !Array.isArray(items)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expandedStates = state.expandedStates[fieldPath];
|
||||
if (!expandedStates) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For each ID in the path, find matching item and expand it
|
||||
itemIds.forEach((itemId) => {
|
||||
const itemIndex = items.findIndex((item) => {
|
||||
if (!item || typeof item !== 'object') return false;
|
||||
const data = item as Record<string, unknown>;
|
||||
// Match by id, caption, or title field
|
||||
return data.id === itemId || data.caption === itemId || data.title === itemId;
|
||||
});
|
||||
|
||||
if (itemIndex !== -1 && itemIndex < expandedStates.length) {
|
||||
expandedStates[itemIndex] = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
reset: () => {
|
||||
set(initialState);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Box, Checkbox, IconButton } from '@mui/material';
|
|||
import { ArrayFieldItemTemplateProps, FormContextType, getTemplate, getUiOptions, RJSFSchema } from '@rjsf/utils';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { ArrayItemProvider, useArrayItemContext } from '../context/ArrayItemContext';
|
||||
import { ExtendedFormContext } from '../index';
|
||||
import { useArrayFieldStore } from '../store/arrayFieldStore';
|
||||
|
|
@ -37,16 +38,25 @@ export function ArrayFieldItemTemplate<T = unknown, S extends RJSFSchema = RJSFS
|
|||
// This ensures consistent path between template and item
|
||||
const fieldPath = arrayItemContext.arrayFieldPath ?? 'array';
|
||||
|
||||
// Get expanded state from store using shallow comparison
|
||||
const expanded = useArrayFieldStore(
|
||||
useCallback((state) => state.expandedStates[fieldPath]?.[index] ?? false, [fieldPath, index]),
|
||||
// Get ALL relevant store data in one subscription
|
||||
// Use useShallow to prevent unnecessary re-renders
|
||||
const {
|
||||
expandedStates,
|
||||
stableItemIds: allStableItemIds,
|
||||
setItemExpanded,
|
||||
registerMoveCallbacks,
|
||||
} = useArrayFieldStore(
|
||||
useShallow((state) => ({
|
||||
expandedStates: state.expandedStates,
|
||||
stableItemIds: state.stableItemIds,
|
||||
setItemExpanded: state.setItemExpanded,
|
||||
registerMoveCallbacks: state.registerMoveCallbacks,
|
||||
})),
|
||||
);
|
||||
// Get stable item ID from store for dnd-kit
|
||||
const stableItemId = useArrayFieldStore(
|
||||
useCallback((state) => state.stableItemIds[fieldPath]?.[index] ?? `item-${index}`, [fieldPath, index]),
|
||||
);
|
||||
const setItemExpanded = useArrayFieldStore((state) => state.setItemExpanded);
|
||||
const registerMoveCallbacks = useArrayFieldStore((state) => state.registerMoveCallbacks);
|
||||
|
||||
// Get data for this specific item
|
||||
const expanded = expandedStates[fieldPath]?.[index] ?? false;
|
||||
const stableItemId = allStableItemIds[fieldPath]?.[index] ?? `item-${index}`;
|
||||
|
||||
// Register move callbacks so they can be accessed during drag operations
|
||||
useEffect(() => {
|
||||
|
|
@ -65,8 +75,15 @@ export function ArrayFieldItemTemplate<T = unknown, S extends RJSFSchema = RJSFS
|
|||
});
|
||||
|
||||
const handleToggleExpanded = useCallback(() => {
|
||||
console.log('[ArrayFieldItemTemplate] handleToggleExpanded called', {
|
||||
fieldPath,
|
||||
index,
|
||||
currentExpanded: expanded,
|
||||
willBeExpanded: !expanded,
|
||||
itemCaption: (itemData as any)?.caption,
|
||||
});
|
||||
setItemExpanded(fieldPath, index, !expanded);
|
||||
}, [fieldPath, index, expanded, setItemExpanded]);
|
||||
}, [fieldPath, index, expanded, setItemExpanded, itemData]);
|
||||
|
||||
// 获取当前项的数据来显示 caption
|
||||
const itemCaption = useMemo(() => {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Box, Typography } from '@mui/material';
|
|||
import { ArrayFieldTemplateProps } from '@rjsf/utils';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { ArrayAddButton, ArrayContainer, ArrayHeader, ArrayItemCount, EmptyState, HelpTooltip, StyledFieldLabel } from '../components';
|
||||
import { ArrayItemProvider } from '../context/ArrayItemContext';
|
||||
import { ExtendedFormContext } from '../index';
|
||||
|
|
@ -16,7 +17,7 @@ import { useArrayFieldStore } from '../store/arrayFieldStore';
|
|||
export const ArrayFieldTemplate: React.FC<ArrayFieldTemplateProps> = (props) => {
|
||||
const { items, onAddClick, canAdd, title, schema, registry } = props;
|
||||
const formData = props.formData as unknown[] | undefined;
|
||||
const fieldPathId = (props as unknown as { fieldPathId?: { path: (string | number)[] } }).fieldPathId;
|
||||
const fieldPathId = (props as unknown as { fieldPathId?: { path: (string | number)[]; $id?: string } }).fieldPathId;
|
||||
const { t } = useTranslation('agent');
|
||||
|
||||
// Get formContext for direct data manipulation
|
||||
|
|
@ -25,18 +26,42 @@ export const ArrayFieldTemplate: React.FC<ArrayFieldTemplateProps> = (props) =>
|
|||
const description = schema.description;
|
||||
|
||||
// Generate a stable field path for this array
|
||||
// Use title as fallback since idSchema might not be available
|
||||
const fieldPath = useMemo(() => title || 'array', [title]);
|
||||
// Use fieldPathId from RJSF which contains the actual property path
|
||||
const fieldPath = useMemo(() => {
|
||||
// First try to use fieldPathId which contains the actual path like ["prompts"] or ["prompts", 0, "children"]
|
||||
if (fieldPathId?.path && Array.isArray(fieldPathId.path) && fieldPathId.path.length > 0) {
|
||||
return fieldPathId.path.join('_');
|
||||
}
|
||||
// Fallback to fieldPathId.$id with root_ prefix removed
|
||||
if (fieldPathId?.$id) {
|
||||
return fieldPathId.$id.replace(/^root_/, '');
|
||||
}
|
||||
return title || 'array';
|
||||
}, [fieldPathId?.path, fieldPathId?.$id, title]);
|
||||
|
||||
// Get store actions and state
|
||||
const initializeField = useArrayFieldStore((state) => state.initializeField);
|
||||
const updateItemsData = useArrayFieldStore((state) => state.updateItemsData);
|
||||
const cleanupField = useArrayFieldStore((state) => state.cleanupField);
|
||||
const moveItem = useArrayFieldStore((state) => state.moveItem);
|
||||
// Get stable item IDs from store - these persist across re-renders
|
||||
const stableItemIds = useArrayFieldStore((state) => state.stableItemIds[fieldPath] ?? []);
|
||||
// Get items order from store - used for optimistic rendering during drag
|
||||
const itemsOrder = useArrayFieldStore((state) => state.itemsOrder[fieldPath] ?? []);
|
||||
// Get ALL store data and functions in one subscription to avoid multiple subscriptions
|
||||
// Use useShallow to prevent unnecessary re-renders when the returned object has the same values
|
||||
const {
|
||||
initializeField,
|
||||
updateItemsData,
|
||||
cleanupField,
|
||||
moveItem,
|
||||
stableItemIds: allStableItemIds,
|
||||
itemsOrder: allItemsOrder,
|
||||
} = useArrayFieldStore(
|
||||
useShallow((state) => ({
|
||||
initializeField: state.initializeField,
|
||||
updateItemsData: state.updateItemsData,
|
||||
cleanupField: state.cleanupField,
|
||||
moveItem: state.moveItem,
|
||||
stableItemIds: state.stableItemIds,
|
||||
itemsOrder: state.itemsOrder,
|
||||
})),
|
||||
);
|
||||
|
||||
// Get data for this specific fieldPath
|
||||
const stableItemIds = allStableItemIds[fieldPath] ?? [];
|
||||
const itemsOrder = allItemsOrder[fieldPath] ?? [];
|
||||
|
||||
// Track active drag item for overlay
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
|
|
@ -48,9 +73,36 @@ export const ArrayFieldTemplate: React.FC<ArrayFieldTemplateProps> = (props) =>
|
|||
}, [fieldPath, items.length, initializeField]);
|
||||
|
||||
// Update store when formData changes (from RJSF)
|
||||
// Use ref to track previous formData and only update when content actually changes
|
||||
const previousFormDataReference = React.useRef<unknown[] | undefined>(undefined);
|
||||
const previousLengthReference = React.useRef<number>(-1);
|
||||
|
||||
useEffect(() => {
|
||||
const itemsData = Array.isArray(formData) ? formData : [];
|
||||
updateItemsData(fieldPath, itemsData);
|
||||
const currentLength = itemsData.length;
|
||||
|
||||
// Only update if:
|
||||
// 1. This is the first render (previousLengthReference.current === -1)
|
||||
// 2. Length changed
|
||||
// 3. Content changed (only check if length is the same)
|
||||
if (previousLengthReference.current === -1 || previousLengthReference.current !== currentLength) {
|
||||
previousFormDataReference.current = itemsData;
|
||||
previousLengthReference.current = currentLength;
|
||||
updateItemsData(fieldPath, itemsData);
|
||||
} else if (previousFormDataReference.current) {
|
||||
// Length is the same, do a shallow comparison of items
|
||||
let hasChanged = false;
|
||||
for (let itemIndex = 0; itemIndex < itemsData.length; itemIndex++) {
|
||||
if (itemsData[itemIndex] !== previousFormDataReference.current[itemIndex]) {
|
||||
hasChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasChanged) {
|
||||
previousFormDataReference.current = itemsData;
|
||||
updateItemsData(fieldPath, itemsData);
|
||||
}
|
||||
}
|
||||
}, [formData, fieldPath, updateItemsData]);
|
||||
|
||||
// Cleanup on unmount
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ describe('PromptPreviewDialog - Tool Information Rendering', () => {
|
|||
previewCurrentPlugin: null,
|
||||
lastUpdated: null,
|
||||
formFieldsToScrollTo: [],
|
||||
expandedArrayItems: new Map(),
|
||||
});
|
||||
|
||||
// Clear all mock calls
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ describe('PromptPreviewDialog - Tool Information Rendering', () => {
|
|||
previewCurrentPlugin: null,
|
||||
lastUpdated: null,
|
||||
formFieldsToScrollTo: [],
|
||||
expandedArrayItems: new Map(),
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export const PromptPreviewDialog: React.FC<PromptPreviewDialogProps> = ({
|
|||
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||
const [baseMode, setBaseMode] = useState<'preview' | 'edit'>(initialBaseMode);
|
||||
const [showSideBySide, setShowSideBySide] = useState(false);
|
||||
const [baseModeBeforeSideBySide, setBaseModeBeforeSideBySide] = useState<'preview' | 'edit'>(initialBaseMode);
|
||||
|
||||
const {
|
||||
loading: agentFrameworkConfigLoading,
|
||||
|
|
@ -75,10 +76,19 @@ export const PromptPreviewDialog: React.FC<PromptPreviewDialogProps> = ({
|
|||
}, []);
|
||||
|
||||
const handleToggleEditMode = useCallback((): void => {
|
||||
setShowSideBySide(previous => !previous);
|
||||
}, []);
|
||||
setShowSideBySide(previous => {
|
||||
if (!previous) {
|
||||
// Entering side-by-side, save current baseMode
|
||||
setBaseModeBeforeSideBySide(baseMode);
|
||||
} else {
|
||||
// Exiting side-by-side, restore previous baseMode
|
||||
setBaseMode(baseModeBeforeSideBySide);
|
||||
}
|
||||
return !previous;
|
||||
});
|
||||
}, [baseMode, baseModeBeforeSideBySide]);
|
||||
|
||||
// Listen for form field scroll targets to automatically switch to edit mode
|
||||
// Listen for form field scroll targets to automatically switch to side-by-side mode
|
||||
const { formFieldsToScrollTo } = useAgentChatStore(
|
||||
useShallow((state) => ({
|
||||
formFieldsToScrollTo: state.formFieldsToScrollTo,
|
||||
|
|
@ -86,10 +96,12 @@ export const PromptPreviewDialog: React.FC<PromptPreviewDialogProps> = ({
|
|||
);
|
||||
useEffect(() => {
|
||||
if (formFieldsToScrollTo.length > 0) {
|
||||
// Save current baseMode before switching to side-by-side
|
||||
setBaseModeBeforeSideBySide(baseMode);
|
||||
setBaseMode('edit');
|
||||
setShowSideBySide(false);
|
||||
setShowSideBySide(true); // Show side-by-side when clicking from PromptTree
|
||||
}
|
||||
}, [formFieldsToScrollTo]);
|
||||
}, [formFieldsToScrollTo, baseMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
|
|
|
|||
|
|
@ -49,10 +49,9 @@ export const PromptTreeNode = memo(({
|
|||
depth: number;
|
||||
fieldPath?: string[];
|
||||
}): React.ReactElement => {
|
||||
const { setFormFieldsToScrollTo, expandPathToTarget } = useAgentChatStore(
|
||||
const { setFormFieldsToScrollTo } = useAgentChatStore(
|
||||
useShallow((state) => ({
|
||||
setFormFieldsToScrollTo: state.setFormFieldsToScrollTo,
|
||||
expandPathToTarget: state.expandPathToTarget,
|
||||
})),
|
||||
);
|
||||
const handleNodeClick = useCallback((event: React.MouseEvent) => {
|
||||
|
|
@ -61,8 +60,7 @@ export const PromptTreeNode = memo(({
|
|||
const targetFieldPath = (node.source && node.source.length > 0) ? node.source : [...fieldPath, node.id];
|
||||
|
||||
setFormFieldsToScrollTo(targetFieldPath);
|
||||
expandPathToTarget(targetFieldPath);
|
||||
}, [node.source, node.id, fieldPath, setFormFieldsToScrollTo, expandPathToTarget]);
|
||||
}, [node.source, node.id, fieldPath, setFormFieldsToScrollTo]);
|
||||
|
||||
return (
|
||||
<TreeItem
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue