feat(ui): add selection mode toggle

This commit is contained in:
psychedelicious 2023-08-22 22:19:52 +10:00
parent 5cf9b75d77
commit 6d10e40c9b
4 changed files with 64 additions and 7 deletions

View File

@ -1,5 +1,8 @@
import { useToken } from '@chakra-ui/react';
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 { contextMenusClosed } from 'features/ui/store/uiSlice';
import { useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
@ -61,14 +64,24 @@ const nodeTypes = {
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
const proOptions: ProOptions = { hideAttribution: true };
const selector = createSelector(
stateSelector,
({ nodes }) => {
const { shouldSnapToGrid, selectionMode } = nodes;
return {
shouldSnapToGrid,
selectionMode,
};
},
defaultSelectorOptions
);
export const Flow = () => {
const dispatch = useAppDispatch();
const nodes = useAppSelector((state) => state.nodes.nodes);
const edges = useAppSelector((state) => state.nodes.edges);
const viewport = useAppSelector((state) => state.nodes.viewport);
const shouldSnapToGrid = useAppSelector(
(state) => state.nodes.shouldSnapToGrid
);
const { shouldSnapToGrid, selectionMode } = useAppSelector(selector);
const isValidConnection = useIsValidConnection();
@ -181,6 +194,7 @@ export const Flow = () => {
style={{ borderRadius }}
onPaneClick={handlePaneClick}
deleteKeyCode={DELETE_KEYS}
selectionMode={selectionMode}
>
<TopLeftPanel />
<TopCenterPanel />

View File

@ -1,6 +1,7 @@
import {
Divider,
Flex,
FormLabelProps,
Heading,
Modal,
ModalBody,
@ -13,17 +14,19 @@ import {
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 IAIIconButton from 'common/components/IAIIconButton';
import IAISwitch from 'common/components/IAISwitch';
import { ChangeEvent, memo, useCallback } from 'react';
import { FaCog } from 'react-icons/fa';
import {
selectionModeChanged,
shouldAnimateEdgesChanged,
shouldColorEdgesChanged,
shouldSnapToGridChanged,
shouldValidateGraphChanged,
} from 'features/nodes/store/nodesSlice';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { ChangeEvent, memo, useCallback } from 'react';
import { FaCog } from 'react-icons/fa';
import { SelectionMode } from 'reactflow';
const selector = createSelector(
stateSelector,
@ -33,12 +36,14 @@ const selector = createSelector(
shouldValidateGraph,
shouldSnapToGrid,
shouldColorEdges,
selectionMode,
} = nodes;
return {
shouldAnimateEdges,
shouldValidateGraph,
shouldSnapToGrid,
shouldColorEdges,
selectionModeIsChecked: selectionMode === SelectionMode.Full,
};
},
defaultSelectorOptions
@ -52,6 +57,7 @@ const NodeEditorSettings = () => {
shouldValidateGraph,
shouldSnapToGrid,
shouldColorEdges,
selectionModeIsChecked,
} = useAppSelector(selector);
const handleChangeShouldValidate = useCallback(
@ -82,6 +88,13 @@ const NodeEditorSettings = () => {
[dispatch]
);
const handleChangeSelectionMode = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
dispatch(selectionModeChanged(e.target.checked));
},
[dispatch]
);
return (
<>
<IAIIconButton
@ -105,6 +118,7 @@ const NodeEditorSettings = () => {
>
<Heading size="sm">General</Heading>
<IAISwitch
formLabelProps={formLabelProps}
onChange={handleChangeShouldAnimate}
isChecked={shouldAnimateEdges}
label="Animated Edges"
@ -112,6 +126,7 @@ const NodeEditorSettings = () => {
/>
<Divider />
<IAISwitch
formLabelProps={formLabelProps}
isChecked={shouldSnapToGrid}
onChange={handleChangeShouldSnap}
label="Snap to Grid"
@ -119,15 +134,24 @@ const NodeEditorSettings = () => {
/>
<Divider />
<IAISwitch
formLabelProps={formLabelProps}
isChecked={shouldColorEdges}
onChange={handleChangeShouldColor}
label="Color-Code Edges"
helperText="Color-code edges according to their connected fields"
/>
<IAISwitch
formLabelProps={formLabelProps}
isChecked={selectionModeIsChecked}
onChange={handleChangeSelectionMode}
label="Fully Contain Nodes to Select"
helperText="Nodes must be fully inside the selection box to be selected"
/>
<Heading size="sm" pt={4}>
Advanced
</Heading>
<IAISwitch
formLabelProps={formLabelProps}
isChecked={shouldValidateGraph}
onChange={handleChangeShouldValidate}
label="Validate Connections and Graph"
@ -142,3 +166,7 @@ const NodeEditorSettings = () => {
};
export default memo(NodeEditorSettings);
const formLabelProps: FormLabelProps = {
fontWeight: 600,
};

View File

@ -14,6 +14,7 @@ import {
Node,
NodeChange,
OnConnectStartParams,
SelectionMode,
Viewport,
} from 'reactflow';
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
@ -103,6 +104,7 @@ export const initialNodesState: NodesState = {
mouseOverField: null,
nodesToCopy: [],
edgesToCopy: [],
selectionMode: SelectionMode.Partial,
};
type FieldValueAction<T extends InputFieldValue> = PayloadAction<{
@ -721,6 +723,11 @@ const nodesSlice = createSlice({
addNodePopoverToggled: (state) => {
state.isAddNodePopoverOpen = !state.isAddNodePopoverOpen;
},
selectionModeChanged: (state, action: PayloadAction<boolean>) => {
state.selectionMode = action.payload
? SelectionMode.Full
: SelectionMode.Partial;
},
},
extraReducers: (builder) => {
builder.addCase(receivedOpenAPISchema.pending, (state) => {
@ -832,6 +839,7 @@ export const {
addNodePopoverOpened,
addNodePopoverClosed,
addNodePopoverToggled,
selectionModeChanged,
} = nodesSlice.actions;
export default nodesSlice.reducer;

View File

@ -1,4 +1,10 @@
import { Edge, Node, OnConnectStartParams, Viewport } from 'reactflow';
import {
Edge,
Node,
OnConnectStartParams,
SelectionMode,
Viewport,
} from 'reactflow';
import {
FieldIdentifier,
FieldType,
@ -32,4 +38,5 @@ export type NodesState = {
nodesToCopy: Node<NodeData>[];
edgesToCopy: Edge<InvocationEdgeExtra>[];
isAddNodePopoverOpen: boolean;
selectionMode: SelectionMode;
};