mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): organise nodes files
- also remove old `.gitignore` of `inputs/` which wasn't used and was ignoring a frontend folder
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,9 +15,6 @@ invokeai.init
|
|||||||
# ignore the Anaconda/Miniconda installer used while building Docker image
|
# ignore the Anaconda/Miniconda installer used while building Docker image
|
||||||
anaconda.sh
|
anaconda.sh
|
||||||
|
|
||||||
# ignore a directory which serves as a place for initial images
|
|
||||||
inputs/
|
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
@ -213,7 +210,6 @@ invokeai/frontend/node_modules
|
|||||||
gfpgan/
|
gfpgan/
|
||||||
models/ldm/stable-diffusion-v1/*.sha256
|
models/ldm/stable-diffusion-v1/*.sha256
|
||||||
|
|
||||||
|
|
||||||
# GFPGAN model files
|
# GFPGAN model files
|
||||||
gfpgan/
|
gfpgan/
|
||||||
|
|
||||||
|
@ -1,199 +0,0 @@
|
|||||||
import { Badge, Flex } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { stateSelector } from 'app/store/store';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
|
||||||
import { memo, useMemo } from 'react';
|
|
||||||
import {
|
|
||||||
BaseEdge,
|
|
||||||
EdgeLabelRenderer,
|
|
||||||
EdgeProps,
|
|
||||||
getBezierPath,
|
|
||||||
} from 'reactflow';
|
|
||||||
import { FIELDS, colorTokenToCssVar } from '../types/constants';
|
|
||||||
import { isInvocationNode } from '../types/types';
|
|
||||||
|
|
||||||
const makeEdgeSelector = (
|
|
||||||
source: string,
|
|
||||||
sourceHandleId: string | null | undefined,
|
|
||||||
target: string,
|
|
||||||
targetHandleId: string | null | undefined,
|
|
||||||
selected?: boolean
|
|
||||||
) =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const sourceNode = nodes.nodes.find((node) => node.id === source);
|
|
||||||
const targetNode = nodes.nodes.find((node) => node.id === target);
|
|
||||||
|
|
||||||
const isInvocationToInvocationEdge =
|
|
||||||
isInvocationNode(sourceNode) && isInvocationNode(targetNode);
|
|
||||||
|
|
||||||
const isSelected =
|
|
||||||
sourceNode?.selected || targetNode?.selected || selected;
|
|
||||||
const sourceType = isInvocationToInvocationEdge
|
|
||||||
? sourceNode?.data?.outputs[sourceHandleId || '']?.type
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const stroke =
|
|
||||||
sourceType && nodes.shouldColorEdges
|
|
||||||
? colorTokenToCssVar(FIELDS[sourceType].color)
|
|
||||||
: colorTokenToCssVar('base.500');
|
|
||||||
|
|
||||||
return {
|
|
||||||
isSelected,
|
|
||||||
shouldAnimate: nodes.shouldAnimateEdges && isSelected,
|
|
||||||
stroke,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
const CollapsedEdge = memo(
|
|
||||||
({
|
|
||||||
sourceX,
|
|
||||||
sourceY,
|
|
||||||
targetX,
|
|
||||||
targetY,
|
|
||||||
sourcePosition,
|
|
||||||
targetPosition,
|
|
||||||
markerEnd,
|
|
||||||
data,
|
|
||||||
selected,
|
|
||||||
source,
|
|
||||||
target,
|
|
||||||
sourceHandleId,
|
|
||||||
targetHandleId,
|
|
||||||
}: EdgeProps<{ count: number }>) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
makeEdgeSelector(
|
|
||||||
source,
|
|
||||||
sourceHandleId,
|
|
||||||
target,
|
|
||||||
targetHandleId,
|
|
||||||
selected
|
|
||||||
),
|
|
||||||
[selected, source, sourceHandleId, target, targetHandleId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { isSelected, shouldAnimate } = useAppSelector(selector);
|
|
||||||
|
|
||||||
const [edgePath, labelX, labelY] = getBezierPath({
|
|
||||||
sourceX,
|
|
||||||
sourceY,
|
|
||||||
sourcePosition,
|
|
||||||
targetX,
|
|
||||||
targetY,
|
|
||||||
targetPosition,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { base500 } = useChakraThemeTokens();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<BaseEdge
|
|
||||||
path={edgePath}
|
|
||||||
markerEnd={markerEnd}
|
|
||||||
style={{
|
|
||||||
strokeWidth: isSelected ? 3 : 2,
|
|
||||||
stroke: base500,
|
|
||||||
opacity: isSelected ? 0.8 : 0.5,
|
|
||||||
animation: shouldAnimate
|
|
||||||
? 'dashdraw 0.5s linear infinite'
|
|
||||||
: undefined,
|
|
||||||
strokeDasharray: shouldAnimate ? 5 : 'none',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{data?.count && data.count > 1 && (
|
|
||||||
<EdgeLabelRenderer>
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
|
||||||
}}
|
|
||||||
className="nodrag nopan"
|
|
||||||
>
|
|
||||||
<Badge
|
|
||||||
variant="solid"
|
|
||||||
sx={{
|
|
||||||
bg: 'base.500',
|
|
||||||
opacity: isSelected ? 0.8 : 0.5,
|
|
||||||
boxShadow: 'base',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{data.count}
|
|
||||||
</Badge>
|
|
||||||
</Flex>
|
|
||||||
</EdgeLabelRenderer>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
CollapsedEdge.displayName = 'CollapsedEdge';
|
|
||||||
|
|
||||||
const DefaultEdge = memo(
|
|
||||||
({
|
|
||||||
sourceX,
|
|
||||||
sourceY,
|
|
||||||
targetX,
|
|
||||||
targetY,
|
|
||||||
sourcePosition,
|
|
||||||
targetPosition,
|
|
||||||
markerEnd,
|
|
||||||
selected,
|
|
||||||
source,
|
|
||||||
target,
|
|
||||||
sourceHandleId,
|
|
||||||
targetHandleId,
|
|
||||||
}: EdgeProps) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
makeEdgeSelector(
|
|
||||||
source,
|
|
||||||
sourceHandleId,
|
|
||||||
target,
|
|
||||||
targetHandleId,
|
|
||||||
selected
|
|
||||||
),
|
|
||||||
[source, sourceHandleId, target, targetHandleId, selected]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { isSelected, shouldAnimate, stroke } = useAppSelector(selector);
|
|
||||||
|
|
||||||
const [edgePath] = getBezierPath({
|
|
||||||
sourceX,
|
|
||||||
sourceY,
|
|
||||||
sourcePosition,
|
|
||||||
targetX,
|
|
||||||
targetY,
|
|
||||||
targetPosition,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<BaseEdge
|
|
||||||
path={edgePath}
|
|
||||||
markerEnd={markerEnd}
|
|
||||||
style={{
|
|
||||||
strokeWidth: isSelected ? 3 : 2,
|
|
||||||
stroke,
|
|
||||||
opacity: isSelected ? 0.8 : 0.5,
|
|
||||||
animation: shouldAnimate
|
|
||||||
? 'dashdraw 0.5s linear infinite'
|
|
||||||
: undefined,
|
|
||||||
strokeDasharray: shouldAnimate ? 5 : 'none',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
DefaultEdge.displayName = 'DefaultEdge';
|
|
||||||
|
|
||||||
export const edgeTypes = {
|
|
||||||
collapsed: CollapsedEdge,
|
|
||||||
default: DefaultEdge,
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
import CurrentImageNode from './nodes/CurrentImageNode';
|
|
||||||
import InvocationNodeWrapper from './nodes/InvocationNodeWrapper';
|
|
||||||
import NotesNode from './nodes/NotesNode';
|
|
||||||
|
|
||||||
export const nodeTypes = {
|
|
||||||
invocation: InvocationNodeWrapper,
|
|
||||||
current_image: CurrentImageNode,
|
|
||||||
notes: NotesNode,
|
|
||||||
};
|
|
@ -6,8 +6,8 @@ import { memo, useState } from 'react';
|
|||||||
import { MdDeviceHub } from 'react-icons/md';
|
import { MdDeviceHub } from 'react-icons/md';
|
||||||
import { Panel, PanelGroup } from 'react-resizable-panels';
|
import { Panel, PanelGroup } from 'react-resizable-panels';
|
||||||
import 'reactflow/dist/style.css';
|
import 'reactflow/dist/style.css';
|
||||||
import NodeEditorPanelGroup from './panel/NodeEditorPanelGroup';
|
import NodeEditorPanelGroup from './sidePanel/NodeEditorPanelGroup';
|
||||||
import { Flow } from './Flow';
|
import { Flow } from './flow/Flow';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
|
||||||
const NodeEditor = () => {
|
const NodeEditor = () => {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import ImageMetadataJSON from 'features/gallery/components/ImageMetadataViewer/ImageMetadataJSON';
|
|
||||||
import { omit } from 'lodash-es';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { useDebounce } from 'use-debounce';
|
|
||||||
import { buildNodesGraph } from '../util/graphBuilders/buildNodesGraph';
|
|
||||||
|
|
||||||
const useNodesGraph = () => {
|
|
||||||
const nodes = useAppSelector((state: RootState) => state.nodes);
|
|
||||||
const [debouncedNodes] = useDebounce(nodes, 300);
|
|
||||||
const graph = useMemo(
|
|
||||||
() => omit(buildNodesGraph(debouncedNodes), 'id'),
|
|
||||||
[debouncedNodes]
|
|
||||||
);
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
};
|
|
||||||
|
|
||||||
const NodeGraph = () => {
|
|
||||||
const graph = useNodesGraph();
|
|
||||||
|
|
||||||
return <ImageMetadataJSON jsonObject={graph} label="Graph" />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NodeGraph;
|
|
@ -1,13 +0,0 @@
|
|||||||
import {
|
|
||||||
InputFieldTemplate,
|
|
||||||
InputFieldValue,
|
|
||||||
} from 'features/nodes/types/types';
|
|
||||||
|
|
||||||
export type FieldComponentProps<
|
|
||||||
V extends InputFieldValue,
|
|
||||||
T extends InputFieldTemplate
|
|
||||||
> = {
|
|
||||||
nodeId: string;
|
|
||||||
field: V;
|
|
||||||
fieldTemplate: T;
|
|
||||||
};
|
|
@ -17,7 +17,7 @@ import {
|
|||||||
ProOptions,
|
ProOptions,
|
||||||
ReactFlow,
|
ReactFlow,
|
||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import { useIsValidConnection } from '../hooks/useIsValidConnection';
|
import { useIsValidConnection } from '../../hooks/useIsValidConnection';
|
||||||
import {
|
import {
|
||||||
connectionEnded,
|
connectionEnded,
|
||||||
connectionMade,
|
connectionMade,
|
||||||
@ -32,18 +32,32 @@ import {
|
|||||||
selectionCopied,
|
selectionCopied,
|
||||||
selectionPasted,
|
selectionPasted,
|
||||||
viewportChanged,
|
viewportChanged,
|
||||||
} from '../store/nodesSlice';
|
} from '../../store/nodesSlice';
|
||||||
import { CustomConnectionLine } from './CustomConnectionLine';
|
import CustomConnectionLine from './connectionLines/CustomConnectionLine';
|
||||||
import { edgeTypes } from './CustomEdges';
|
import InvocationCollapsedEdge from './edges/InvocationCollapsedEdge';
|
||||||
import { nodeTypes } from './CustomNodes';
|
import InvocationDefaultEdge from './edges/InvocationDefaultEdge';
|
||||||
import BottomLeftPanel from './editorPanels/BottomLeftPanel';
|
import CurrentImageNode from './nodes/CurrentImage/CurrentImageNode';
|
||||||
import MinimapPanel from './editorPanels/MinimapPanel';
|
import InvocationNodeWrapper from './nodes/Invocation/InvocationNodeWrapper';
|
||||||
import TopCenterPanel from './editorPanels/TopCenterPanel';
|
import NotesNode from './nodes/Notes/NotesNode';
|
||||||
import TopLeftPanel from './editorPanels/TopLeftPanel';
|
import BottomLeftPanel from './panels/BottomLeftPanel/BottomLeftPanel';
|
||||||
import TopRightPanel from './editorPanels/TopRightPanel';
|
import MinimapPanel from './panels/MinimapPanel/MinimapPanel';
|
||||||
|
import TopCenterPanel from './panels/TopCenterPanel/TopCenterPanel';
|
||||||
|
import TopLeftPanel from './panels/TopLeftPanel/TopLeftPanel';
|
||||||
|
import TopRightPanel from './panels/TopRightPanel/TopRightPanel';
|
||||||
|
|
||||||
const DELETE_KEYS = ['Delete', 'Backspace'];
|
const DELETE_KEYS = ['Delete', 'Backspace'];
|
||||||
|
|
||||||
|
const edgeTypes = {
|
||||||
|
collapsed: InvocationCollapsedEdge,
|
||||||
|
default: InvocationDefaultEdge,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nodeTypes = {
|
||||||
|
invocation: InvocationNodeWrapper,
|
||||||
|
current_image: CurrentImageNode,
|
||||||
|
notes: NotesNode,
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
|
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
|
||||||
const proOptions: ProOptions = { hideAttribution: true };
|
const proOptions: ProOptions = { hideAttribution: true };
|
||||||
|
|
@ -2,7 +2,8 @@ import { createSelector } from '@reduxjs/toolkit';
|
|||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { ConnectionLineComponentProps, getBezierPath } from 'reactflow';
|
import { ConnectionLineComponentProps, getBezierPath } from 'reactflow';
|
||||||
import { FIELDS, colorTokenToCssVar } from '../types/constants';
|
import { FIELDS, colorTokenToCssVar } from '../../../types/constants';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
const selector = createSelector(stateSelector, ({ nodes }) => {
|
const selector = createSelector(stateSelector, ({ nodes }) => {
|
||||||
const { shouldAnimateEdges, currentConnectionFieldType, shouldColorEdges } =
|
const { shouldAnimateEdges, currentConnectionFieldType, shouldColorEdges } =
|
||||||
@ -25,7 +26,7 @@ const selector = createSelector(stateSelector, ({ nodes }) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CustomConnectionLine = ({
|
const CustomConnectionLine = ({
|
||||||
fromX,
|
fromX,
|
||||||
fromY,
|
fromY,
|
||||||
fromPosition,
|
fromPosition,
|
||||||
@ -59,3 +60,5 @@ export const CustomConnectionLine = ({
|
|||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default memo(CustomConnectionLine);
|
@ -0,0 +1,94 @@
|
|||||||
|
import { Badge, Flex } from '@chakra-ui/react';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||||
|
import { memo, useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
BaseEdge,
|
||||||
|
EdgeLabelRenderer,
|
||||||
|
EdgeProps,
|
||||||
|
getBezierPath,
|
||||||
|
} from 'reactflow';
|
||||||
|
import { makeEdgeSelector } from './util/makeEdgeSelector';
|
||||||
|
|
||||||
|
const InvocationCollapsedEdge = ({
|
||||||
|
sourceX,
|
||||||
|
sourceY,
|
||||||
|
targetX,
|
||||||
|
targetY,
|
||||||
|
sourcePosition,
|
||||||
|
targetPosition,
|
||||||
|
markerEnd,
|
||||||
|
data,
|
||||||
|
selected,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
sourceHandleId,
|
||||||
|
targetHandleId,
|
||||||
|
}: EdgeProps<{ count: number }>) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
makeEdgeSelector(
|
||||||
|
source,
|
||||||
|
sourceHandleId,
|
||||||
|
target,
|
||||||
|
targetHandleId,
|
||||||
|
selected
|
||||||
|
),
|
||||||
|
[selected, source, sourceHandleId, target, targetHandleId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { isSelected, shouldAnimate } = useAppSelector(selector);
|
||||||
|
|
||||||
|
const [edgePath, labelX, labelY] = getBezierPath({
|
||||||
|
sourceX,
|
||||||
|
sourceY,
|
||||||
|
sourcePosition,
|
||||||
|
targetX,
|
||||||
|
targetY,
|
||||||
|
targetPosition,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { base500 } = useChakraThemeTokens();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseEdge
|
||||||
|
path={edgePath}
|
||||||
|
markerEnd={markerEnd}
|
||||||
|
style={{
|
||||||
|
strokeWidth: isSelected ? 3 : 2,
|
||||||
|
stroke: base500,
|
||||||
|
opacity: isSelected ? 0.8 : 0.5,
|
||||||
|
animation: shouldAnimate
|
||||||
|
? 'dashdraw 0.5s linear infinite'
|
||||||
|
: undefined,
|
||||||
|
strokeDasharray: shouldAnimate ? 5 : 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{data?.count && data.count > 1 && (
|
||||||
|
<EdgeLabelRenderer>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
||||||
|
}}
|
||||||
|
className="nodrag nopan"
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
variant="solid"
|
||||||
|
sx={{
|
||||||
|
bg: 'base.500',
|
||||||
|
opacity: isSelected ? 0.8 : 0.5,
|
||||||
|
boxShadow: 'base',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.count}
|
||||||
|
</Badge>
|
||||||
|
</Flex>
|
||||||
|
</EdgeLabelRenderer>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(InvocationCollapsedEdge);
|
@ -0,0 +1,58 @@
|
|||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { memo, useMemo } from 'react';
|
||||||
|
import { BaseEdge, EdgeProps, getBezierPath } from 'reactflow';
|
||||||
|
import { makeEdgeSelector } from './util/makeEdgeSelector';
|
||||||
|
|
||||||
|
const InvocationDefaultEdge = ({
|
||||||
|
sourceX,
|
||||||
|
sourceY,
|
||||||
|
targetX,
|
||||||
|
targetY,
|
||||||
|
sourcePosition,
|
||||||
|
targetPosition,
|
||||||
|
markerEnd,
|
||||||
|
selected,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
sourceHandleId,
|
||||||
|
targetHandleId,
|
||||||
|
}: EdgeProps) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
makeEdgeSelector(
|
||||||
|
source,
|
||||||
|
sourceHandleId,
|
||||||
|
target,
|
||||||
|
targetHandleId,
|
||||||
|
selected
|
||||||
|
),
|
||||||
|
[source, sourceHandleId, target, targetHandleId, selected]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { isSelected, shouldAnimate, stroke } = useAppSelector(selector);
|
||||||
|
|
||||||
|
const [edgePath] = getBezierPath({
|
||||||
|
sourceX,
|
||||||
|
sourceY,
|
||||||
|
sourcePosition,
|
||||||
|
targetX,
|
||||||
|
targetY,
|
||||||
|
targetPosition,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseEdge
|
||||||
|
path={edgePath}
|
||||||
|
markerEnd={markerEnd}
|
||||||
|
style={{
|
||||||
|
strokeWidth: isSelected ? 3 : 2,
|
||||||
|
stroke,
|
||||||
|
opacity: isSelected ? 0.8 : 0.5,
|
||||||
|
animation: shouldAnimate ? 'dashdraw 0.5s linear infinite' : undefined,
|
||||||
|
strokeDasharray: shouldAnimate ? 5 : 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(InvocationDefaultEdge);
|
@ -0,0 +1,41 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { FIELDS, colorTokenToCssVar } from 'features/nodes/types/constants';
|
||||||
|
import { isInvocationNode } from 'features/nodes/types/types';
|
||||||
|
|
||||||
|
export const makeEdgeSelector = (
|
||||||
|
source: string,
|
||||||
|
sourceHandleId: string | null | undefined,
|
||||||
|
target: string,
|
||||||
|
targetHandleId: string | null | undefined,
|
||||||
|
selected?: boolean
|
||||||
|
) =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const sourceNode = nodes.nodes.find((node) => node.id === source);
|
||||||
|
const targetNode = nodes.nodes.find((node) => node.id === target);
|
||||||
|
|
||||||
|
const isInvocationToInvocationEdge =
|
||||||
|
isInvocationNode(sourceNode) && isInvocationNode(targetNode);
|
||||||
|
|
||||||
|
const isSelected =
|
||||||
|
sourceNode?.selected || targetNode?.selected || selected;
|
||||||
|
const sourceType = isInvocationToInvocationEdge
|
||||||
|
? sourceNode?.data?.outputs[sourceHandleId || '']?.type
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const stroke =
|
||||||
|
sourceType && nodes.shouldColorEdges
|
||||||
|
? colorTokenToCssVar(FIELDS[sourceType].color)
|
||||||
|
: colorTokenToCssVar('base.500');
|
||||||
|
|
||||||
|
return {
|
||||||
|
isSelected,
|
||||||
|
shouldAnimate: nodes.shouldAnimateEdges && isSelected,
|
||||||
|
stroke,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
);
|
@ -7,7 +7,7 @@ import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
|||||||
import { PropsWithChildren, memo } from 'react';
|
import { PropsWithChildren, memo } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { NodeProps } from 'reactflow';
|
import { NodeProps } from 'reactflow';
|
||||||
import NodeWrapper from '../Invocation/NodeWrapper';
|
import NodeWrapper from '../common/NodeWrapper';
|
||||||
|
|
||||||
const selector = createSelector(stateSelector, ({ system, gallery }) => {
|
const selector = createSelector(stateSelector, ({ system, gallery }) => {
|
||||||
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
@ -1,11 +1,12 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
import { useFieldNames, useWithFooter } from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import InputField from '../fields/InputField';
|
import InvocationNodeFooter from './InvocationNodeFooter';
|
||||||
import OutputField from '../fields/OutputField';
|
import InvocationNodeHeader from './InvocationNodeHeader';
|
||||||
import NodeFooter from './NodeFooter';
|
import NodeWrapper from '../common/NodeWrapper';
|
||||||
import NodeHeader from './NodeHeader';
|
import OutputField from './fields/OutputField';
|
||||||
import NodeWrapper from './NodeWrapper';
|
import InputField from './fields/InputField';
|
||||||
|
import { useFieldNames } from 'features/nodes/hooks/useFieldNames';
|
||||||
|
import { useWithFooter } from 'features/nodes/hooks/useWithFooter';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
@ -22,7 +23,7 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeWrapper nodeId={nodeId} selected={selected}>
|
<NodeWrapper nodeId={nodeId} selected={selected}>
|
||||||
<NodeHeader
|
<InvocationNodeHeader
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
label={label}
|
label={label}
|
||||||
@ -59,7 +60,7 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
|||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
{withFooter && <NodeFooter nodeId={nodeId} />}
|
{withFooter && <InvocationNodeFooter nodeId={nodeId} />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</NodeWrapper>
|
</NodeWrapper>
|
@ -10,7 +10,7 @@ interface Props {
|
|||||||
nodeId: string;
|
nodeId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeCollapsedHandles = ({ nodeId }: Props) => {
|
const InvocationNodeCollapsedHandles = ({ nodeId }: Props) => {
|
||||||
const data = useNodeData(nodeId);
|
const data = useNodeData(nodeId);
|
||||||
const { base400, base600 } = useChakraThemeTokens();
|
const { base400, base600 } = useChakraThemeTokens();
|
||||||
const backgroundColor = useColorModeValue(base400, base600);
|
const backgroundColor = useColorModeValue(base400, base600);
|
||||||
@ -71,4 +71,4 @@ const NodeCollapsedHandles = ({ nodeId }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeCollapsedHandles);
|
export default memo(InvocationNodeCollapsedHandles);
|
@ -6,10 +6,8 @@ import {
|
|||||||
Spacer,
|
Spacer,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import {
|
import { useHasImageOutput } from 'features/nodes/hooks/useHasImageOutput';
|
||||||
useHasImageOutput,
|
import { useIsIntermediate } from 'features/nodes/hooks/useIsIntermediate';
|
||||||
useIsIntermediate,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { fieldBooleanValueChanged } from 'features/nodes/store/nodesSlice';
|
import { fieldBooleanValueChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
@ -18,7 +16,7 @@ type Props = {
|
|||||||
nodeId: string;
|
nodeId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeFooter = ({ nodeId }: Props) => {
|
const InvocationNodeFooter = ({ nodeId }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
className={DRAG_HANDLE_CLASSNAME}
|
className={DRAG_HANDLE_CLASSNAME}
|
||||||
@ -37,7 +35,7 @@ const NodeFooter = ({ nodeId }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeFooter);
|
export default memo(InvocationNodeFooter);
|
||||||
|
|
||||||
const SaveImageCheckbox = memo(({ nodeId }: { nodeId: string }) => {
|
const SaveImageCheckbox = memo(({ nodeId }: { nodeId: string }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
@ -1,10 +1,10 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import NodeCollapseButton from '../Invocation/NodeCollapseButton';
|
import NodeCollapseButton from '../common/NodeCollapseButton';
|
||||||
import NodeCollapsedHandles from '../Invocation/NodeCollapsedHandles';
|
import NodeTitle from '../common/NodeTitle';
|
||||||
import NodeNotesEdit from '../Invocation/NodeNotesEdit';
|
import InvocationNodeCollapsedHandles from './InvocationNodeCollapsedHandles';
|
||||||
import NodeStatusIndicator from '../Invocation/NodeStatusIndicator';
|
import InvocationNodeNotes from './InvocationNodeNotes';
|
||||||
import NodeTitle from '../Invocation/NodeTitle';
|
import InvocationNodeStatusIndicator from './InvocationNodeStatusIndicator';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
@ -14,7 +14,7 @@ type Props = {
|
|||||||
selected: boolean;
|
selected: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeHeader = ({ nodeId, isOpen }: Props) => {
|
const InvocationNodeHeader = ({ nodeId, isOpen }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
layerStyle="nodeHeader"
|
layerStyle="nodeHeader"
|
||||||
@ -33,12 +33,12 @@ const NodeHeader = ({ nodeId, isOpen }: Props) => {
|
|||||||
<NodeCollapseButton nodeId={nodeId} isOpen={isOpen} />
|
<NodeCollapseButton nodeId={nodeId} isOpen={isOpen} />
|
||||||
<NodeTitle nodeId={nodeId} />
|
<NodeTitle nodeId={nodeId} />
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
<NodeStatusIndicator nodeId={nodeId} />
|
<InvocationNodeStatusIndicator nodeId={nodeId} />
|
||||||
<NodeNotesEdit nodeId={nodeId} />
|
<InvocationNodeNotes nodeId={nodeId} />
|
||||||
</Flex>
|
</Flex>
|
||||||
{!isOpen && <NodeCollapsedHandles nodeId={nodeId} />}
|
{!isOpen && <InvocationNodeCollapsedHandles nodeId={nodeId} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeHeader);
|
export default memo(InvocationNodeHeader);
|
@ -16,12 +16,10 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import IAITextarea from 'common/components/IAITextarea';
|
import IAITextarea from 'common/components/IAITextarea';
|
||||||
import {
|
import { useNodeData } from 'features/nodes/hooks/useNodeData';
|
||||||
useNodeData,
|
import { useNodeLabel } from 'features/nodes/hooks/useNodeLabel';
|
||||||
useNodeLabel,
|
import { useNodeTemplate } from 'features/nodes/hooks/useNodeTemplate';
|
||||||
useNodeTemplate,
|
import { useNodeTemplateTitle } from 'features/nodes/hooks/useNodeTemplateTitle';
|
||||||
useNodeTemplateTitle,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { nodeNotesChanged } from 'features/nodes/store/nodesSlice';
|
import { nodeNotesChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import { isInvocationNodeData } from 'features/nodes/types/types';
|
import { isInvocationNodeData } from 'features/nodes/types/types';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
@ -31,7 +29,7 @@ interface Props {
|
|||||||
nodeId: string;
|
nodeId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeNotesEdit = ({ nodeId }: Props) => {
|
const InvocationNodeNotes = ({ nodeId }: Props) => {
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const label = useNodeLabel(nodeId);
|
const label = useNodeLabel(nodeId);
|
||||||
const title = useNodeTemplateTitle(nodeId);
|
const title = useNodeTemplateTitle(nodeId);
|
||||||
@ -76,7 +74,7 @@ const NodeNotesEdit = ({ nodeId }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeNotesEdit);
|
export default memo(InvocationNodeNotes);
|
||||||
|
|
||||||
const TooltipContent = memo(({ nodeId }: { nodeId: string }) => {
|
const TooltipContent = memo(({ nodeId }: { nodeId: string }) => {
|
||||||
const data = useNodeData(nodeId);
|
const data = useNodeData(nodeId);
|
@ -28,7 +28,7 @@ const circleStyles = {
|
|||||||
'.chakra-progress__track': { stroke: 'transparent' },
|
'.chakra-progress__track': { stroke: 'transparent' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeStatusIndicator = ({ nodeId }: Props) => {
|
const InvocationNodeStatusIndicator = ({ nodeId }: Props) => {
|
||||||
const selectNodeExecutionState = useMemo(
|
const selectNodeExecutionState = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createSelector(
|
createSelector(
|
||||||
@ -64,7 +64,7 @@ const NodeStatusIndicator = ({ nodeId }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeStatusIndicator);
|
export default memo(InvocationNodeStatusIndicator);
|
||||||
|
|
||||||
type TooltipLabelProps = {
|
type TooltipLabelProps = {
|
||||||
nodeExecutionState: NodeExecutionState;
|
nodeExecutionState: NodeExecutionState;
|
@ -1,8 +1,8 @@
|
|||||||
import { Box, Flex, Text } from '@chakra-ui/react';
|
import { Box, Flex, Text } from '@chakra-ui/react';
|
||||||
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import NodeCollapseButton from '../Invocation/NodeCollapseButton';
|
import NodeCollapseButton from '../common/NodeCollapseButton';
|
||||||
import NodeWrapper from '../Invocation/NodeWrapper';
|
import NodeWrapper from '../common/NodeWrapper';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
@ -12,7 +12,7 @@ type Props = {
|
|||||||
selected: boolean;
|
selected: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UnknownNodeFallback = ({
|
const InvocationNodeUnknownFallback = ({
|
||||||
nodeId,
|
nodeId,
|
||||||
isOpen,
|
isOpen,
|
||||||
label,
|
label,
|
||||||
@ -72,4 +72,4 @@ const UnknownNodeFallback = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(UnknownNodeFallback);
|
export default memo(InvocationNodeUnknownFallback);
|
@ -5,7 +5,7 @@ import { InvocationNodeData } from 'features/nodes/types/types';
|
|||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { NodeProps } from 'reactflow';
|
import { NodeProps } from 'reactflow';
|
||||||
import InvocationNode from '../Invocation/InvocationNode';
|
import InvocationNode from '../Invocation/InvocationNode';
|
||||||
import UnknownNodeFallback from '../Invocation/UnknownNodeFallback';
|
import InvocationNodeUnknownFallback from './InvocationNodeUnknownFallback';
|
||||||
|
|
||||||
const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
||||||
const { data, selected } = props;
|
const { data, selected } = props;
|
||||||
@ -23,7 +23,7 @@ const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
|||||||
|
|
||||||
if (!nodeTemplate) {
|
if (!nodeTemplate) {
|
||||||
return (
|
return (
|
||||||
<UnknownNodeFallback
|
<InvocationNodeUnknownFallback
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
label={label}
|
label={label}
|
@ -7,11 +7,9 @@ import {
|
|||||||
IAIContextMenu,
|
IAIContextMenu,
|
||||||
IAIContextMenuProps,
|
IAIContextMenuProps,
|
||||||
} from 'common/components/IAIContextMenu';
|
} from 'common/components/IAIContextMenu';
|
||||||
import {
|
import { useFieldInputKind } from 'features/nodes/hooks/useFieldInputKind';
|
||||||
useFieldInputKind,
|
import { useFieldLabel } from 'features/nodes/hooks/useFieldLabel';
|
||||||
useFieldLabel,
|
import { useFieldTemplateTitle } from 'features/nodes/hooks/useFieldTemplateTitle';
|
||||||
useFieldTemplateTitle,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import {
|
import {
|
||||||
workflowExposedFieldAdded,
|
workflowExposedFieldAdded,
|
||||||
workflowExposedFieldRemoved,
|
workflowExposedFieldRemoved,
|
||||||
@ -31,6 +29,7 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const label = useFieldLabel(nodeId, fieldName);
|
const label = useFieldLabel(nodeId, fieldName);
|
||||||
const fieldTemplateTitle = useFieldTemplateTitle(nodeId, fieldName, kind);
|
const fieldTemplateTitle = useFieldTemplateTitle(nodeId, fieldName, kind);
|
||||||
|
const input = useFieldInputKind(nodeId, fieldName);
|
||||||
|
|
||||||
const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => {
|
const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -54,7 +53,6 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
|||||||
[fieldName, nodeId]
|
[fieldName, nodeId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const input = useFieldInputKind(nodeId, fieldName);
|
|
||||||
const mayExpose = useMemo(
|
const mayExpose = useMemo(
|
||||||
() => ['any', 'direct'].includes(input ?? '__UNKNOWN_INPUT__'),
|
() => ['any', 'direct'].includes(input ?? '__UNKNOWN_INPUT__'),
|
||||||
[input]
|
[input]
|
@ -5,8 +5,11 @@ import {
|
|||||||
FIELDS,
|
FIELDS,
|
||||||
HANDLE_TOOLTIP_OPEN_DELAY,
|
HANDLE_TOOLTIP_OPEN_DELAY,
|
||||||
colorTokenToCssVar,
|
colorTokenToCssVar,
|
||||||
} from '../../types/constants';
|
} from '../../../../../types/constants';
|
||||||
import { InputFieldTemplate, OutputFieldTemplate } from '../../types/types';
|
import {
|
||||||
|
InputFieldTemplate,
|
||||||
|
OutputFieldTemplate,
|
||||||
|
} from '../../../../../types/types';
|
||||||
|
|
||||||
export const handleBaseStyles: CSSProperties = {
|
export const handleBaseStyles: CSSProperties = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
@ -7,10 +7,8 @@ import {
|
|||||||
useEditableControls,
|
useEditableControls,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import {
|
import { useFieldLabel } from 'features/nodes/hooks/useFieldLabel';
|
||||||
useFieldLabel,
|
import { useFieldTemplateTitle } from 'features/nodes/hooks/useFieldTemplateTitle';
|
||||||
useFieldTemplateTitle,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { fieldLabelChanged } from 'features/nodes/store/nodesSlice';
|
import { fieldLabelChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import { MouseEvent, memo, useCallback, useEffect, useState } from 'react';
|
import { MouseEvent, memo, useCallback, useEffect, useState } from 'react';
|
||||||
|
|
@ -1,8 +1,6 @@
|
|||||||
import { Flex, Text } from '@chakra-ui/react';
|
import { Flex, Text } from '@chakra-ui/react';
|
||||||
import {
|
import { useFieldData } from 'features/nodes/hooks/useFieldData';
|
||||||
useFieldData,
|
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
|
||||||
useFieldTemplate,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { FIELDS } from 'features/nodes/types/constants';
|
import { FIELDS } from 'features/nodes/types/constants';
|
||||||
import {
|
import {
|
||||||
isInputFieldTemplate,
|
isInputFieldTemplate,
|
@ -1,14 +1,12 @@
|
|||||||
import { Box, Flex, FormControl, FormLabel, Tooltip } from '@chakra-ui/react';
|
import { Box, Flex, FormControl, FormLabel, Tooltip } from '@chakra-ui/react';
|
||||||
import SelectionOverlay from 'common/components/SelectionOverlay';
|
import SelectionOverlay from 'common/components/SelectionOverlay';
|
||||||
import { useConnectionState } from 'features/nodes/hooks/useConnectionState';
|
import { useConnectionState } from 'features/nodes/hooks/useConnectionState';
|
||||||
import {
|
import { useDoesInputHaveValue } from 'features/nodes/hooks/useDoesInputHaveValue';
|
||||||
useDoesInputHaveValue,
|
import { useFieldInputKind } from 'features/nodes/hooks/useFieldInputKind';
|
||||||
useFieldInputKind,
|
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
|
||||||
useFieldTemplate,
|
import { useIsMouseOverField } from 'features/nodes/hooks/useIsMouseOverField';
|
||||||
useIsMouseOverField,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
||||||
import { PropsWithChildren, memo, useCallback, useMemo, useState } from 'react';
|
import { PropsWithChildren, memo, useMemo } from 'react';
|
||||||
import FieldContextMenu from './FieldContextMenu';
|
import FieldContextMenu from './FieldContextMenu';
|
||||||
import FieldHandle from './FieldHandle';
|
import FieldHandle from './FieldHandle';
|
||||||
import FieldTitle from './FieldTitle';
|
import FieldTitle from './FieldTitle';
|
||||||
@ -24,15 +22,6 @@ const InputField = ({ nodeId, fieldName }: Props) => {
|
|||||||
const fieldTemplate = useFieldTemplate(nodeId, fieldName, 'input');
|
const fieldTemplate = useFieldTemplate(nodeId, fieldName, 'input');
|
||||||
const doesFieldHaveValue = useDoesInputHaveValue(nodeId, fieldName);
|
const doesFieldHaveValue = useDoesInputHaveValue(nodeId, fieldName);
|
||||||
const input = useFieldInputKind(nodeId, fieldName);
|
const input = useFieldInputKind(nodeId, fieldName);
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
|
||||||
|
|
||||||
const handleMouseOver = useCallback(() => {
|
|
||||||
setIsHovered(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleMouseOut = useCallback(() => {
|
|
||||||
setIsHovered(false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isConnected,
|
isConnected,
|
@ -1,31 +1,29 @@
|
|||||||
import { Box, Text } from '@chakra-ui/react';
|
import { Box, Text } from '@chakra-ui/react';
|
||||||
import {
|
import { useFieldData } from 'features/nodes/hooks/useFieldData';
|
||||||
useFieldData,
|
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
|
||||||
useFieldTemplate,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import BooleanInputField from './fieldTypes/BooleanInputField';
|
import BooleanInputField from './inputs/BooleanInputField';
|
||||||
import ClipInputField from './fieldTypes/ClipInputField';
|
import ClipInputField from './inputs/ClipInputField';
|
||||||
import CollectionInputField from './fieldTypes/CollectionInputField';
|
import CollectionInputField from './inputs/CollectionInputField';
|
||||||
import CollectionItemInputField from './fieldTypes/CollectionItemInputField';
|
import CollectionItemInputField from './inputs/CollectionItemInputField';
|
||||||
import ColorInputField from './fieldTypes/ColorInputField';
|
import ColorInputField from './inputs/ColorInputField';
|
||||||
import ConditioningInputField from './fieldTypes/ConditioningInputField';
|
import ConditioningInputField from './inputs/ConditioningInputField';
|
||||||
import ControlInputField from './fieldTypes/ControlInputField';
|
import ControlInputField from './inputs/ControlInputField';
|
||||||
import ControlNetModelInputField from './fieldTypes/ControlNetModelInputField';
|
import ControlNetModelInputField from './inputs/ControlNetModelInputField';
|
||||||
import EnumInputField from './fieldTypes/EnumInputField';
|
import EnumInputField from './inputs/EnumInputField';
|
||||||
import ImageCollectionInputField from './fieldTypes/ImageCollectionInputField';
|
import ImageCollectionInputField from './inputs/ImageCollectionInputField';
|
||||||
import ImageInputField from './fieldTypes/ImageInputField';
|
import ImageInputField from './inputs/ImageInputField';
|
||||||
import LatentsInputField from './fieldTypes/LatentsInputField';
|
import LatentsInputField from './inputs/LatentsInputField';
|
||||||
import LoRAModelInputField from './fieldTypes/LoRAModelInputField';
|
import LoRAModelInputField from './inputs/LoRAModelInputField';
|
||||||
import MainModelInputField from './fieldTypes/MainModelInputField';
|
import MainModelInputField from './inputs/MainModelInputField';
|
||||||
import NumberInputField from './fieldTypes/NumberInputField';
|
import NumberInputField from './inputs/NumberInputField';
|
||||||
import RefinerModelInputField from './fieldTypes/RefinerModelInputField';
|
import RefinerModelInputField from './inputs/RefinerModelInputField';
|
||||||
import SDXLMainModelInputField from './fieldTypes/SDXLMainModelInputField';
|
import SDXLMainModelInputField from './inputs/SDXLMainModelInputField';
|
||||||
import SchedulerInputField from './fieldTypes/SchedulerInputField';
|
import SchedulerInputField from './inputs/SchedulerInputField';
|
||||||
import StringInputField from './fieldTypes/StringInputField';
|
import StringInputField from './inputs/StringInputField';
|
||||||
import UnetInputField from './fieldTypes/UnetInputField';
|
import UnetInputField from './inputs/UnetInputField';
|
||||||
import VaeInputField from './fieldTypes/VaeInputField';
|
import VaeInputField from './inputs/VaeInputField';
|
||||||
import VaeModelInputField from './fieldTypes/VaeModelInputField';
|
import VaeModelInputField from './inputs/VaeModelInputField';
|
||||||
|
|
||||||
type InputFieldProps = {
|
type InputFieldProps = {
|
||||||
nodeId: string;
|
nodeId: string;
|
@ -2,7 +2,7 @@ import { Flex, FormControl, FormLabel, Icon, Tooltip } from '@chakra-ui/react';
|
|||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
import SelectionOverlay from 'common/components/SelectionOverlay';
|
import SelectionOverlay from 'common/components/SelectionOverlay';
|
||||||
import { useIsMouseOverField } from 'features/nodes/hooks/useNodeData';
|
import { useIsMouseOverField } from 'features/nodes/hooks/useIsMouseOverField';
|
||||||
import { workflowExposedFieldRemoved } from 'features/nodes/store/nodesSlice';
|
import { workflowExposedFieldRemoved } from 'features/nodes/store/nodesSlice';
|
||||||
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
@ -6,7 +6,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useConnectionState } from 'features/nodes/hooks/useConnectionState';
|
import { useConnectionState } from 'features/nodes/hooks/useConnectionState';
|
||||||
import { useFieldTemplate } from 'features/nodes/hooks/useNodeData';
|
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
|
||||||
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
||||||
import { PropsWithChildren, memo } from 'react';
|
import { PropsWithChildren, memo } from 'react';
|
||||||
import FieldHandle from './FieldHandle';
|
import FieldHandle from './FieldHandle';
|
@ -4,9 +4,9 @@ import { fieldBooleanValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
BooleanInputFieldTemplate,
|
BooleanInputFieldTemplate,
|
||||||
BooleanInputFieldValue,
|
BooleanInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const BooleanInputFieldComponent = (
|
const BooleanInputFieldComponent = (
|
||||||
props: FieldComponentProps<BooleanInputFieldValue, BooleanInputFieldTemplate>
|
props: FieldComponentProps<BooleanInputFieldValue, BooleanInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
ClipInputFieldTemplate,
|
ClipInputFieldTemplate,
|
||||||
ClipInputFieldValue,
|
ClipInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ClipInputFieldComponent = (
|
const ClipInputFieldComponent = (
|
||||||
_props: FieldComponentProps<ClipInputFieldValue, ClipInputFieldTemplate>
|
_props: FieldComponentProps<ClipInputFieldValue, ClipInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
CollectionInputFieldTemplate,
|
CollectionInputFieldTemplate,
|
||||||
CollectionInputFieldValue,
|
CollectionInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const CollectionInputFieldComponent = (
|
const CollectionInputFieldComponent = (
|
||||||
_props: FieldComponentProps<
|
_props: FieldComponentProps<
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
CollectionItemInputFieldTemplate,
|
CollectionItemInputFieldTemplate,
|
||||||
CollectionItemInputFieldValue,
|
CollectionItemInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const CollectionItemInputFieldComponent = (
|
const CollectionItemInputFieldComponent = (
|
||||||
_props: FieldComponentProps<
|
_props: FieldComponentProps<
|
@ -3,10 +3,10 @@ import { fieldColorValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
ColorInputFieldTemplate,
|
ColorInputFieldTemplate,
|
||||||
ColorInputFieldValue,
|
ColorInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { RgbaColor, RgbaColorPicker } from 'react-colorful';
|
import { RgbaColor, RgbaColorPicker } from 'react-colorful';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ColorInputFieldComponent = (
|
const ColorInputFieldComponent = (
|
||||||
props: FieldComponentProps<ColorInputFieldValue, ColorInputFieldTemplate>
|
props: FieldComponentProps<ColorInputFieldValue, ColorInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
ConditioningInputFieldTemplate,
|
ConditioningInputFieldTemplate,
|
||||||
ConditioningInputFieldValue,
|
ConditioningInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ConditioningInputFieldComponent = (
|
const ConditioningInputFieldComponent = (
|
||||||
_props: FieldComponentProps<
|
_props: FieldComponentProps<
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
ControlInputFieldTemplate,
|
ControlInputFieldTemplate,
|
||||||
ControlInputFieldValue,
|
ControlInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ControlInputFieldComponent = (
|
const ControlInputFieldComponent = (
|
||||||
_props: FieldComponentProps<ControlInputFieldValue, ControlInputFieldTemplate>
|
_props: FieldComponentProps<ControlInputFieldValue, ControlInputFieldTemplate>
|
@ -5,13 +5,13 @@ import { fieldControlNetModelValueChanged } from 'features/nodes/store/nodesSlic
|
|||||||
import {
|
import {
|
||||||
ControlNetModelInputFieldTemplate,
|
ControlNetModelInputFieldTemplate,
|
||||||
ControlNetModelInputFieldValue,
|
ControlNetModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToControlNetModelParam } from 'features/parameters/util/modelIdToControlNetModelParam';
|
import { modelIdToControlNetModelParam } from 'features/parameters/util/modelIdToControlNetModelParam';
|
||||||
import { forEach } from 'lodash-es';
|
import { forEach } from 'lodash-es';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useGetControlNetModelsQuery } from 'services/api/endpoints/models';
|
import { useGetControlNetModelsQuery } from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ControlNetModelInputFieldComponent = (
|
const ControlNetModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -4,9 +4,9 @@ import { fieldEnumModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
EnumInputFieldTemplate,
|
EnumInputFieldTemplate,
|
||||||
EnumInputFieldValue,
|
EnumInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const EnumInputFieldComponent = (
|
const EnumInputFieldComponent = (
|
||||||
props: FieldComponentProps<EnumInputFieldValue, EnumInputFieldTemplate>
|
props: FieldComponentProps<EnumInputFieldValue, EnumInputFieldTemplate>
|
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ImageCollectionInputFieldTemplate,
|
ImageCollectionInputFieldTemplate,
|
||||||
ImageCollectionInputFieldValue,
|
ImageCollectionInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
|
|
||||||
@ -11,7 +12,6 @@ import { useDroppableTypesafe } from 'features/dnd/hooks/typesafeHooks';
|
|||||||
import { NodesMultiImageDropData } from 'features/dnd/types';
|
import { NodesMultiImageDropData } from 'features/dnd/types';
|
||||||
import { isValidDrop } from 'features/dnd/util/isValidDrop';
|
import { isValidDrop } from 'features/dnd/util/isValidDrop';
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ImageCollectionInputFieldComponent = (
|
const ImageCollectionInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -11,12 +11,12 @@ import { fieldImageValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
ImageInputFieldTemplate,
|
ImageInputFieldTemplate,
|
||||||
ImageInputFieldValue,
|
ImageInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { FaUndo } from 'react-icons/fa';
|
import { FaUndo } from 'react-icons/fa';
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import { PostUploadAction } from 'services/api/types';
|
import { PostUploadAction } from 'services/api/types';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ImageInputFieldComponent = (
|
const ImageInputFieldComponent = (
|
||||||
props: FieldComponentProps<ImageInputFieldValue, ImageInputFieldTemplate>
|
props: FieldComponentProps<ImageInputFieldValue, ImageInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
LatentsInputFieldTemplate,
|
LatentsInputFieldTemplate,
|
||||||
LatentsInputFieldValue,
|
LatentsInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const LatentsInputFieldComponent = (
|
const LatentsInputFieldComponent = (
|
||||||
_props: FieldComponentProps<LatentsInputFieldValue, LatentsInputFieldTemplate>
|
_props: FieldComponentProps<LatentsInputFieldValue, LatentsInputFieldTemplate>
|
@ -7,13 +7,13 @@ import { fieldLoRAModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
LoRAModelInputFieldTemplate,
|
LoRAModelInputFieldTemplate,
|
||||||
LoRAModelInputFieldValue,
|
LoRAModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToLoRAModelParam } from 'features/parameters/util/modelIdToLoRAModelParam';
|
import { modelIdToLoRAModelParam } from 'features/parameters/util/modelIdToLoRAModelParam';
|
||||||
import { forEach } from 'lodash-es';
|
import { forEach } from 'lodash-es';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
|
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const LoRAModelInputFieldComponent = (
|
const LoRAModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -6,6 +6,7 @@ import { fieldMainModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
MainModelInputFieldTemplate,
|
MainModelInputFieldTemplate,
|
||||||
MainModelInputFieldValue,
|
MainModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
||||||
@ -18,7 +19,6 @@ import {
|
|||||||
useGetMainModelsQuery,
|
useGetMainModelsQuery,
|
||||||
useGetOnnxModelsQuery,
|
useGetOnnxModelsQuery,
|
||||||
} from 'services/api/endpoints/models';
|
} from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const MainModelInputFieldComponent = (
|
const MainModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -13,9 +13,9 @@ import {
|
|||||||
FloatInputFieldValue,
|
FloatInputFieldValue,
|
||||||
IntegerInputFieldTemplate,
|
IntegerInputFieldTemplate,
|
||||||
IntegerInputFieldValue,
|
IntegerInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo, useEffect, useMemo, useState } from 'react';
|
import { memo, useEffect, useMemo, useState } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const NumberInputFieldComponent = (
|
const NumberInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -6,6 +6,7 @@ import { fieldRefinerModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
SDXLRefinerModelInputFieldTemplate,
|
SDXLRefinerModelInputFieldTemplate,
|
||||||
SDXLRefinerModelInputFieldValue,
|
SDXLRefinerModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
||||||
@ -16,7 +17,6 @@ import { memo, useCallback, useMemo } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { REFINER_BASE_MODELS } from 'services/api/constants';
|
import { REFINER_BASE_MODELS } from 'services/api/constants';
|
||||||
import { useGetMainModelsQuery } from 'services/api/endpoints/models';
|
import { useGetMainModelsQuery } from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const RefinerModelInputFieldComponent = (
|
const RefinerModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -6,6 +6,7 @@ import { fieldMainModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
SDXLMainModelInputFieldTemplate,
|
SDXLMainModelInputFieldTemplate,
|
||||||
SDXLMainModelInputFieldValue,
|
SDXLMainModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
import { modelIdToMainModelParam } from 'features/parameters/util/modelIdToMainModelParam';
|
||||||
@ -19,7 +20,6 @@ import {
|
|||||||
useGetMainModelsQuery,
|
useGetMainModelsQuery,
|
||||||
useGetOnnxModelsQuery,
|
useGetOnnxModelsQuery,
|
||||||
} from 'services/api/endpoints/models';
|
} from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const ModelInputFieldComponent = (
|
const ModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -7,6 +7,7 @@ import { fieldSchedulerValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
SchedulerInputFieldTemplate,
|
SchedulerInputFieldTemplate,
|
||||||
SchedulerInputFieldValue,
|
SchedulerInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import {
|
import {
|
||||||
SCHEDULER_LABEL_MAP,
|
SCHEDULER_LABEL_MAP,
|
||||||
@ -14,7 +15,6 @@ import {
|
|||||||
} from 'features/parameters/types/parameterSchemas';
|
} from 'features/parameters/types/parameterSchemas';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[stateSelector],
|
[stateSelector],
|
@ -5,9 +5,9 @@ import { fieldStringValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
StringInputFieldTemplate,
|
StringInputFieldTemplate,
|
||||||
StringInputFieldValue,
|
StringInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const StringInputFieldComponent = (
|
const StringInputFieldComponent = (
|
||||||
props: FieldComponentProps<StringInputFieldValue, StringInputFieldTemplate>
|
props: FieldComponentProps<StringInputFieldValue, StringInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
UNetInputFieldTemplate,
|
UNetInputFieldTemplate,
|
||||||
UNetInputFieldValue,
|
UNetInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const UNetInputFieldComponent = (
|
const UNetInputFieldComponent = (
|
||||||
_props: FieldComponentProps<UNetInputFieldValue, UNetInputFieldTemplate>
|
_props: FieldComponentProps<UNetInputFieldValue, UNetInputFieldTemplate>
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
VaeInputFieldTemplate,
|
VaeInputFieldTemplate,
|
||||||
VaeInputFieldValue,
|
VaeInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const VaeInputFieldComponent = (
|
const VaeInputFieldComponent = (
|
||||||
_props: FieldComponentProps<VaeInputFieldValue, VaeInputFieldTemplate>
|
_props: FieldComponentProps<VaeInputFieldValue, VaeInputFieldTemplate>
|
@ -6,13 +6,13 @@ import { fieldVaeModelValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import {
|
import {
|
||||||
VaeModelInputFieldTemplate,
|
VaeModelInputFieldTemplate,
|
||||||
VaeModelInputFieldValue,
|
VaeModelInputFieldValue,
|
||||||
|
FieldComponentProps,
|
||||||
} from 'features/nodes/types/types';
|
} from 'features/nodes/types/types';
|
||||||
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
|
||||||
import { modelIdToVAEModelParam } from 'features/parameters/util/modelIdToVAEModelParam';
|
import { modelIdToVAEModelParam } from 'features/parameters/util/modelIdToVAEModelParam';
|
||||||
import { forEach } from 'lodash-es';
|
import { forEach } from 'lodash-es';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useGetVaeModelsQuery } from 'services/api/endpoints/models';
|
import { useGetVaeModelsQuery } from 'services/api/endpoints/models';
|
||||||
import { FieldComponentProps } from './types';
|
|
||||||
|
|
||||||
const VaeModelInputFieldComponent = (
|
const VaeModelInputFieldComponent = (
|
||||||
props: FieldComponentProps<
|
props: FieldComponentProps<
|
@ -5,9 +5,9 @@ import { notesNodeValueChanged } from 'features/nodes/store/nodesSlice';
|
|||||||
import { NotesNodeData } from 'features/nodes/types/types';
|
import { NotesNodeData } from 'features/nodes/types/types';
|
||||||
import { ChangeEvent, memo, useCallback } from 'react';
|
import { ChangeEvent, memo, useCallback } from 'react';
|
||||||
import { NodeProps } from 'reactflow';
|
import { NodeProps } from 'reactflow';
|
||||||
import NodeCollapseButton from '../Invocation/NodeCollapseButton';
|
import NodeWrapper from '../common/NodeWrapper';
|
||||||
import NodeTitle from '../Invocation/NodeTitle';
|
import NodeCollapseButton from '../common/NodeCollapseButton';
|
||||||
import NodeWrapper from '../Invocation/NodeWrapper';
|
import NodeTitle from '../common/NodeTitle';
|
||||||
|
|
||||||
const NotesNode = (props: NodeProps<NotesNodeData>) => {
|
const NotesNode = (props: NodeProps<NotesNodeData>) => {
|
||||||
const { id: nodeId, data, selected } = props;
|
const { id: nodeId, data, selected } = props;
|
@ -7,10 +7,8 @@ import {
|
|||||||
useEditableControls,
|
useEditableControls,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import {
|
import { useNodeLabel } from 'features/nodes/hooks/useNodeLabel';
|
||||||
useNodeLabel,
|
import { useNodeTemplateTitle } from 'features/nodes/hooks/useNodeTemplateTitle';
|
||||||
useNodeTemplateTitle,
|
|
||||||
} from 'features/nodes/hooks/useNodeData';
|
|
||||||
import { nodeLabelChanged } from 'features/nodes/store/nodesSlice';
|
import { nodeLabelChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||||
import { MouseEvent, memo, useCallback, useEffect, useState } from 'react';
|
import { MouseEvent, memo, useCallback, useEffect, useState } from 'react';
|
@ -5,9 +5,12 @@ import {
|
|||||||
useToken,
|
useToken,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import {
|
||||||
|
DRAG_HANDLE_CLASSNAME,
|
||||||
|
NODE_WIDTH,
|
||||||
|
} from 'features/nodes/types/constants';
|
||||||
import { contextMenusClosed } from 'features/ui/store/uiSlice';
|
import { contextMenusClosed } from 'features/ui/store/uiSlice';
|
||||||
import { PropsWithChildren, memo, useCallback } from 'react';
|
import { PropsWithChildren, memo, useCallback } from 'react';
|
||||||
import { DRAG_HANDLE_CLASSNAME, NODE_WIDTH } from '../../types/constants';
|
|
||||||
|
|
||||||
type NodeWrapperProps = PropsWithChildren & {
|
type NodeWrapperProps = PropsWithChildren & {
|
||||||
nodeId: string;
|
nodeId: string;
|
@ -1,7 +1,7 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Panel } from 'reactflow';
|
import { Panel } from 'reactflow';
|
||||||
import ViewportControls from '../ViewportControls';
|
import ViewportControls from './ViewportControls';
|
||||||
import NodeOpacitySlider from '../NodeOpacitySlider';
|
import NodeOpacitySlider from './NodeOpacitySlider';
|
||||||
import { Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
|
|
||||||
const BottomLeftPanel = () => (
|
const BottomLeftPanel = () => (
|
@ -7,7 +7,7 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { nodeOpacityChanged } from '../store/nodesSlice';
|
import { nodeOpacityChanged } from 'features/nodes/store/nodesSlice';
|
||||||
|
|
||||||
export default function NodeOpacitySlider() {
|
export default function NodeOpacitySlider() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
@ -14,7 +14,7 @@ import { useReactFlow } from 'reactflow';
|
|||||||
import {
|
import {
|
||||||
shouldShowFieldTypeLegendChanged,
|
shouldShowFieldTypeLegendChanged,
|
||||||
shouldShowMinimapPanelChanged,
|
shouldShowMinimapPanelChanged,
|
||||||
} from '../store/nodesSlice';
|
} from 'features/nodes/store/nodesSlice';
|
||||||
|
|
||||||
const ViewportControls = () => {
|
const ViewportControls = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
@ -22,7 +22,7 @@ import {
|
|||||||
shouldColorEdgesChanged,
|
shouldColorEdgesChanged,
|
||||||
shouldSnapToGridChanged,
|
shouldSnapToGridChanged,
|
||||||
shouldValidateGraphChanged,
|
shouldValidateGraphChanged,
|
||||||
} from '../store/nodesSlice';
|
} from 'features/nodes/store/nodesSlice';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
@ -2,10 +2,10 @@ import { HStack } from '@chakra-ui/react';
|
|||||||
import CancelButton from 'features/parameters/components/ProcessButtons/CancelButton';
|
import CancelButton from 'features/parameters/components/ProcessButtons/CancelButton';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Panel } from 'reactflow';
|
import { Panel } from 'reactflow';
|
||||||
import NodeEditorSettings from '../NodeEditorSettings';
|
import NodeEditorSettings from './NodeEditorSettings';
|
||||||
import ClearGraphButton from '../ui/ClearGraphButton';
|
import ClearGraphButton from './ClearGraphButton';
|
||||||
import NodeInvokeButton from '../ui/NodeInvokeButton';
|
import NodeInvokeButton from './NodeInvokeButton';
|
||||||
import ReloadSchemaButton from '../ui/ReloadSchemaButton';
|
import ReloadSchemaButton from './ReloadSchemaButton';
|
||||||
|
|
||||||
const TopCenterPanel = () => {
|
const TopCenterPanel = () => {
|
||||||
return (
|
return (
|
@ -5,12 +5,12 @@ import { stateSelector } from 'app/store/store';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||||
|
import { useBuildNodeData } from 'features/nodes/hooks/useBuildNodeData';
|
||||||
|
import { nodeAdded } from 'features/nodes/store/nodesSlice';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import { forwardRef, useCallback } from 'react';
|
import { forwardRef, useCallback } from 'react';
|
||||||
import 'reactflow/dist/style.css';
|
import 'reactflow/dist/style.css';
|
||||||
import { AnyInvocationType } from 'services/events/types';
|
import { AnyInvocationType } from 'services/events/types';
|
||||||
import { useBuildNodeData } from '../hooks/useBuildNodeData';
|
|
||||||
import { nodeAdded } from '../store/nodesSlice';
|
|
||||||
|
|
||||||
type NodeTemplate = {
|
type NodeTemplate = {
|
||||||
label: string;
|
label: string;
|
@ -1,6 +1,6 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Panel } from 'reactflow';
|
import { Panel } from 'reactflow';
|
||||||
import AddNodeMenu from '../AddNodeMenu';
|
import AddNodeMenu from './AddNodeMenu';
|
||||||
|
|
||||||
const TopLeftPanel = () => (
|
const TopLeftPanel = () => (
|
||||||
<Panel position="top-left">
|
<Panel position="top-left">
|
@ -1,8 +1,8 @@
|
|||||||
import { Badge, Flex, Tooltip } from '@chakra-ui/react';
|
import { Badge, Flex, Tooltip } from '@chakra-ui/react';
|
||||||
|
import { FIELDS } from 'features/nodes/types/constants';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import 'reactflow/dist/style.css';
|
import 'reactflow/dist/style.css';
|
||||||
import { FIELDS } from '../types/constants';
|
|
||||||
|
|
||||||
const FieldTypeLegend = () => {
|
const FieldTypeLegend = () => {
|
||||||
return (
|
return (
|
@ -1,7 +1,7 @@
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Panel } from 'reactflow';
|
import { Panel } from 'reactflow';
|
||||||
import FieldTypeLegend from '../FieldTypeLegend';
|
import FieldTypeLegend from './FieldTypeLegend';
|
||||||
|
|
||||||
const TopRightPanel = () => {
|
const TopRightPanel = () => {
|
||||||
const shouldShowFieldTypeLegend = useAppSelector(
|
const shouldShowFieldTypeLegend = useAppSelector(
|
@ -1,17 +0,0 @@
|
|||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
|
||||||
import { ImageOutput } from 'services/api/types';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
output: ImageOutput;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ImageOutputPreview = ({ output }: Props) => {
|
|
||||||
const { image, width, height } = output;
|
|
||||||
const { data: imageDTO } = useGetImageDTOQuery(image.image_name);
|
|
||||||
|
|
||||||
return <IAIDndImage imageDTO={imageDTO} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(ImageOutputPreview);
|
|
@ -1,13 +0,0 @@
|
|||||||
import { Text } from '@chakra-ui/react';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { FloatOutput, IntegerOutput } from 'services/api/types';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
output: IntegerOutput | FloatOutput;
|
|
||||||
};
|
|
||||||
|
|
||||||
const NumberOutputPreview = ({ output }: Props) => {
|
|
||||||
return <Text>{output.value}</Text>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(NumberOutputPreview);
|
|
@ -1,13 +0,0 @@
|
|||||||
import { Text } from '@chakra-ui/react';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { StringOutput } from 'services/api/types';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
output: StringOutput;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StringOutputPreview = ({ output }: Props) => {
|
|
||||||
return <Text>{output.value}</Text>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(StringOutputPreview);
|
|
@ -1,9 +1,9 @@
|
|||||||
import InspectorPanel from 'features/nodes/components/panel/InspectorPanel';
|
|
||||||
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
|
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
|
||||||
import { memo, useState } from 'react';
|
import { memo, useState } from 'react';
|
||||||
import { Panel, PanelGroup } from 'react-resizable-panels';
|
import { Panel, PanelGroup } from 'react-resizable-panels';
|
||||||
import 'reactflow/dist/style.css';
|
import 'reactflow/dist/style.css';
|
||||||
import WorkflowPanel from './WorkflowPanel';
|
import WorkflowPanel from './workflow/WorkflowPanel';
|
||||||
|
import InspectorPanel from './inspector/InspectorPanel';
|
||||||
|
|
||||||
const NodeEditorPanelGroup = () => {
|
const NodeEditorPanelGroup = () => {
|
||||||
const [isTopPanelCollapsed, setIsTopPanelCollapsed] = useState(false);
|
const [isTopPanelCollapsed, setIsTopPanelCollapsed] = useState(false);
|
@ -23,7 +23,7 @@ const selector = createSelector(
|
|||||||
defaultSelectorOptions
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const NodeDataInspector = () => {
|
const InspectorDataTab = () => {
|
||||||
const { data } = useAppSelector(selector);
|
const { data } = useAppSelector(selector);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -33,4 +33,4 @@ const NodeDataInspector = () => {
|
|||||||
return <ImageMetadataJSON jsonObject={data} label="Node Data" />;
|
return <ImageMetadataJSON jsonObject={data} label="Node Data" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeDataInspector);
|
export default memo(InspectorDataTab);
|
@ -5,11 +5,11 @@ import { useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import ImageOutputPreview from './ImageOutputPreview';
|
import ImageOutputPreview from './outputs/ImageOutputPreview';
|
||||||
import NumberOutputPreview from './NumberOutputPreview';
|
import ScrollableContent from '../ScrollableContent';
|
||||||
import ScrollableContent from './ScrollableContent';
|
|
||||||
import StringOutputPreview from './StringOutputPreview';
|
|
||||||
import { AnyResult } from 'services/events/types';
|
import { AnyResult } from 'services/events/types';
|
||||||
|
import StringOutputPreview from './outputs/StringOutputPreview';
|
||||||
|
import NumberOutputPreview from './outputs/NumberOutputPreview';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
stateSelector,
|
stateSelector,
|
||||||
@ -32,7 +32,7 @@ const selector = createSelector(
|
|||||||
defaultSelectorOptions
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const NodeResultsInspector = () => {
|
const InspectorOutputsTab = () => {
|
||||||
const { node, nes } = useAppSelector(selector);
|
const { node, nes } = useAppSelector(selector);
|
||||||
|
|
||||||
if (!node || !nes) {
|
if (!node || !nes) {
|
||||||
@ -96,6 +96,6 @@ const NodeResultsInspector = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(NodeResultsInspector);
|
export default memo(InspectorOutputsTab);
|
||||||
|
|
||||||
const getKey = (result: AnyResult, i: number) => `${result.type}-${i}`;
|
const getKey = (result: AnyResult, i: number) => `${result.type}-${i}`;
|
@ -7,9 +7,9 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import NodeDataInspector from './NodeDataInspector';
|
import InspectorDataTab from './InspectorDataTab';
|
||||||
import NodeResultsInspector from './NodeResultsInspector';
|
import InspectorOutputsTab from './InspectorOutputsTab';
|
||||||
import NodeTemplateInspector from './NodeTemplateInspector';
|
import InspectorTemplateTab from './InspectorTemplateTab';
|
||||||
|
|
||||||
const InspectorPanel = () => {
|
const InspectorPanel = () => {
|
||||||
return (
|
return (
|
||||||
@ -29,20 +29,20 @@ const InspectorPanel = () => {
|
|||||||
sx={{ display: 'flex', flexDir: 'column', w: 'full', h: 'full' }}
|
sx={{ display: 'flex', flexDir: 'column', w: 'full', h: 'full' }}
|
||||||
>
|
>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab>Node Outputs</Tab>
|
<Tab>Outputs</Tab>
|
||||||
<Tab>Node Data</Tab>
|
<Tab>Data</Tab>
|
||||||
<Tab>Node Template</Tab>
|
<Tab>Template</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<NodeResultsInspector />
|
<InspectorOutputsTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<NodeDataInspector />
|
<InspectorDataTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<NodeTemplateInspector />
|
<InspectorTemplateTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
@ -36,7 +36,7 @@ const selector = createSelector(
|
|||||||
defaultSelectorOptions
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const WorkflowPanel = () => {
|
const WorkflowGeneralTab = () => {
|
||||||
const { author, name, description, tags, version, contact, notes } =
|
const { author, name, description, tags, version, contact, notes } =
|
||||||
useAppSelector(selector);
|
useAppSelector(selector);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -139,4 +139,4 @@ const WorkflowPanel = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(WorkflowPanel);
|
export default memo(WorkflowGeneralTab);
|
@ -19,7 +19,7 @@ const useWatchWorkflow = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const WorkflowWorkflowTab = () => {
|
const WorkflowJSONTab = () => {
|
||||||
const { workflow } = useWatchWorkflow();
|
const { workflow } = useWatchWorkflow();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -40,4 +40,4 @@ const WorkflowWorkflowTab = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(WorkflowWorkflowTab);
|
export default memo(WorkflowJSONTab);
|
@ -5,7 +5,7 @@ import { useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import LinearViewField from '../../fields/LinearViewField';
|
import LinearViewField from '../../flow/nodes/Invocation/fields/LinearViewField';
|
||||||
import ScrollableContent from '../ScrollableContent';
|
import ScrollableContent from '../ScrollableContent';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
@ -18,7 +18,7 @@ const selector = createSelector(
|
|||||||
defaultSelectorOptions
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const LinearTabContent = () => {
|
const WorkflowLinearTab = () => {
|
||||||
const { fields } = useAppSelector(selector);
|
const { fields } = useAppSelector(selector);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -61,4 +61,4 @@ const LinearTabContent = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(LinearTabContent);
|
export default memo(WorkflowLinearTab);
|
@ -14,7 +14,7 @@ const selector = createSelector(stateSelector, ({ nodes }) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const WorkflowPanel = () => {
|
const WorkflowNotesTab = () => {
|
||||||
const { notes } = useAppSelector(selector);
|
const { notes } = useAppSelector(selector);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@ -48,4 +48,4 @@ const WorkflowPanel = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(WorkflowPanel);
|
export default memo(WorkflowNotesTab);
|
@ -7,9 +7,9 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import GeneralTab from './workflow/GeneralTab';
|
import WorkflowGeneralTab from './WorkflowGeneralTab';
|
||||||
import LinearTab from './workflow/LinearTab';
|
import WorkflowLinearTab from './WorkflowLinearTab';
|
||||||
import WorkflowTab from './workflow/WorkflowTab';
|
import WorkflowJSONTab from './WorkflowJSONTab';
|
||||||
|
|
||||||
const WorkflowPanel = () => {
|
const WorkflowPanel = () => {
|
||||||
return (
|
return (
|
||||||
@ -35,13 +35,13 @@ const WorkflowPanel = () => {
|
|||||||
|
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<LinearTab />
|
<WorkflowLinearTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<GeneralTab />
|
<WorkflowGeneralTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<WorkflowTab />
|
<WorkflowJSONTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
@ -3,7 +3,7 @@ import { stateSelector } from 'app/store/store';
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { makeConnectionErrorSelector } from 'features/nodes/store/util/makeIsConnectionValidSelector';
|
import { makeConnectionErrorSelector } from 'features/nodes/store/util/makeIsConnectionValidSelector';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useFieldType } from './useNodeData';
|
import { useFieldType } from './useFieldType.ts';
|
||||||
|
|
||||||
const selectIsConnectionInProgress = createSelector(
|
const selectIsConnectionInProgress = createSelector(
|
||||||
stateSelector,
|
stateSelector,
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useDoesInputHaveValue = (nodeId: string, fieldName: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return Boolean(node?.data.inputs[fieldName]?.value);
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const doesFieldHaveValue = useAppSelector(selector);
|
||||||
|
|
||||||
|
return doesFieldHaveValue;
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldData = (nodeId: string, fieldName: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return node?.data.inputs[fieldName];
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fieldData = useAppSelector(selector);
|
||||||
|
|
||||||
|
return fieldData;
|
||||||
|
};
|
@ -0,0 +1,30 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldInputKind = (nodeId: string, fieldName: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
||||||
|
const fieldTemplate = nodeTemplate?.inputs[fieldName];
|
||||||
|
return fieldTemplate?.input;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const inputKind = useAppSelector(selector);
|
||||||
|
|
||||||
|
return inputKind;
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldLabel = (nodeId: string, fieldName: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return node?.data.inputs[fieldName]?.label;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const label = useAppSelector(selector);
|
||||||
|
|
||||||
|
return label;
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { map } from 'lodash-es';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { KIND_MAP } from '../types/constants';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldNames = (nodeId: string, kind: 'input' | 'output') => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return map(node.data[KIND_MAP[kind]], (field) => field.name).filter(
|
||||||
|
(fieldName) => fieldName !== 'is_intermediate'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[kind, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fieldNames = useAppSelector(selector);
|
||||||
|
return fieldNames;
|
||||||
|
};
|
@ -0,0 +1,34 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { KIND_MAP } from '../types/constants';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldTemplate = (
|
||||||
|
nodeId: string,
|
||||||
|
fieldName: string,
|
||||||
|
kind: 'input' | 'output'
|
||||||
|
) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
||||||
|
return nodeTemplate?.[KIND_MAP[kind]][fieldName];
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, kind, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fieldTemplate = useAppSelector(selector);
|
||||||
|
|
||||||
|
return fieldTemplate;
|
||||||
|
};
|
@ -0,0 +1,34 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
import { KIND_MAP } from '../types/constants';
|
||||||
|
|
||||||
|
export const useFieldTemplateTitle = (
|
||||||
|
nodeId: string,
|
||||||
|
fieldName: string,
|
||||||
|
kind: 'input' | 'output'
|
||||||
|
) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
||||||
|
return nodeTemplate?.[KIND_MAP[kind]][fieldName]?.title;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, kind, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fieldTemplate = useAppSelector(selector);
|
||||||
|
|
||||||
|
return fieldTemplate;
|
||||||
|
};
|
@ -0,0 +1,33 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { KIND_MAP } from '../types/constants';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useFieldType = (
|
||||||
|
nodeId: string,
|
||||||
|
fieldName: string,
|
||||||
|
kind: 'input' | 'output'
|
||||||
|
) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return node?.data[KIND_MAP[kind]][fieldName]?.type;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, kind, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fieldType = useAppSelector(selector);
|
||||||
|
|
||||||
|
return fieldType;
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { some } from 'lodash-es';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { IMAGE_FIELDS } from '../types/constants';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useHasImageOutput = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return some(node.data.outputs, (output) =>
|
||||||
|
IMAGE_FIELDS.includes(output.type)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasImageOutput = useAppSelector(selector);
|
||||||
|
return hasImageOutput;
|
||||||
|
};
|
@ -0,0 +1,27 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useIsIntermediate = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Boolean(node.data.inputs.is_intermediate?.value);
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const is_intermediate = useAppSelector(selector);
|
||||||
|
return is_intermediate;
|
||||||
|
};
|
@ -0,0 +1,33 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { mouseOverFieldChanged } from '../store/nodesSlice';
|
||||||
|
|
||||||
|
export const useIsMouseOverField = (nodeId: string, fieldName: string) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) =>
|
||||||
|
nodes.mouseOverField?.nodeId === nodeId &&
|
||||||
|
nodes.mouseOverField?.fieldName === fieldName,
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[fieldName, nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const isMouseOverField = useAppSelector(selector);
|
||||||
|
|
||||||
|
const handleMouseOver = useCallback(() => {
|
||||||
|
dispatch(mouseOverFieldChanged({ nodeId, fieldName }));
|
||||||
|
}, [dispatch, fieldName, nodeId]);
|
||||||
|
|
||||||
|
const handleMouseOut = useCallback(() => {
|
||||||
|
dispatch(mouseOverFieldChanged(null));
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
return { isMouseOverField, handleMouseOver, handleMouseOut };
|
||||||
|
};
|
@ -1,37 +1,8 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import { map, some } from 'lodash-es';
|
import { useMemo } from 'react';
|
||||||
import { useCallback, useMemo } from 'react';
|
|
||||||
import { mouseOverFieldChanged } from '../store/nodesSlice';
|
|
||||||
import { FOOTER_FIELDS, IMAGE_FIELDS } from '../types/constants';
|
|
||||||
import { isInvocationNode } from '../types/types';
|
|
||||||
|
|
||||||
const KIND_MAP = {
|
|
||||||
input: 'inputs' as const,
|
|
||||||
output: 'outputs' as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useNodeTemplate = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
|
||||||
return nodeTemplate;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const nodeTemplate = useAppSelector(selector);
|
|
||||||
|
|
||||||
return nodeTemplate;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useNodeData = (nodeId: string) => {
|
export const useNodeData = (nodeId: string) => {
|
||||||
const selector = useMemo(
|
const selector = useMemo(
|
||||||
@ -51,337 +22,3 @@ export const useNodeData = (nodeId: string) => {
|
|||||||
|
|
||||||
return nodeData;
|
return nodeData;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFieldLabel = (nodeId: string, fieldName: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return node?.data.inputs[fieldName]?.label;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const label = useAppSelector(selector);
|
|
||||||
|
|
||||||
return label;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldData = (nodeId: string, fieldName: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return node?.data.inputs[fieldName];
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldData = useAppSelector(selector);
|
|
||||||
|
|
||||||
return fieldData;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldInputKind = (nodeId: string, fieldName: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
|
||||||
const fieldTemplate = nodeTemplate?.inputs[fieldName];
|
|
||||||
return fieldTemplate?.input;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const inputKind = useAppSelector(selector);
|
|
||||||
|
|
||||||
return inputKind;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldType = (
|
|
||||||
nodeId: string,
|
|
||||||
fieldName: string,
|
|
||||||
kind: 'input' | 'output'
|
|
||||||
) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return node?.data[KIND_MAP[kind]][fieldName]?.type;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, kind, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldType = useAppSelector(selector);
|
|
||||||
|
|
||||||
return fieldType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldNames = (nodeId: string, kind: 'input' | 'output') => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return map(node.data[KIND_MAP[kind]], (field) => field.name).filter(
|
|
||||||
(fieldName) => fieldName !== 'is_intermediate'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[kind, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldNames = useAppSelector(selector);
|
|
||||||
return fieldNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useWithFooter = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return some(node.data.outputs, (output) =>
|
|
||||||
FOOTER_FIELDS.includes(output.type)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const withFooter = useAppSelector(selector);
|
|
||||||
return withFooter;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useHasImageOutput = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return some(node.data.outputs, (output) =>
|
|
||||||
IMAGE_FIELDS.includes(output.type)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const hasImageOutput = useAppSelector(selector);
|
|
||||||
return hasImageOutput;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useIsIntermediate = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Boolean(node.data.inputs.is_intermediate?.value);
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const is_intermediate = useAppSelector(selector);
|
|
||||||
return is_intermediate;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useNodeLabel = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.data.label;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const label = useAppSelector(selector);
|
|
||||||
return label;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useNodeTemplateTitle = (nodeId: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const nodeTemplate = node
|
|
||||||
? nodes.nodeTemplates[node.data.type]
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return nodeTemplate?.title;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const title = useAppSelector(selector);
|
|
||||||
return title;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldTemplateTitle = (
|
|
||||||
nodeId: string,
|
|
||||||
fieldName: string,
|
|
||||||
kind: 'input' | 'output'
|
|
||||||
) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
|
||||||
return nodeTemplate?.[KIND_MAP[kind]][fieldName]?.title;
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, kind, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldTemplate = useAppSelector(selector);
|
|
||||||
|
|
||||||
return fieldTemplate;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFieldTemplate = (
|
|
||||||
nodeId: string,
|
|
||||||
fieldName: string,
|
|
||||||
kind: 'input' | 'output'
|
|
||||||
) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
|
||||||
return nodeTemplate?.[KIND_MAP[kind]][fieldName];
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, kind, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldTemplate = useAppSelector(selector);
|
|
||||||
|
|
||||||
return fieldTemplate;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDoesInputHaveValue = (nodeId: string, fieldName: string) => {
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) => {
|
|
||||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
|
||||||
if (!isInvocationNode(node)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return Boolean(node?.data.inputs[fieldName]?.value);
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const doesFieldHaveValue = useAppSelector(selector);
|
|
||||||
|
|
||||||
return doesFieldHaveValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useIsMouseOverField = (nodeId: string, fieldName: string) => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ nodes }) =>
|
|
||||||
nodes.mouseOverField?.nodeId === nodeId &&
|
|
||||||
nodes.mouseOverField?.fieldName === fieldName,
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[fieldName, nodeId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const isMouseOverField = useAppSelector(selector);
|
|
||||||
|
|
||||||
const handleMouseOver = useCallback(() => {
|
|
||||||
dispatch(mouseOverFieldChanged({ nodeId, fieldName }));
|
|
||||||
}, [dispatch, fieldName, nodeId]);
|
|
||||||
|
|
||||||
const handleMouseOut = useCallback(() => {
|
|
||||||
dispatch(mouseOverFieldChanged(null));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return { isMouseOverField, handleMouseOver, handleMouseOut };
|
|
||||||
};
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useNodeLabel = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.data.label;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const label = useAppSelector(selector);
|
||||||
|
return label;
|
||||||
|
};
|
@ -0,0 +1,25 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export const useNodeTemplate = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
|
||||||
|
return nodeTemplate;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const nodeTemplate = useAppSelector(selector);
|
||||||
|
|
||||||
|
return nodeTemplate;
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useNodeTemplateTitle = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const nodeTemplate = node
|
||||||
|
? nodes.nodeTemplates[node.data.type]
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return nodeTemplate?.title;
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const title = useAppSelector(selector);
|
||||||
|
return title;
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import { some } from 'lodash-es';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { FOOTER_FIELDS } from '../types/constants';
|
||||||
|
import { isInvocationNode } from '../types/types';
|
||||||
|
|
||||||
|
export const useWithFooter = (nodeId: string) => {
|
||||||
|
const selector = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(
|
||||||
|
stateSelector,
|
||||||
|
({ nodes }) => {
|
||||||
|
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||||
|
if (!isInvocationNode(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return some(node.data.outputs, (output) =>
|
||||||
|
FOOTER_FIELDS.includes(output.type)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
|
),
|
||||||
|
[nodeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const withFooter = useAppSelector(selector);
|
||||||
|
return withFooter;
|
||||||
|
};
|
@ -9,6 +9,11 @@ export const DRAG_HANDLE_CLASSNAME = 'node-drag-handle';
|
|||||||
export const IMAGE_FIELDS = ['ImageField', 'ImageCollection'];
|
export const IMAGE_FIELDS = ['ImageField', 'ImageCollection'];
|
||||||
export const FOOTER_FIELDS = IMAGE_FIELDS;
|
export const FOOTER_FIELDS = IMAGE_FIELDS;
|
||||||
|
|
||||||
|
export const KIND_MAP = {
|
||||||
|
input: 'inputs' as const,
|
||||||
|
output: 'outputs' as const,
|
||||||
|
};
|
||||||
|
|
||||||
export const COLLECTION_TYPES: FieldType[] = [
|
export const COLLECTION_TYPES: FieldType[] = [
|
||||||
'Collection',
|
'Collection',
|
||||||
'IntegerCollection',
|
'IntegerCollection',
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user