mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
refactor(ui): workflows left panel internal components structure
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import 'reactflow/dist/style.css';
|
||||
|
||||
import { Box } from '@invoke-ai/ui-library';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels';
|
||||
|
||||
import WorkflowNodeInspectorPanel from './inspector/WorkflowNodeInspectorPanel';
|
||||
import WorkflowFieldsLinearViewPanel from './workflow/WorkflowPanel';
|
||||
|
||||
const panelGroupStyles: CSSProperties = { height: '100%', width: '100%' };
|
||||
|
||||
export const LinearViewLeftPanelContent = memo(() => {
|
||||
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
|
||||
|
||||
const handleDoubleClickHandle = useCallback(() => {
|
||||
if (!panelGroupRef.current) {
|
||||
return;
|
||||
}
|
||||
panelGroupRef.current.setLayout([50, 50]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box position="relative" w="full" h="full">
|
||||
<ScrollableContent>
|
||||
<PanelGroup
|
||||
ref={panelGroupRef}
|
||||
id="workflow-panel-group"
|
||||
autoSaveId="workflow-panel-group"
|
||||
direction="vertical"
|
||||
style={panelGroupStyles}
|
||||
>
|
||||
<Panel id="workflow" collapsible minSize={25}>
|
||||
<WorkflowFieldsLinearViewPanel />
|
||||
</Panel>
|
||||
<ResizeHandle onDoubleClick={handleDoubleClickHandle} />
|
||||
<Panel id="inspector" collapsible minSize={25}>
|
||||
<WorkflowNodeInspectorPanel />
|
||||
</Panel>
|
||||
</PanelGroup>
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
|
||||
LinearViewLeftPanelContent.displayName = 'LinearViewLeftPanelContent';
|
||||
@@ -1,79 +0,0 @@
|
||||
import 'reactflow/dist/style.css';
|
||||
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
|
||||
import { selectWorkflowMode } from 'features/nodes/store/workflowSlice';
|
||||
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
|
||||
import { Panel, PanelGroup } from 'react-resizable-panels';
|
||||
|
||||
import WorkflowNodeInspectorPanel from './inspector/WorkflowNodeInspectorPanel';
|
||||
import { FieldsSimpleView } from './viewMode/WorkflowSimpleView';
|
||||
import WorkflowFieldsLinearViewPanel from './workflow/WorkflowPanel';
|
||||
import { WorkflowListMenu } from './WorkflowListMenu/WorkflowListMenu';
|
||||
import { WorkflowListMenuTrigger } from './WorkflowListMenu/WorkflowListMenuTrigger';
|
||||
|
||||
const panelGroupStyles: CSSProperties = { height: '100%', width: '100%' };
|
||||
|
||||
const overlayScrollbarsStyles: CSSProperties = {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
};
|
||||
|
||||
const WorkflowsLeftPanel = () => {
|
||||
const mode = useAppSelector(selectWorkflowMode);
|
||||
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
|
||||
const workflowListMenu = useWorkflowListMenu();
|
||||
|
||||
const handleDoubleClickHandle = useCallback(() => {
|
||||
if (!panelGroupRef.current) {
|
||||
return;
|
||||
}
|
||||
panelGroupRef.current.setLayout([50, 50]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex w="full" h="full" gap={2} flexDir="column">
|
||||
<WorkflowListMenuTrigger />
|
||||
<Flex w="full" h="full" position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
{workflowListMenu.isOpen && (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<WorkflowListMenu />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
)}
|
||||
|
||||
{mode === 'view' && <FieldsSimpleView />}
|
||||
{mode === 'edit' && (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<PanelGroup
|
||||
ref={panelGroupRef}
|
||||
id="workflow-panel-group"
|
||||
autoSaveId="workflow-panel-group"
|
||||
direction="vertical"
|
||||
style={panelGroupStyles}
|
||||
>
|
||||
<Panel id="workflow" collapsible minSize={25}>
|
||||
<WorkflowFieldsLinearViewPanel />
|
||||
</Panel>
|
||||
<ResizeHandle onDoubleClick={handleDoubleClickHandle} />
|
||||
<Panel id="inspector" collapsible minSize={25}>
|
||||
<WorkflowNodeInspectorPanel />
|
||||
</Panel>
|
||||
</PanelGroup>
|
||||
</OverlayScrollbarsComponent>
|
||||
)}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(WorkflowsLeftPanel);
|
||||
@@ -1,28 +1,34 @@
|
||||
import { Flex } from '@invoke-ai/ui-library';
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $workflowCategories } from 'app/store/nanostores/workflowCategories';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import UploadWorkflowButton from 'features/workflowLibrary/components/UploadWorkflowButton';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { WorkflowList } from './WorkflowList';
|
||||
import WorkflowSearch from './WorkflowSearch';
|
||||
import { WorkflowSortControl } from './WorkflowSortControl';
|
||||
|
||||
export const WorkflowListMenu = () => {
|
||||
export const WorkflowListMenu = memo(() => {
|
||||
const workflowCategories = useStore($workflowCategories);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">
|
||||
<Flex w="full" h="full" flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">
|
||||
<Flex alignItems="center" gap={2} w="full" justifyContent="space-between">
|
||||
<WorkflowSearch />
|
||||
|
||||
<WorkflowSortControl />
|
||||
|
||||
<UploadWorkflowButton />
|
||||
</Flex>
|
||||
|
||||
{workflowCategories.map((category) => (
|
||||
<WorkflowList key={category} category={category} />
|
||||
))}
|
||||
<Box position="relative" w="full" h="full">
|
||||
<ScrollableContent>
|
||||
{workflowCategories.map((category) => (
|
||||
<WorkflowList key={category} category={category} />
|
||||
))}
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
WorkflowListMenu.displayName = 'WorkflowListMenu';
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'reactflow/dist/style.css';
|
||||
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { LinearViewLeftPanelContent } from 'features/nodes/components/sidePanel/LinearViewLeftPanelContent';
|
||||
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
|
||||
import { selectWorkflowMode } from 'features/nodes/store/workflowSlice';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { SimpleViewLeftPanelContent } from './viewMode/SimpleViewLeftPanelContent';
|
||||
import { WorkflowListMenu } from './WorkflowListMenu/WorkflowListMenu';
|
||||
import { WorkflowListMenuTrigger } from './WorkflowListMenu/WorkflowListMenuTrigger';
|
||||
|
||||
const WorkflowsTabLeftPanel = () => {
|
||||
const mode = useAppSelector(selectWorkflowMode);
|
||||
const workflowListMenu = useWorkflowListMenu();
|
||||
|
||||
return (
|
||||
<Flex w="full" h="full" gap={2} flexDir="column">
|
||||
<WorkflowListMenuTrigger />
|
||||
<Flex w="full" h="full" position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
{workflowListMenu.isOpen && <WorkflowListMenu />}
|
||||
{mode === 'view' && <SimpleViewLeftPanelContent />}
|
||||
{mode === 'edit' && <LinearViewLeftPanelContent />}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(WorkflowsTabLeftPanel);
|
||||
@@ -14,20 +14,20 @@ import { EmptyState } from './EmptyState';
|
||||
|
||||
const selectExposedFields = createMemoizedSelector(selectWorkflowSlice, (workflow) => workflow.exposedFields);
|
||||
|
||||
export const FieldsSimpleView = memo(() => {
|
||||
export const SimpleViewLeftPanelContent = memo(() => {
|
||||
return (
|
||||
<Box position="relative" w="full" h="full">
|
||||
<ScrollableContent>
|
||||
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} gap={2} w="full" h="full">
|
||||
<FieldSimpleViewContent />
|
||||
<SimpleViewLeftPanelContentInner />
|
||||
</Flex>
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
FieldsSimpleView.displayName = 'FieldsSimpleView';
|
||||
SimpleViewLeftPanelContent.displayName = 'SimpleViewLeftPanelContent';
|
||||
|
||||
const FieldSimpleViewContent = memo(() => {
|
||||
const SimpleViewLeftPanelContentInner = memo(() => {
|
||||
const { isLoading } = useGetOpenAPISchemaQuery();
|
||||
const exposedFields = useAppSelector(selectExposedFields);
|
||||
|
||||
@@ -49,4 +49,4 @@ const FieldSimpleViewContent = memo(() => {
|
||||
</>
|
||||
);
|
||||
});
|
||||
FieldSimpleViewContent.displayName = 'FieldSimpleViewContent';
|
||||
SimpleViewLeftPanelContentInner.displayName = ' SimpleViewLeftPanelContentInner';
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useFieldTemplateTitle = (nodeId: string, fieldName: string, kind: 'inputs' | 'outputs'): string | null => {
|
||||
export const useFieldTemplateTitle = (nodeId: string, fieldName: string, kind: 'inputs' | 'outputs'): string => {
|
||||
const fieldTemplate = useFieldTemplate(nodeId, fieldName, kind);
|
||||
const fieldTemplateTitle = useMemo(() => fieldTemplate.title, [fieldTemplate]);
|
||||
return fieldTemplateTitle;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { CanvasRightPanel } from 'features/controlLayers/components/CanvasRightP
|
||||
import { useDndMonitor } from 'features/dnd/useDndMonitor';
|
||||
import GalleryPanelContent from 'features/gallery/components/GalleryPanelContent';
|
||||
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
|
||||
import WorkflowsLeftPanel from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
|
||||
import WorkflowsTabLeftPanel from 'features/nodes/components/sidePanel/WorkflowsTabLeftPanel';
|
||||
import QueueControls from 'features/queue/components/QueueControls';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
|
||||
@@ -183,7 +183,7 @@ const LeftPanelContent = memo(() => {
|
||||
return <ParametersPanelUpscale />;
|
||||
}
|
||||
if (tab === 'workflows') {
|
||||
return <WorkflowsLeftPanel />;
|
||||
return <WorkflowsTabLeftPanel />;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user