Refactor utils file

This commit is contained in:
igorrCarvalho 2024-05-15 21:51:32 -03:00
commit 5e8cec40c9
14 changed files with 175 additions and 162 deletions

View file

@ -19,15 +19,15 @@ import Router from "./routes";
import useAlertStore from "./stores/alertStore"; import useAlertStore from "./stores/alertStore";
import { useDarkStore } from "./stores/darkStore"; import { useDarkStore } from "./stores/darkStore";
import useFlowsManagerStore from "./stores/flowsManagerStore"; import useFlowsManagerStore from "./stores/flowsManagerStore";
import { useGlobalVariablesStore } from "./stores/globalVariables"; import { useGlobalVariablesStore } from "./stores/globalVariablesStore/globalVariables";
import { useStoreStore } from "./stores/storeStore"; import { useStoreStore } from "./stores/storeStore";
import { useTypesStore } from "./stores/typesStore"; import { useTypesStore } from "./stores/typesStore";
export default function App() { export default function App() {
const removeFromTempNotificationList = useAlertStore( const removeFromTempNotificationList = useAlertStore(
(state) => state.removeFromTempNotificationList (state) => state.removeFromTempNotificationList,
); );
const tempNotificationList = useAlertStore( const tempNotificationList = useAlertStore(
(state) => state.tempNotificationList (state) => state.tempNotificationList,
); );
const [fetchError, setFetchError] = useState(false); const [fetchError, setFetchError] = useState(false);
const isLoading = useFlowsManagerStore((state) => state.isLoading); const isLoading = useFlowsManagerStore((state) => state.isLoading);
@ -45,10 +45,10 @@ export default function App() {
const refreshVersion = useDarkStore((state) => state.refreshVersion); const refreshVersion = useDarkStore((state) => state.refreshVersion);
const refreshStars = useDarkStore((state) => state.refreshStars); const refreshStars = useDarkStore((state) => state.refreshStars);
const setGlobalVariables = useGlobalVariablesStore( const setGlobalVariables = useGlobalVariablesStore(
(state) => state.setGlobalVariables (state) => state.setGlobalVariables,
); );
const setUnavailableFields = useGlobalVariablesStore( const setUnavailableFields = useGlobalVariablesStore(
(state) => state.setUnavaliableFields (state) => state.setUnavaliableFields,
); );
const checkHasStore = useStoreStore((state) => state.checkHasStore); const checkHasStore = useStoreStore((state) => state.checkHasStore);
const navigate = useNavigate(); const navigate = useNavigate();
@ -92,8 +92,8 @@ export default function App() {
} }
}); });
/* /*
Abort the request as it isn't needed anymore, the component being Abort the request as it isn't needed anymore, the component being
unmounted. It helps avoid, among other things, the well-known "can't unmounted. It helps avoid, among other things, the well-known "can't
perform a React state update on an unmounted component" warning. perform a React state update on an unmounted component" warning.
*/ */

View file

@ -2,7 +2,7 @@ import { useState } from "react";
import { registerGlobalVariable } from "../../controllers/API"; import { registerGlobalVariable } from "../../controllers/API";
import BaseModal from "../../modals/baseModal"; import BaseModal from "../../modals/baseModal";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useGlobalVariablesStore } from "../../stores/globalVariables"; import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
import { useTypesStore } from "../../stores/typesStore"; import { useTypesStore } from "../../stores/typesStore";
import { ResponseErrorDetailAPI } from "../../types/api"; import { ResponseErrorDetailAPI } from "../../types/api";
import { sortByName } from "../../utils/utils"; import { sortByName } from "../../utils/utils";

View file

@ -2,7 +2,7 @@ import { useEffect } from "react";
import { deleteGlobalVariable } from "../../controllers/API"; import { deleteGlobalVariable } from "../../controllers/API";
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal"; import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useGlobalVariablesStore } from "../../stores/globalVariables"; import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
import { InputGlobalComponentType } from "../../types/components"; import { InputGlobalComponentType } from "../../types/components";
import { cn } from "../../utils/utils"; import { cn } from "../../utils/utils";
import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton"; import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton";

View file

@ -49,7 +49,8 @@ import {
nodeIconsLucide, nodeIconsLucide,
nodeNames, nodeNames,
} from "../../../../utils/styleUtils"; } from "../../../../utils/styleUtils";
import { classNames, groupByFamily } from "../../../../utils/utils"; import { classNames } from "../../../../utils/utils";
import groupByFamily from "./utils/group-by-family";
export default function ParameterComponent({ export default function ParameterComponent({
left, left,

View file

@ -0,0 +1,119 @@
import { APIDataType, TemplateVariableType } from "../../../../../types/api";
import {
groupedObjType,
nodeGroupedObjType,
} from "../../../../../types/components";
import { NodeType } from "../../../../../types/flow";
export default function groupByFamily(
data: APIDataType,
baseClasses: string,
left: boolean,
flow?: NodeType[],
): groupedObjType[] {
const baseClassesSet = new Set(baseClasses.split("\n"));
let arrOfPossibleInputs: Array<{
category: string;
nodes: nodeGroupedObjType[];
full: boolean;
display_name?: string;
}> = [];
let arrOfPossibleOutputs: Array<{
category: string;
nodes: nodeGroupedObjType[];
full: boolean;
display_name?: string;
}> = [];
let checkedNodes = new Map();
const excludeTypes = new Set(["bool", "float", "code", "file", "int"]);
const checkBaseClass = (template: TemplateVariableType) => {
return (
template.type &&
template.show &&
((!excludeTypes.has(template.type) &&
baseClassesSet.has(template.type)) ||
(template.input_types &&
template.input_types.some((inputType) =>
baseClassesSet.has(inputType),
)))
);
};
if (flow) {
// se existir o flow
for (const node of flow) {
// para cada node do flow
if (node!.data!.node!.flow || !node!.data!.node!.template) break; // não faz nada se o node for um group
const nodeData = node.data;
const foundNode = checkedNodes.get(nodeData.type); // verifica se o tipo do node já foi checado
checkedNodes.set(nodeData.type, {
hasBaseClassInTemplate:
foundNode?.hasBaseClassInTemplate ||
Object.values(nodeData.node!.template).some(checkBaseClass),
hasBaseClassInBaseClasses:
foundNode?.hasBaseClassInBaseClasses ||
nodeData.node!.base_classes.some((baseClass) =>
baseClassesSet.has(baseClass),
), //seta como anterior ou verifica se o node tem base class
displayName: nodeData.node?.display_name,
});
}
}
for (const [d, nodes] of Object.entries(data)) {
let tempInputs: nodeGroupedObjType[] = [],
tempOutputs: nodeGroupedObjType[] = [];
for (const [n, node] of Object.entries(nodes!)) {
let foundNode = checkedNodes.get(n);
if (!foundNode) {
foundNode = {
hasBaseClassInTemplate: Object.values(node!.template).some(
checkBaseClass,
),
hasBaseClassInBaseClasses: node!.base_classes.some((baseClass) =>
baseClassesSet.has(baseClass),
),
displayName: node?.display_name,
};
}
if (foundNode.hasBaseClassInTemplate)
tempInputs.push({ node: n, displayName: foundNode.displayName });
if (foundNode.hasBaseClassInBaseClasses)
tempOutputs.push({ node: n, displayName: foundNode.displayName });
}
const totalNodes = Object.keys(nodes!).length;
if (tempInputs.length)
arrOfPossibleInputs.push({
category: d,
nodes: tempInputs,
full: tempInputs.length === totalNodes,
});
if (tempOutputs.length)
arrOfPossibleOutputs.push({
category: d,
nodes: tempOutputs,
full: tempOutputs.length === totalNodes,
});
}
return left
? arrOfPossibleOutputs.map((output) => ({
family: output.category,
type: output.full
? ""
: output.nodes.map((item) => item.node).join(", "),
display_name: "",
}))
: arrOfPossibleInputs.map((input) => ({
family: input.category,
type: input.full ? "" : input.nodes.map((item) => item.node).join(", "),
display_name: input.nodes.map((item) => item.displayName).join(", "),
}));
}

View file

@ -24,8 +24,9 @@ import { postValidatePrompt } from "../../controllers/API";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { genericModalPropsType } from "../../types/components"; import { genericModalPropsType } from "../../types/components";
import { handleKeyDown } from "../../utils/reactflowUtils"; import { handleKeyDown } from "../../utils/reactflowUtils";
import { classNames, varHighlightHTML } from "../../utils/utils"; import { classNames } from "../../utils/utils";
import BaseModal from "../baseModal"; import BaseModal from "../baseModal";
import varHighlightHTML from "./utils/var-highlight-html";
export default function GenericModal({ export default function GenericModal({
field_name = "", field_name = "",
@ -82,7 +83,7 @@ export default function GenericModal({
} }
const filteredWordsHighlight = matches.filter( const filteredWordsHighlight = matches.filter(
(word) => !invalid_chars.includes(word) (word) => !invalid_chars.includes(word),
); );
setWordsHighlight(filteredWordsHighlight); setWordsHighlight(filteredWordsHighlight);
@ -133,7 +134,7 @@ export default function GenericModal({
// to the first key of the custom_fields object // to the first key of the custom_fields object
if (field_name === "") { if (field_name === "") {
field_name = Array.isArray( field_name = Array.isArray(
apiReturn.data?.frontend_node?.custom_fields?.[""] apiReturn.data?.frontend_node?.custom_fields?.[""],
) )
? apiReturn.data?.frontend_node?.custom_fields?.[""][0] ?? "" ? apiReturn.data?.frontend_node?.custom_fields?.[""][0] ?? ""
: apiReturn.data?.frontend_node?.custom_fields?.[""] ?? ""; : apiReturn.data?.frontend_node?.custom_fields?.[""] ?? "";
@ -209,7 +210,7 @@ export default function GenericModal({
<div <div
className={classNames( className={classNames(
!isEdit ? "rounded-lg border" : "", !isEdit ? "rounded-lg border" : "",
"flex h-full w-full" "flex h-full w-full",
)} )}
> >
{type === TypeModal.PROMPT && isEdit && !readonly ? ( {type === TypeModal.PROMPT && isEdit && !readonly ? (

View file

@ -0,0 +1,6 @@
import { IVarHighlightType } from "../../../types/components";
export default function varHighlightHTML({ name }: IVarHighlightType): string {
const html = `<span class="font-semibold chat-message-highlight">{${name}}</span>`;
return html;
}

View file

@ -34,9 +34,10 @@ import {
updateIds, updateIds,
validateSelection, validateSelection,
} from "../../../../utils/reactflowUtils"; } from "../../../../utils/reactflowUtils";
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils"; import { getRandomName } from "../../../../utils/utils";
import ConnectionLineComponent from "../ConnectionLineComponent"; import ConnectionLineComponent from "../ConnectionLineComponent";
import SelectionMenu from "../SelectionMenuComponent"; import SelectionMenu from "../SelectionMenuComponent";
import isWrappedWithClass from "./utils/is-wrapped-with-class";
const nodeTypes = { const nodeTypes = {
genericNode: GenericNode, genericNode: GenericNode,

View file

@ -0,0 +1,4 @@
const isWrappedWithClass = (event: any, className: string | undefined) =>
event.target.closest(`.${className}`);
export default isWrappedWithClass;

View file

@ -11,7 +11,7 @@ import { Badge } from "../../../../components/ui/badge";
import { Card, CardContent } from "../../../../components/ui/card"; import { Card, CardContent } from "../../../../components/ui/card";
import { deleteGlobalVariable } from "../../../../controllers/API"; import { deleteGlobalVariable } from "../../../../controllers/API";
import useAlertStore from "../../../../stores/alertStore"; import useAlertStore from "../../../../stores/alertStore";
import { useGlobalVariablesStore } from "../../../../stores/globalVariables"; import { useGlobalVariablesStore } from "../../../../stores/globalVariablesStore/globalVariables";
import { cn } from "../../../../utils/utils"; import { cn } from "../../../../utils/utils";
export default function GlobalVariablesPage() { export default function GlobalVariablesPage() {

View file

@ -1,6 +1,6 @@
import { create } from "zustand"; import { create } from "zustand";
import { GlobalVariablesStore } from "../types/zustand/globalVariables"; import { GlobalVariablesStore } from "../../types/zustand/globalVariables";
import { getUnavailableFields } from "../utils/utils"; import getUnavailableFields from "./utils/get-unavailable-fields";
export const useGlobalVariablesStore = create<GlobalVariablesStore>( export const useGlobalVariablesStore = create<GlobalVariablesStore>(
(set, get) => ({ (set, get) => ({
@ -45,5 +45,5 @@ export const useGlobalVariablesStore = create<GlobalVariablesStore>(
getVariableId: (name) => { getVariableId: (name) => {
return get().globalVariables[name]?.id; return get().globalVariables[name]?.id;
}, },
}) }),
); );

View file

@ -0,0 +1,13 @@
export default function getUnavailableFields(variables: {
[key: string]: { default_fields?: string[] };
}): { [name: string]: string } {
const unVariables: { [name: string]: string } = {};
Object.keys(variables).forEach((key) => {
if (variables[key].default_fields) {
variables[key].default_fields!.forEach((field) => {
unVariables[field] = key;
});
}
});
return unVariables;
}

View file

@ -36,12 +36,8 @@ import {
unselectAllNodesType, unselectAllNodesType,
updateEdgesHandleIdsType, updateEdgesHandleIdsType,
} from "../types/utils/reactflowUtils"; } from "../types/utils/reactflowUtils";
import { import { createRandomKey, getFieldTitle, toTitleCase } from "./utils";
createRandomKey, import { DESCRIPTIONS } from "../flow_constants";
getFieldTitle,
getRandomDescription,
toTitleCase,
} from "./utils";
const uid = new ShortUniqueId({ length: 5 }); const uid = new ShortUniqueId({ length: 5 });
export function checkChatInput(nodes: Node[]) { export function checkChatInput(nodes: Node[]) {
@ -1286,6 +1282,14 @@ export function downloadFlows() {
}); });
} }
export function getRandomElement<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
export function getRandomDescription(): string {
return getRandomElement(DESCRIPTIONS);
}
export const createNewFlow = ( export const createNewFlow = (
flowData: ReactFlowJsonObject, flowData: ReactFlowJsonObject,
flow: FlowType, flow: FlowType,

View file

@ -15,6 +15,7 @@ import {
} from "../types/components"; } from "../types/components";
import { NodeType } from "../types/flow"; import { NodeType } from "../types/flow";
import { FlowState } from "../types/tabs"; import { FlowState } from "../types/tabs";
import { getRandomElement } from "./reactflowUtils";
export function classNames(...classes: Array<string>): string { export function classNames(...classes: Array<string>): string {
return classes.filter(Boolean).join(" "); return classes.filter(Boolean).join(" ");
@ -90,20 +91,6 @@ export function toTitleCase(
.join(" "); .join(" ");
} }
export function getUnavailableFields(variables: {
[key: string]: { default_fields?: string[] };
}): { [name: string]: string } {
const unVariables: { [name: string]: string } = {};
Object.keys(variables).forEach((key) => {
if (variables[key].default_fields) {
variables[key].default_fields!.forEach((field) => {
unVariables[field] = key;
});
}
});
return unVariables;
}
export const upperCaseWords: string[] = ["llm", "uri"]; export const upperCaseWords: string[] = ["llm", "uri"];
export function checkUpperWords(str: string): string { export function checkUpperWords(str: string): string {
const words = str.split(" ").map((word) => { const words = str.split(" ").map((word) => {
@ -115,133 +102,10 @@ export function checkUpperWords(str: string): string {
return words.join(" "); return words.join(" ");
} }
export const isWrappedWithClass = (event: any, className: string | undefined) =>
event.target.closest(`.${className}`);
export function groupByFamily(
data: APIDataType,
baseClasses: string,
left: boolean,
flow?: NodeType[],
): groupedObjType[] {
const baseClassesSet = new Set(baseClasses.split("\n"));
let arrOfPossibleInputs: Array<{
category: string;
nodes: nodeGroupedObjType[];
full: boolean;
display_name?: string;
}> = [];
let arrOfPossibleOutputs: Array<{
category: string;
nodes: nodeGroupedObjType[];
full: boolean;
display_name?: string;
}> = [];
let checkedNodes = new Map();
const excludeTypes = new Set(["bool", "float", "code", "file", "int"]);
const checkBaseClass = (template: TemplateVariableType) => {
return (
template.type &&
template.show &&
((!excludeTypes.has(template.type) &&
baseClassesSet.has(template.type)) ||
(template.input_types &&
template.input_types.some((inputType) =>
baseClassesSet.has(inputType),
)))
);
};
if (flow) {
// se existir o flow
for (const node of flow) {
// para cada node do flow
if (node!.data!.node!.flow || !node!.data!.node!.template) break; // não faz nada se o node for um group
const nodeData = node.data;
const foundNode = checkedNodes.get(nodeData.type); // verifica se o tipo do node já foi checado
checkedNodes.set(nodeData.type, {
hasBaseClassInTemplate:
foundNode?.hasBaseClassInTemplate ||
Object.values(nodeData.node!.template).some(checkBaseClass),
hasBaseClassInBaseClasses:
foundNode?.hasBaseClassInBaseClasses ||
nodeData.node!.base_classes.some((baseClass) =>
baseClassesSet.has(baseClass),
), //seta como anterior ou verifica se o node tem base class
displayName: nodeData.node?.display_name,
});
}
}
for (const [d, nodes] of Object.entries(data)) {
let tempInputs: nodeGroupedObjType[] = [],
tempOutputs: nodeGroupedObjType[] = [];
for (const [n, node] of Object.entries(nodes!)) {
let foundNode = checkedNodes.get(n);
if (!foundNode) {
foundNode = {
hasBaseClassInTemplate: Object.values(node!.template).some(
checkBaseClass,
),
hasBaseClassInBaseClasses: node!.base_classes.some((baseClass) =>
baseClassesSet.has(baseClass),
),
displayName: node?.display_name,
};
}
if (foundNode.hasBaseClassInTemplate)
tempInputs.push({ node: n, displayName: foundNode.displayName });
if (foundNode.hasBaseClassInBaseClasses)
tempOutputs.push({ node: n, displayName: foundNode.displayName });
}
const totalNodes = Object.keys(nodes!).length;
if (tempInputs.length)
arrOfPossibleInputs.push({
category: d,
nodes: tempInputs,
full: tempInputs.length === totalNodes,
});
if (tempOutputs.length)
arrOfPossibleOutputs.push({
category: d,
nodes: tempOutputs,
full: tempOutputs.length === totalNodes,
});
}
return left
? arrOfPossibleOutputs.map((output) => ({
family: output.category,
type: output.full
? ""
: output.nodes.map((item) => item.node).join(", "),
display_name: "",
}))
: arrOfPossibleInputs.map((input) => ({
family: input.category,
type: input.full ? "" : input.nodes.map((item) => item.node).join(", "),
display_name: input.nodes.map((item) => item.displayName).join(", "),
}));
}
export function buildInputs(): string { export function buildInputs(): string {
return '{"input_value": "message"}'; return '{"input_value": "message"}';
} }
export function getRandomElement<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
export function getRandomDescription(): string {
return getRandomElement(DESCRIPTIONS);
}
export function getRandomName( export function getRandomName(
retry: number = 0, retry: number = 0,
noSpace: boolean = false, noSpace: boolean = false,