error nodes outlined in red

This commit is contained in:
Attila Cseh
2025-08-05 12:38:36 +02:00
committed by psychedelicious
parent 1a11437b6f
commit deb4dc64af
6 changed files with 30 additions and 14 deletions

View File

@@ -8,6 +8,7 @@ import {
useInputFieldNamesConnection,
useInputFieldNamesMissing,
} from 'features/nodes/hooks/useInputFieldNamesByStatus';
import { useNodeHasErrors } from 'features/nodes/hooks/useNodeIsInvalid';
import { useOutputFieldNames } from 'features/nodes/hooks/useOutputFieldNames';
import { useWithFooter } from 'features/nodes/hooks/useWithFooter';
import { memo } from 'react';
@@ -37,11 +38,12 @@ const sx: SystemStyleObject = {
};
const InvocationNode = ({ nodeId, isOpen }: Props) => {
const isInvalid = useNodeHasErrors();
const withFooter = useWithFooter();
return (
<>
<InvocationNodeHeader nodeId={nodeId} isOpen={isOpen} />
<InvocationNodeHeader nodeId={nodeId} isOpen={isOpen} isInvalid={isInvalid} />
{isOpen && (
<>
<Flex layerStyle="nodeBody" sx={sx} data-with-footer={withFooter}>

View File

@@ -3,7 +3,6 @@ import { Flex } from '@invoke-ai/ui-library';
import NodeCollapseButton from 'features/nodes/components/flow/nodes/common/NodeCollapseButton';
import NodeTitle from 'features/nodes/components/flow/nodes/common/NodeTitle';
import InvocationNodeClassificationIcon from 'features/nodes/components/flow/nodes/Invocation/InvocationNodeClassificationIcon';
import { useNodeHasErrors } from 'features/nodes/hooks/useNodeIsInvalid';
import { memo } from 'react';
import InvocationNodeCollapsedHandles from './InvocationNodeCollapsedHandles';
@@ -13,6 +12,7 @@ import InvocationNodeStatusIndicator from './InvocationNodeStatusIndicator';
type Props = {
nodeId: string;
isOpen: boolean;
isInvalid?: boolean;
};
const sx: SystemStyleObject = {
@@ -28,14 +28,12 @@ const sx: SystemStyleObject = {
},
};
const InvocationNodeHeader = ({ nodeId, isOpen }: Props) => {
const isInvalid = useNodeHasErrors();
const InvocationNodeHeader = ({ nodeId, isOpen, isInvalid }: Props) => {
return (
<Flex sx={sx} data-is-open={isOpen} data-is-invalid={isInvalid}>
<NodeCollapseButton nodeId={nodeId} isOpen={isOpen} />
<InvocationNodeClassificationIcon nodeId={nodeId} />
<NodeTitle nodeId={nodeId} />
<NodeTitle nodeId={nodeId} isInvalid={isInvalid} />
<Flex alignItems="center">
<InvocationNodeStatusIndicator nodeId={nodeId} />
<InvocationNodeInfoIcon nodeId={nodeId} />

View File

@@ -30,12 +30,12 @@ const labelSx: SystemStyleObject = {
_hover: {
fontWeight: 'semibold !important',
},
'&[data-is-invalid="true"]': {
color: 'error.300',
},
'&[data-is-added-to-form="true"]': {
color: 'blue.300',
},
'&[data-is-invalid="true"]': {
color: 'error.300',
},
'&[data-is-disabled="true"]': {
opacity: 0.5,
},

View File

@@ -1,3 +1,4 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { Flex, Input, Text } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { useEditable } from 'common/hooks/useEditable';
@@ -10,12 +11,20 @@ import { NO_FIT_ON_DOUBLE_CLICK_CLASS } from 'features/nodes/types/constants';
import { memo, useCallback, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
const labelSx: SystemStyleObject = {
fontWeight: 'semibold',
'&[data-is-invalid="true"]': {
color: 'error.300',
},
};
type Props = {
nodeId: string;
title?: string;
isInvalid?: boolean;
};
const NodeTitle = ({ nodeId, title }: Props) => {
const NodeTitle = ({ nodeId, title, isInvalid }: Props) => {
const dispatch = useAppDispatch();
const label = useNodeUserTitleSafe();
const batchGroupId = useBatchGroupId(nodeId);
@@ -53,10 +62,11 @@ const NodeTitle = ({ nodeId, title }: Props) => {
{!editable.isEditing && (
<Text
className={NO_FIT_ON_DOUBLE_CLICK_CLASS}
fontWeight="semibold"
color={batchGroupColorToken}
onDoubleClick={editable.startEditing}
sx={labelSx}
noOfLines={1}
color={batchGroupColorToken}
data-is-invalid={isInvalid}
onDoubleClick={editable.startEditing}
>
{titleWithBatchGroupId}
</Text>

View File

@@ -5,6 +5,7 @@ import { useInvocationNodeContext } from 'features/nodes/components/flow/nodes/I
import { useIsWorkflowEditorLocked } from 'features/nodes/hooks/useIsWorkflowEditorLocked';
import { useMouseOverFormField, useMouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
import { useNodeExecutionState } from 'features/nodes/hooks/useNodeExecutionState';
import { useNodeHasErrors } from 'features/nodes/hooks/useNodeIsInvalid';
import { useZoomToNode } from 'features/nodes/hooks/useZoomToNode';
import { selectNodeOpacity } from 'features/nodes/store/workflowSettingsSlice';
import { DRAG_HANDLE_CLASSNAME, NO_FIT_ON_DOUBLE_CLICK_CLASS, NODE_WIDTH } from 'features/nodes/types/constants';
@@ -29,6 +30,8 @@ const NodeWrapper = (props: NodeWrapperProps) => {
const mouseOverFormField = useMouseOverFormField(nodeId);
const zoomToNode = useZoomToNode(nodeId);
const isLocked = useIsWorkflowEditorLocked();
const isInvalid = useNodeHasErrors();
const hasError = isMissingTemplate || isInvalid;
const executionState = useNodeExecutionState(nodeId);
const isInProgress = executionState?.status === zNodeStatus.enum.IN_PROGRESS;
@@ -74,7 +77,7 @@ const NodeWrapper = (props: NodeWrapperProps) => {
data-is-editor-locked={isLocked}
data-is-selected={selected}
data-is-mouse-over-form-field={mouseOverFormField.isMouseOverFormField}
data-status={isMissingTemplate ? 'error' : needsUpdate ? 'warning' : undefined}
data-status={hasError ? 'error' : needsUpdate ? 'warning' : undefined}
>
<Box sx={shadowsSx} />
<Box sx={inProgressSx} data-is-in-progress={isInProgress} />

View File

@@ -56,6 +56,9 @@ export const containerSx: SystemStyleObject = {
display: 'block',
shadow: '0 0 0 2px var(--border-color-selected)',
},
'&[data-is-invalid="true"]': {
color: 'error.300',
},
'&[data-is-editor-locked="true"]': {
'& *': {
cursor: 'not-allowed',