mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
added sortable to linear view, not saving yet
This commit is contained in:
parent
273994b742
commit
8a147bd6e6
@ -52,6 +52,7 @@
|
|||||||
"@chakra-ui/react-use-size": "^2.1.0",
|
"@chakra-ui/react-use-size": "^2.1.0",
|
||||||
"@dagrejs/graphlib": "^2.1.13",
|
"@dagrejs/graphlib": "^2.1.13",
|
||||||
"@dnd-kit/core": "^6.1.0",
|
"@dnd-kit/core": "^6.1.0",
|
||||||
|
"@dnd-kit/sortable": "^8.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"@fontsource-variable/inter": "^5.0.16",
|
"@fontsource-variable/inter": "^5.0.16",
|
||||||
"@invoke-ai/ui-library": "^0.0.18",
|
"@invoke-ai/ui-library": "^0.0.18",
|
||||||
|
@ -22,6 +22,9 @@ dependencies:
|
|||||||
'@dnd-kit/core':
|
'@dnd-kit/core':
|
||||||
specifier: ^6.1.0
|
specifier: ^6.1.0
|
||||||
version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@dnd-kit/sortable':
|
||||||
|
specifier: ^8.0.0
|
||||||
|
version: 8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0)
|
||||||
'@dnd-kit/utilities':
|
'@dnd-kit/utilities':
|
||||||
specifier: ^3.2.2
|
specifier: ^3.2.2
|
||||||
version: 3.2.2(react@18.2.0)
|
version: 3.2.2(react@18.2.0)
|
||||||
@ -2884,6 +2887,18 @@ packages:
|
|||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@dnd-kit/core': ^6.1.0
|
||||||
|
react: '>=16.8.0'
|
||||||
|
dependencies:
|
||||||
|
'@dnd-kit/core': 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@dnd-kit/utilities@3.2.2(react@18.2.0):
|
/@dnd-kit/utilities@3.2.2(react@18.2.0):
|
||||||
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -19,6 +19,7 @@ const AppDndContext = (props: PropsWithChildren) => {
|
|||||||
|
|
||||||
const handleDragStart = useCallback(
|
const handleDragStart = useCallback(
|
||||||
(event: DragStartEvent) => {
|
(event: DragStartEvent) => {
|
||||||
|
console.log('handling drag start', event.active.data.current);
|
||||||
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag started');
|
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag started');
|
||||||
const activeData = event.active.data.current;
|
const activeData = event.active.data.current;
|
||||||
if (!activeData) {
|
if (!activeData) {
|
||||||
@ -31,6 +32,7 @@ const AppDndContext = (props: PropsWithChildren) => {
|
|||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
(event: DragEndEvent) => {
|
(event: DragEndEvent) => {
|
||||||
|
console.log('handling drag end', event.active.data.current);
|
||||||
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag ended');
|
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag ended');
|
||||||
const overData = event.over?.data.current;
|
const overData = event.over?.data.current;
|
||||||
if (!activeDragData || !overData) {
|
if (!activeDragData || !overData) {
|
||||||
|
@ -80,6 +80,14 @@ export type NodeFieldDraggableData = BaseDragData & {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LinearViewFieldDraggableData = BaseDragData & {
|
||||||
|
payloadType: 'LINEAR_VIEW_FIELD';
|
||||||
|
payload: {
|
||||||
|
nodeId: string;
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type ImageDraggableData = BaseDragData & {
|
export type ImageDraggableData = BaseDragData & {
|
||||||
payloadType: 'IMAGE_DTO';
|
payloadType: 'IMAGE_DTO';
|
||||||
payload: { imageDTO: ImageDTO };
|
payload: { imageDTO: ImageDTO };
|
||||||
@ -90,7 +98,11 @@ export type GallerySelectionDraggableData = BaseDragData & {
|
|||||||
payload: { boardId: BoardId };
|
payload: { boardId: BoardId };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TypesafeDraggableData = NodeFieldDraggableData | ImageDraggableData | GallerySelectionDraggableData;
|
export type TypesafeDraggableData =
|
||||||
|
| NodeFieldDraggableData
|
||||||
|
| LinearViewFieldDraggableData
|
||||||
|
| ImageDraggableData
|
||||||
|
| GallerySelectionDraggableData;
|
||||||
|
|
||||||
export interface UseDroppableTypesafeArguments extends Omit<UseDroppableArguments, 'data'> {
|
export interface UseDroppableTypesafeArguments extends Omit<UseDroppableArguments, 'data'> {
|
||||||
data?: TypesafeDroppableData;
|
data?: TypesafeDroppableData;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { useSortable } from '@dnd-kit/sortable';
|
||||||
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
import { Flex, Icon, IconButton, Spacer, Tooltip } from '@invoke-ai/ui-library';
|
import { Flex, Icon, IconButton, Spacer, Tooltip } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
||||||
@ -25,6 +27,13 @@ const LinearViewField = ({ nodeId, fieldName }: Props) => {
|
|||||||
dispatch(workflowExposedFieldRemoved({ nodeId, fieldName }));
|
dispatch(workflowExposedFieldRemoved({ nodeId, fieldName }));
|
||||||
}, [dispatch, fieldName, nodeId]);
|
}, [dispatch, fieldName, nodeId]);
|
||||||
|
|
||||||
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: nodeId });
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
transform: CSS.Transform.toString(transform),
|
||||||
|
transition,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
onMouseEnter={handleMouseOver}
|
onMouseEnter={handleMouseOver}
|
||||||
@ -35,6 +44,10 @@ const LinearViewField = ({ nodeId, fieldName }: Props) => {
|
|||||||
w="full"
|
w="full"
|
||||||
p={4}
|
p={4}
|
||||||
flexDir="column"
|
flexDir="column"
|
||||||
|
ref={setNodeRef}
|
||||||
|
style={style}
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}
|
||||||
>
|
>
|
||||||
<Flex>
|
<Flex>
|
||||||
<EditableFieldTitle nodeId={nodeId} fieldName={fieldName} kind="input" />
|
<EditableFieldTitle nodeId={nodeId} fieldName={fieldName} kind="input" />
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
|
|
||||||
|
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
||||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import IAIDroppable from 'common/components/IAIDroppable';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
|
import type { TypesafeDroppableData } from 'features/dnd/types';
|
||||||
import LinearViewField from 'features/nodes/components/flow/nodes/Invocation/fields/LinearViewField';
|
import LinearViewField from 'features/nodes/components/flow/nodes/Invocation/fields/LinearViewField';
|
||||||
import { selectWorkflowSlice } from 'features/nodes/store/workflowSlice';
|
import { selectWorkflowSlice } from 'features/nodes/store/workflowSlice';
|
||||||
import { memo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetOpenAPISchemaQuery } from 'services/api/endpoints/appInfo';
|
import { useGetOpenAPISchemaQuery } from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
@ -16,9 +20,19 @@ const WorkflowLinearTab = () => {
|
|||||||
const { isLoading } = useGetOpenAPISchemaQuery();
|
const { isLoading } = useGetOpenAPISchemaQuery();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const droppableData = useMemo<TypesafeDroppableData | undefined>(
|
||||||
|
() => ({
|
||||||
|
id: 'current-image',
|
||||||
|
actionType: 'SET_CURRENT_IMAGE',
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box position="relative" w="full" h="full">
|
<Box position="relative" w="full" h="full">
|
||||||
|
<IAIDroppable data={droppableData} disabled={false} dropLabel="drop label" />
|
||||||
<ScrollableContent>
|
<ScrollableContent>
|
||||||
|
<SortableContext items={fields.map((field) => field.nodeId)} strategy={verticalListSortingStrategy}>
|
||||||
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} gap={2} h="full" w="full">
|
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} gap={2} h="full" w="full">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<IAINoContentFallback label={t('nodes.loadingNodes')} icon={null} />
|
<IAINoContentFallback label={t('nodes.loadingNodes')} icon={null} />
|
||||||
@ -30,6 +44,7 @@ const WorkflowLinearTab = () => {
|
|||||||
<IAINoContentFallback label={t('nodes.noFieldsLinearview')} icon={null} />
|
<IAINoContentFallback label={t('nodes.noFieldsLinearview')} icon={null} />
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</SortableContext>
|
||||||
</ScrollableContent>
|
</ScrollableContent>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -42,6 +42,13 @@ export const workflowSlice = createSlice({
|
|||||||
state.exposedFields = state.exposedFields.filter((field) => !isEqual(field, action.payload));
|
state.exposedFields = state.exposedFields.filter((field) => !isEqual(field, action.payload));
|
||||||
state.isTouched = true;
|
state.isTouched = true;
|
||||||
},
|
},
|
||||||
|
workflowExposedFieldsReordered: (state, action: PayloadAction<string>) => {
|
||||||
|
state.exposedFields = action.payload.split(',').map((id) => {
|
||||||
|
const [nodeId, fieldName] = id.split('.');
|
||||||
|
return { nodeId, fieldName };
|
||||||
|
});
|
||||||
|
state.isTouched = true;
|
||||||
|
},
|
||||||
workflowNameChanged: (state, action: PayloadAction<string>) => {
|
workflowNameChanged: (state, action: PayloadAction<string>) => {
|
||||||
state.name = action.payload;
|
state.name = action.payload;
|
||||||
state.isTouched = true;
|
state.isTouched = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user