feat(ui): store node templates in separate slice

Flattens the `nodes` slice. May offer minor perf improvements in addition to just being cleaner.
This commit is contained in:
psychedelicious
2024-01-01 12:27:05 +11:00
committed by Kent Keirsey
parent 7c548c5bf3
commit 5d4610d981
33 changed files with 200 additions and 167 deletions

View File

@ -10,12 +10,12 @@ import { useMemo } from 'react';
export const useAnyOrDirectInputFieldNames = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return [];
}
const nodeTemplate = nodes.nodeTemplates[node.data.type];
const nodeTemplate = nodeTemplates.templates[node.data.type];
if (!nodeTemplate) {
return [];
}

View File

@ -1,5 +1,3 @@
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import type { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import {
DRAG_HANDLE_CLASSNAME,
@ -16,17 +14,14 @@ import { useCallback } from 'react';
import type { Node } from 'reactflow';
import { useReactFlow } from 'reactflow';
const templatesSelector = createMemoizedSelector(
[(state: RootState) => state.nodes],
(nodes) => nodes.nodeTemplates
);
export const SHARED_NODE_PROPERTIES: Partial<Node> = {
dragHandle: `.${DRAG_HANDLE_CLASSNAME}`,
};
export const useBuildNode = () => {
const nodeTemplates = useAppSelector(templatesSelector);
const nodeTemplates = useAppSelector(
(state) => state.nodeTemplates.templates
);
const flow = useReactFlow();

View File

@ -10,12 +10,12 @@ import { useMemo } from 'react';
export const useConnectionInputFieldNames = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return [];
}
const nodeTemplate = nodes.nodeTemplates[node.data.type];
const nodeTemplate = nodeTemplates.templates[node.data.type];
if (!nodeTemplate) {
return [];
}

View File

@ -8,12 +8,12 @@ import { useMemo } from 'react';
export const useDoNodeVersionsMatch = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return false;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
if (!nodeTemplate?.version || !node.data?.version) {
return false;
}

View File

@ -7,12 +7,12 @@ import { useMemo } from 'react';
export const useFieldInputKind = (nodeId: string, fieldName: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
const fieldTemplate = nodeTemplate?.inputs[fieldName];
return fieldTemplate?.input;
}),

View File

@ -7,12 +7,12 @@ import { useMemo } from 'react';
export const useFieldInputTemplate = (nodeId: string, fieldName: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate?.inputs[fieldName];
}),
[fieldName, nodeId]

View File

@ -7,12 +7,12 @@ import { useMemo } from 'react';
export const useFieldOutputTemplate = (nodeId: string, fieldName: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate?.outputs[fieldName];
}),
[fieldName, nodeId]

View File

@ -12,12 +12,12 @@ export const useFieldTemplate = (
) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate?.[KIND_MAP[kind]][fieldName];
}),
[fieldName, kind, nodeId]

View File

@ -12,12 +12,12 @@ export const useFieldTemplateTitle = (
) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate?.[KIND_MAP[kind]][fieldName]?.title;
}),
[fieldName, kind, nodeId]

View File

@ -4,19 +4,15 @@ import { useAppSelector } from 'app/store/storeHooks';
import { isInvocationNode } from 'features/nodes/types/invocation';
import { getNeedsUpdate } from 'features/nodes/util/node/nodeUpdate';
const selector = createMemoizedSelector(stateSelector, (state) => {
const nodes = state.nodes.nodes;
const templates = state.nodes.nodeTemplates;
const needsUpdate = nodes.filter(isInvocationNode).some((node) => {
const template = templates[node.data.type];
const selector = createMemoizedSelector(stateSelector, (state) =>
state.nodes.nodes.filter(isInvocationNode).some((node) => {
const template = state.nodeTemplates.templates[node.data.type];
if (!template) {
return false;
}
return getNeedsUpdate(node, template);
});
return needsUpdate;
});
})
);
export const useGetNodesNeedUpdate = () => {
const getNeedsUpdate = useAppSelector(selector);

View File

@ -7,12 +7,12 @@ import { useMemo } from 'react';
export const useNodeClassification = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return false;
}
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate?.classification;
}),
[nodeId]

View File

@ -8,9 +8,9 @@ import { useMemo } from 'react';
export const useNodeNeedsUpdate = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
const template = nodes.nodeTemplates[node?.data.type ?? ''];
const template = nodeTemplates.templates[node?.data.type ?? ''];
if (isInvocationNode(node) && template) {
return getNeedsUpdate(node, template);
}

View File

@ -6,9 +6,9 @@ import { useMemo } from 'react';
export const useNodeTemplate = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
const nodeTemplate = nodes.nodeTemplates[node?.data.type ?? ''];
const nodeTemplate = nodeTemplates.templates[node?.data.type ?? ''];
return nodeTemplate;
}),
[nodeId]

View File

@ -9,9 +9,8 @@ export const useNodeTemplateByType = (type: string) => {
() =>
createMemoizedSelector(
stateSelector,
({ nodes }): InvocationTemplate | undefined => {
const nodeTemplate = nodes.nodeTemplates[type];
return nodeTemplate;
({ nodeTemplates }): InvocationTemplate | undefined => {
return nodeTemplates.templates[type];
}
),
[type]

View File

@ -7,13 +7,13 @@ import { useMemo } from 'react';
export const useNodeTemplateTitle = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return false;
}
const nodeTemplate = node
? nodes.nodeTemplates[node.data.type]
? nodeTemplates.templates[node.data.type]
: undefined;
return nodeTemplate?.title;

View File

@ -9,12 +9,12 @@ import { useMemo } from 'react';
export const useOutputFieldNames = (nodeId: string) => {
const selector = useMemo(
() =>
createMemoizedSelector(stateSelector, ({ nodes }) => {
createMemoizedSelector(stateSelector, ({ nodes, nodeTemplates }) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return [];
}
const nodeTemplate = nodes.nodeTemplates[node.data.type];
const nodeTemplate = nodeTemplates.templates[node.data.type];
if (!nodeTemplate) {
return [];
}