refactor: Reduce errors on types

This commit is contained in:
Igor Carvalho 2023-08-02 19:08:39 -03:00
commit 5e65397773
34 changed files with 193 additions and 182 deletions

View file

@ -40,13 +40,13 @@ export default function ParameterComponent({
info = "", info = "",
}: ParameterComponentType): JSX.Element { }: ParameterComponentType): JSX.Element {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const refHtml = useRef(null); const refHtml = useRef<HTMLDivElement>(null);
const infoHtml = useRef(null); const infoHtml = useRef<HTMLDivElement>(null);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0); const [position, setPosition] = useState(0);
const { setTabsState, tabId, save, flows } = useContext(TabsContext); const { setTabsState, tabId, save, flows } = useContext(TabsContext);
const flow = flows.find((f) => f.id === tabId).data?.nodes ?? null; const flow = flows.find((f) => f.id === tabId)?.data?.nodes ?? null;
// Update component position // Update component position
useEffect(() => { useEffect(() => {
@ -68,7 +68,7 @@ export default function ParameterComponent({
const handleOnNewValue = (newValue: string | string[] | boolean): void => { const handleOnNewValue = (newValue: string | string[] | boolean): void => {
let newData = cloneDeep(data); let newData = cloneDeep(data);
newData.node.template[name].value = newValue; newData.node!.template[name].value = newValue;
setData(newData); setData(newData);
// Set state to pending // Set state to pending
setTabsState((prev) => { setTabsState((prev) => {
@ -99,6 +99,7 @@ export default function ParameterComponent({
function renderTooltips() { function renderTooltips() {
let groupedObj = groupByFamily(myData, tooltipTitle, left, flow); let groupedObj = groupByFamily(myData, tooltipTitle, left, flow);
console.log(groupedObj)
if (groupedObj && groupedObj.length > 0) { if (groupedObj && groupedObj.length > 0) {
refHtml.current = groupedObj.map((item, i) => { refHtml.current = groupedObj.map((item, i) => {
@ -207,7 +208,7 @@ export default function ParameterComponent({
position={left ? Position.Left : Position.Right} position={left ? Position.Left : Position.Right}
id={id} id={id}
isValidConnection={(connection) => isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance) isValidConnection(connection, reactFlowInstance!)
} }
className={classNames( className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ", left ? "-ml-0.5 " : "-mr-0.5 ",
@ -255,7 +256,7 @@ export default function ParameterComponent({
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<ToggleShadComponent <ToggleShadComponent
disabled={disabled} disabled={disabled}
enabled={data.node.template[name].value ?? false} enabled={data.node?.template[name].value ?? false}
setEnabled={(t) => { setEnabled={(t) => {
handleOnNewValue(t); handleOnNewValue(t);
}} }}
@ -283,7 +284,7 @@ export default function ParameterComponent({
) : left === true && type === "code" ? ( ) : left === true && type === "code" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<CodeAreaComponent <CodeAreaComponent
dynamic={data.node.template[name].dynamic ?? false} dynamic={data.node?.template[name].dynamic ?? false}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
data.node = nodeClass; data.node = nodeClass;
}} }}
@ -302,7 +303,7 @@ export default function ParameterComponent({
fileTypes={data.node?.template[name].fileTypes} fileTypes={data.node?.template[name].fileTypes}
suffixes={data.node?.template[name].suffixes} suffixes={data.node?.template[name].suffixes}
onFileChange={(t: string) => { onFileChange={(t: string) => {
data.node.template[name].file_path = t; data.node!.template[name].file_path = t;
save(); save();
}} }}
></InputFileComponent> ></InputFileComponent>

View file

@ -13,6 +13,7 @@ import { cleanEdges } from "../../utils/reactflowUtils";
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
import { classNames, toTitleCase } from "../../utils/utils"; import { classNames, toTitleCase } from "../../utils/utils";
import ParameterComponent from "./components/parameterComponent"; import ParameterComponent from "./components/parameterComponent";
import { validationStatusType } from "../../types/components";
export default function GenericNode({ export default function GenericNode({
data: olddata, data: olddata,
@ -26,7 +27,7 @@ export default function GenericNode({
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const { types, deleteNode, reactFlowInstance } = useContext(typesContext); const { types, deleteNode, reactFlowInstance } = useContext(typesContext);
const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
const [validationStatus, setValidationStatus] = useState(null); const [validationStatus, setValidationStatus] = useState<validationStatusType | null>(null);
// State for outline color // State for outline color
const { sseData, isBuilding } = useSSE(); const { sseData, isBuilding } = useSSE();
useEffect(() => { useEffect(() => {
@ -77,7 +78,7 @@ export default function GenericNode({
"generic-node-div" "generic-node-div"
)} )}
> >
{data.node.beta && ( {data.node?.beta && (
<div className="beta-badge-wrapper"> <div className="beta-badge-wrapper">
<div className="beta-badge-content">BETA</div> <div className="beta-badge-content">BETA</div>
</div> </div>
@ -114,6 +115,7 @@ export default function GenericNode({
</span> </span>
) : ( ) : (
<div className="max-h-96 overflow-auto"> <div className="max-h-96 overflow-auto">
{typeof validationStatus.params === "string" {typeof validationStatus.params === "string"
? validationStatus.params ? validationStatus.params
.split("\n") .split("\n")
@ -160,16 +162,16 @@ export default function GenericNode({
<div className="generic-node-desc-text">{data.node?.description}</div> <div className="generic-node-desc-text">{data.node?.description}</div>
<> <>
{Object.keys(data.node.template) {Object.keys(data.node!.template)
.filter((t) => t.charAt(0) !== "_") .filter((t) => t.charAt(0) !== "_")
.map((t: string, idx) => ( .map((t: string, idx) => (
<div key={idx}> <div key={idx}>
{data.node.template[t].show && {data.node!.template[t].show &&
!data.node.template[t].advanced ? ( !data.node!.template[t].advanced ? (
<ParameterComponent <ParameterComponent
key={ key={
(data.node.template[t].input_types?.join(";") ?? (data.node!.template[t].input_types?.join(";") ??
data.node.template[t].type) + data.node!.template[t].type) +
"|" + "|" +
t + t +
"|" + "|" +
@ -178,8 +180,8 @@ export default function GenericNode({
data={data} data={data}
setData={setData} setData={setData}
color={ color={
nodeColors[types[data.node?.template[t].type]] ?? nodeColors[types[data.node?.template[t].type!]] ??
nodeColors[data.node?.template[t].type] ?? nodeColors[data.node?.template[t].type!] ??
nodeColors.unknown nodeColors.unknown
} }
title={ title={
@ -215,14 +217,14 @@ export default function GenericNode({
))} ))}
<div <div
className={classNames( className={classNames(
Object.keys(data.node.template).length < 1 ? "hidden" : "", Object.keys(data.node!.template).length < 1 ? "hidden" : "",
"flex-max-width justify-center" "flex-max-width justify-center"
)} )}
> >
{" "} {" "}
</div> </div>
<ParameterComponent <ParameterComponent
key={[data.type, data.id, ...data.node.base_classes].join("|")} key={[data.type, data.id, ...data.node!.base_classes].join("|")}
data={data} data={data}
setData={setData} setData={setData}
color={nodeColors[types[data.type]] ?? nodeColors.unknown} color={nodeColors[types[data.type]] ?? nodeColors.unknown}
@ -232,7 +234,7 @@ export default function GenericNode({
: data.type : data.type
} }
tooltipTitle={data.node?.base_classes.join("\n")} tooltipTitle={data.node?.base_classes.join("\n")}
id={[data.type, data.id, ...data.node.base_classes].join("|")} id={[data.type, data.id, ...data.node!.base_classes].join("|")}
type={data.node?.base_classes.join("|")} type={data.node?.base_classes.join("|")}
left={false} left={false}
/> />

View file

@ -29,7 +29,7 @@ export default function AccordionComponent({
} }
function handleClick(): void { function handleClick(): void {
value === "" ? setValue(keyValue) : setValue(""); value === "" ? setValue(keyValue!) : setValue("");
} }
return ( return (
@ -40,7 +40,7 @@ export default function AccordionComponent({
value={value} value={value}
onValueChange={setValue} onValueChange={setValue}
> >
<AccordionItem value={keyValue} className="border-b"> <AccordionItem value={keyValue!} className="border-b">
<AccordionTrigger <AccordionTrigger
onClick={() => { onClick={() => {
handleClick(); handleClick();

View file

@ -18,7 +18,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
updateFlow, updateFlow,
}: InputProps): JSX.Element => { }: InputProps): JSX.Element => {
const [isMaxLength, setIsMaxLength] = useState(false); const [isMaxLength, setIsMaxLength] = useState(false);
const nameLists = useRef([]); const nameLists = useRef<string[]>([]);
useEffect(() => { useEffect(() => {
readFlowsFromDatabase().then((flows) => { readFlowsFromDatabase().then((flows) => {
flows.forEach((flow) => { flows.forEach((flow) => {
@ -47,7 +47,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
); );
const handleDescriptionChange = (event: ChangeEvent<HTMLTextAreaElement>) => { const handleDescriptionChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
flows.find((f) => f.id === tabId).description = event.target.value; flows.find((f) => f.id === tabId)!.description = event.target.value;
setDesc(flows.find((f) => f.id === tabId)?.description); setDesc(flows.find((f) => f.id === tabId)?.description);
setDescription(event.target.value); setDescription(event.target.value);
}; };

View file

@ -5,14 +5,14 @@ export default function RadialProgressComponent({
color, color,
}: RadialProgressType): JSX.Element { }: RadialProgressType): JSX.Element {
const style = { const style = {
"--value": value * 100, "--value": value! * 100,
"--size": "1.5rem", "--size": "1.5rem",
"--thickness": "2px", "--thickness": "2px",
} as React.CSSProperties; } as React.CSSProperties;
return ( return (
<div className={"radial-progress " + color} style={style}> <div className={"radial-progress " + color} style={style}>
<strong className="text-[8px]">{Math.trunc(value * 100)}%</strong> <strong className="text-[8px]">{Math.trunc(value! * 100)}%</strong>
</div> </div>
); );
} }

View file

@ -27,7 +27,7 @@ const TooltipReact: FC<TooltipProps> = ({
content={content} content={content}
className={classNames( className={classNames(
"z-[9999] !bg-white !text-xs !font-normal !text-foreground !opacity-100 !shadow-md", "z-[9999] !bg-white !text-xs !font-normal !text-foreground !opacity-100 !shadow-md",
className className!
)} )}
place={position} place={position}
clickable={clickable} clickable={clickable}

View file

@ -36,7 +36,7 @@ export default function BuildTrigger({
if (isBuilding) { if (isBuilding) {
return; return;
} }
const errors = validateNodes(reactFlowInstance); const errors = validateNodes(reactFlowInstance!);
if (errors.length > 0) { if (errors.length > 0) {
setErrorData({ setErrorData({
title: "Oops! Looks like you missed something", title: "Oops! Looks like you missed something",

View file

@ -48,7 +48,7 @@ export default function Chat({ flow }: ChatType): JSX.Element {
useEffect(() => { useEffect(() => {
const prevNodes = prevNodesRef.current; const prevNodes = prevNodesRef.current;
const currentNodes = nodes.map((node: NodeType) => const currentNodes = nodes.map((node: NodeType) =>
_.cloneDeep(node.data.node.template) _.cloneDeep(node.data.node?.template)
); );
if ( if (
tabsState && tabsState &&
@ -63,7 +63,7 @@ export default function Chat({ flow }: ChatType): JSX.Element {
tabsState[flow.id] && tabsState[flow.id] &&
tabsState[flow.id].formKeysData && tabsState[flow.id].formKeysData &&
tabsState[flow.id].formKeysData.input_keys && tabsState[flow.id].formKeysData.input_keys &&
Object.keys(tabsState[flow.id].formKeysData.input_keys).length > 0 Object.keys(tabsState[flow.id].formKeysData.input_keys!).length > 0
) { ) {
setCanOpen(true); setCanOpen(true);
} else { } else {

View file

@ -33,7 +33,7 @@ export default function CodeAreaComponent({
dynamic={dynamic} dynamic={dynamic}
value={myValue} value={myValue}
nodeClass={nodeClass} nodeClass={nodeClass}
setNodeClass={setNodeClass} setNodeClass={setNodeClass!}
setValue={(t: string) => { setValue={(t: string) => {
setMyValue(t); setMyValue(t);
onChange(t); onChange(t);

View file

@ -43,7 +43,7 @@ export default function CodeTabsComponent({
}: codeTabsPropsType) { }: codeTabsPropsType) {
const [isCopied, setIsCopied] = useState<Boolean>(false); const [isCopied, setIsCopied] = useState<Boolean>(false);
const [data, setData] = useState(flow ? flow["data"]["nodes"] : null); const [data, setData] = useState(flow ? flow["data"]["nodes"] : null);
const [openAccordion, setOpenAccordion] = useState([]); const [openAccordion, setOpenAccordion] = useState<string[]>([]);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
useEffect(() => { useEffect(() => {
@ -89,8 +89,8 @@ export default function CodeTabsComponent({
}; };
function openAccordions() { function openAccordions() {
let accordionsToOpen = []; let accordionsToOpen: string[] = [];
tweaks?.tweak.current.forEach((el) => { tweaks?.tweak!.current.forEach((el) => {
Object.keys(el).forEach((key) => { Object.keys(el).forEach((key) => {
if (Object.keys(el[key]).length > 0) { if (Object.keys(el[key]).length > 0) {
accordionsToOpen.push(key); accordionsToOpen.push(key);
@ -190,7 +190,7 @@ export default function CodeTabsComponent({
> >
{data?.map((t: any, index) => ( {data?.map((t: any, index) => (
<div className="px-3" key={index}> <div className="px-3" key={index}>
{tweaks?.tweaksList.current.includes(t["data"]["id"]) && ( {tweaks?.tweaksList!.current.includes(t["data"]["id"]) && (
<AccordionComponent <AccordionComponent
trigger={t["data"]["id"]} trigger={t["data"]["id"]}
open={openAccordion} open={openAccordion}
@ -261,14 +261,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -278,7 +278,7 @@ export default function CodeTabsComponent({
) : t.data.node.template[n] ) : t.data.node.template[n]
.multiline ? ( .multiline ? (
<ShadTooltip <ShadTooltip
content={tweaks.buildContent( content={tweaks.buildContent!(
t.data.node.template[n] t.data.node.template[n]
.value .value
)} )}
@ -303,14 +303,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node t.data.node
@ -342,14 +342,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -371,14 +371,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = e; ].value = e;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
e, e,
t.data.node.template[n] t.data.node.template[n]
@ -391,7 +391,7 @@ export default function CodeTabsComponent({
) : t.data.node.template[n].type === ) : t.data.node.template[n].type ===
"file" ? ( "file" ? (
<ShadTooltip <ShadTooltip
content={tweaks.buildContent( content={tweaks.buildContent!(
!t.data.node.template[n] !t.data.node.template[n]
.value || .value ||
t.data.node.template[n] t.data.node.template[n]
@ -447,14 +447,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -478,14 +478,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -521,14 +521,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -539,7 +539,7 @@ export default function CodeTabsComponent({
) : t.data.node.template[n].type === ) : t.data.node.template[n].type ===
"prompt" ? ( "prompt" ? (
<ShadTooltip <ShadTooltip
content={tweaks.buildContent( content={tweaks.buildContent!(
!t.data.node.template[n] !t.data.node.template[n]
.value || .value ||
t.data.node.template[n] t.data.node.template[n]
@ -567,14 +567,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -586,8 +586,8 @@ export default function CodeTabsComponent({
) : t.data.node.template[n].type === ) : t.data.node.template[n].type ===
"code" ? ( "code" ? (
<ShadTooltip <ShadTooltip
content={tweaks.buildContent( content={tweaks.buildContent!(
tweaks.getValue( tweaks.getValue!(
t.data.node.template[n] t.data.node.template[n]
.value, .value,
t.data, t.data,
@ -613,14 +613,14 @@ export default function CodeTabsComponent({
setData((old) => { setData((old) => {
let newInputList = let newInputList =
cloneDeep(old); cloneDeep(old);
newInputList[ newInputList![
index index
].data.node.template[ ].data.node.template[
n n
].value = k; ].value = k;
return newInputList; return newInputList;
}); });
tweaks.buildTweakObject( tweaks.buildTweakObject!(
t["data"]["id"], t["data"]["id"],
k, k,
t.data.node.template[n] t.data.node.template[n]
@ -646,7 +646,7 @@ export default function CodeTabsComponent({
</AccordionComponent> </AccordionComponent>
)} )}
{tweaks?.tweaksList.current.length === 0 && ( {tweaks?.tweaksList!.current.length === 0 && (
<> <>
<div className="pt-3"> <div className="pt-3">
No tweaks are available for this flow. No tweaks are available for this flow.

View file

@ -26,7 +26,7 @@ export const MenuBar = ({ flows, tabId }: menuBarPropsType): JSX.Element => {
function handleAddFlow() { function handleAddFlow() {
try { try {
addFlow(null, true).then((id) => { addFlow(null!, true).then((id) => {
navigate("/flow/" + id); navigate("/flow/" + id);
}); });
// saveFlowStyleInDataBase(); // saveFlowStyleInDataBase();
@ -46,7 +46,7 @@ export const MenuBar = ({ flows, tabId }: menuBarPropsType): JSX.Element => {
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button asChild variant="primary" size="sm"> <Button asChild variant="primary" size="sm">
<div className="header-menu-bar-display"> <div className="header-menu-bar-display">
<div className="header-menu-flow-name">{current_flow.name}</div> <div className="header-menu-flow-name">{current_flow!.name}</div>
<IconComponent name="ChevronDown" className="h-4 w-4" /> <IconComponent name="ChevronDown" className="h-4 w-4" />
</div> </div>
</Button> </Button>

View file

@ -23,9 +23,9 @@ export default function PromptAreaComponent({
useEffect(() => { useEffect(() => {
if (value !== "" && !editNode) { if (value !== "" && !editNode) {
postValidatePrompt(field_name, value, nodeClass).then((apiReturn) => { postValidatePrompt(field_name!, value, nodeClass!).then((apiReturn) => {
if (apiReturn.data) { if (apiReturn.data) {
setNodeClass(apiReturn.data.frontend_node); setNodeClass!(apiReturn.data.frontend_node);
// need to update reactFlowInstance to re-render the nodes. // need to update reactFlowInstance to re-render the nodes.
} }
}); });

View file

@ -10,13 +10,13 @@ export const darkContext = createContext<darkContextType>(initialValue);
export function DarkProvider({ children }) { export function DarkProvider({ children }) {
const [dark, setDark] = useState( const [dark, setDark] = useState(
JSON.parse(window.localStorage.getItem("isDark")) ?? false JSON.parse(window.localStorage.getItem("isDark")!) ?? false
); );
useEffect(() => { useEffect(() => {
if (dark) { if (dark) {
document.getElementById("body").classList.add("dark"); document.getElementById("body")!.classList.add("dark");
} else { } else {
document.getElementById("body").classList.remove("dark"); document.getElementById("body")!.classList.remove("dark");
} }
window.localStorage.setItem("isDark", dark.toString()); window.localStorage.setItem("isDark", dark.toString());
}, [dark]); }, [dark]);

View file

@ -153,11 +153,11 @@ export function TabsProvider({ children }: { children: ReactNode }) {
} }
function updateDisplay_name(node: NodeType, template: APIClassType) { function updateDisplay_name(node: NodeType, template: APIClassType) {
node.data.node.display_name = template["display_name"] || node.data.type; node.data.node!.display_name = template["display_name"] || node.data.type;
} }
function updateNodeDocumentation(node: NodeType, template: APIClassType) { function updateNodeDocumentation(node: NodeType, template: APIClassType) {
node.data.node.documentation = template["documentation"]; node.data.node!.documentation = template["documentation"];
} }
function processFlowNodes(flow) { function processFlowNodes(flow) {
@ -180,7 +180,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
} }
function updateNodeBaseClasses(node: NodeType, template: APIClassType) { function updateNodeBaseClasses(node: NodeType, template: APIClassType) {
node.data.node.base_classes = template["base_classes"]; node.data.node!.base_classes = template["base_classes"];
} }
function updateNodeEdges( function updateNodeEdges(
@ -191,7 +191,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
flow.data.edges.forEach((edge) => { flow.data.edges.forEach((edge) => {
if (edge.source === node.id) { if (edge.source === node.id) {
edge.sourceHandle = edge.sourceHandle edge.sourceHandle = edge.sourceHandle
.split("|") ?.split("|")
.slice(0, 2) .slice(0, 2)
.concat(template["base_classes"]) .concat(template["base_classes"])
.join("|"); .join("|");
@ -200,13 +200,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
} }
function updateNodeDescription(node: NodeType, template: APIClassType) { function updateNodeDescription(node: NodeType, template: APIClassType) {
node.data.node.description = template["description"]; node.data.node!.description = template["description"];
} }
function updateNodeTemplate(node: NodeType, template: APIClassType) { function updateNodeTemplate(node: NodeType, template: APIClassType) {
node.data.node.template = updateTemplate( node.data.node!.template = updateTemplate(
template["template"] as unknown as APITemplateType, template["template"] as unknown as APITemplateType,
node.data.node.template as APITemplateType node.data.node!.template as APITemplateType
); );
} }
@ -241,7 +241,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
link.download = `${ link.download = `${
flowName && flowName != "" flowName && flowName != ""
? flowName ? flowName
: flows.find((f) => f.id === tabId).name : flows.find((f) => f.id === tabId)!.name
}.json`; }.json`;
// simulate a click on the link element to trigger the download // simulate a click on the link element to trigger the download
@ -293,10 +293,10 @@ export function TabsProvider({ children }: { children: ReactNode }) {
input.onchange = (e: Event) => { input.onchange = (e: Event) => {
// check if the file type is application/json // check if the file type is application/json
if ( if (
(e.target as HTMLInputElement).files[0].type === "application/json" (e.target as HTMLInputElement).files![0].type === "application/json"
) { ) {
// get the file from the file input // get the file from the file input
const currentfile = (e.target as HTMLInputElement).files[0]; const currentfile = (e.target as HTMLInputElement).files![0];
// read the file as text // read the file as text
currentfile.text().then((text) => { currentfile.text().then((text) => {
// parse the text into a JSON object // parse the text into a JSON object
@ -318,9 +318,9 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// add a change event listener to the file input // add a change event listener to the file input
input.onchange = (e: Event) => { input.onchange = (e: Event) => {
// check if the file type is application/json // check if the file type is application/json
if ((e.target as HTMLInputElement).files[0].type === "application/json") { if ((e.target as HTMLInputElement).files![0].type === "application/json") {
// get the file from the file input // get the file from the file input
const file = (e.target as HTMLInputElement).files[0]; const file = (e.target as HTMLInputElement).files![0];
// read the file as text // read the file as text
const formData = new FormData(); const formData = new FormData();
formData.append("file", file); formData.append("file", file);
@ -357,8 +357,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
let minimumX = Infinity; let minimumX = Infinity;
let minimumY = Infinity; let minimumY = Infinity;
let idsMap = {}; let idsMap = {};
let nodes = reactFlowInstance.getNodes(); let nodes = reactFlowInstance!.getNodes();
let edges = reactFlowInstance.getEdges(); let edges = reactFlowInstance!.getEdges();
selectionInstance.nodes.forEach((n) => { selectionInstance.nodes.forEach((n) => {
if (n.position.y < minimumY) { if (n.position.y < minimumY) {
minimumY = n.position.y; minimumY = n.position.y;
@ -369,8 +369,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
}); });
const insidePosition = position.paneX const insidePosition = position.paneX
? { x: position.paneX + position.x, y: position.paneY + position.y } ? { x: position.paneX + position.x, y: position.paneY! + position.y }
: reactFlowInstance.project({ x: position.x, y: position.y }); : reactFlowInstance!.project({ x: position.x, y: position.y });
selectionInstance.nodes.forEach((n: NodeType) => { selectionInstance.nodes.forEach((n: NodeType) => {
// Generate a unique node ID // Generate a unique node ID
@ -396,7 +396,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
.map((e) => ({ ...e, selected: false })) .map((e) => ({ ...e, selected: false }))
.concat({ ...newNode, selected: false }); .concat({ ...newNode, selected: false });
}); });
reactFlowInstance.setNodes(nodes); reactFlowInstance!.setNodes(nodes);
selectionInstance.edges.forEach((e) => { selectionInstance.edges.forEach((e) => {
let source = idsMap[e.source]; let source = idsMap[e.source];
@ -436,13 +436,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
edges.map((e) => ({ ...e, selected: false })) edges.map((e) => ({ ...e, selected: false }))
); );
}); });
reactFlowInstance.setEdges(edges); reactFlowInstance!.setEdges(edges);
} }
const addFlow = async ( const addFlow = async (
flow?: FlowType, flow?: FlowType,
newProject?: Boolean newProject?: Boolean
): Promise<String> => { ): Promise<String | undefined> => {
if (newProject) { if (newProject) {
let flowData = extractDataFromFlow(flow); let flowData = extractDataFromFlow(flow);
if (flowData.description == "") { if (flowData.description == "") {
@ -475,7 +475,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
} }
} else { } else {
paste( paste(
{ nodes: flow.data.nodes, edges: flow.data.edges }, { nodes: flow!.data.nodes, edges: flow!.data.edges },
{ x: 10, y: 10 } { x: 10, y: 10 }
); );
} }

View file

@ -69,7 +69,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
); );
} }
// Clear the interval if successful. // Clear the interval if successful.
clearInterval(intervalId); clearInterval(intervalId!);
} catch (error) { } catch (error) {
console.error("An error has occurred while fetching types."); console.error("An error has occurred while fetching types.");
} }
@ -80,18 +80,18 @@ export function TypesProvider({ children }: { children: ReactNode }) {
return () => { return () => {
// This will clear the interval when the component unmounts, or when the dependencies of the useEffect hook change. // This will clear the interval when the component unmounts, or when the dependencies of the useEffect hook change.
clearInterval(intervalId); clearInterval(intervalId!);
// Indicate that the component has been unmounted. // Indicate that the component has been unmounted.
isMounted = false; isMounted = false;
}; };
}, []); }, []);
function deleteNode(idx: string) { function deleteNode(idx: string) {
reactFlowInstance.setNodes( reactFlowInstance!.setNodes(
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx) reactFlowInstance!.getNodes().filter((n: Node) => n.id !== idx)
); );
reactFlowInstance.setEdges( reactFlowInstance!.setEdges(
reactFlowInstance reactFlowInstance!
.getEdges() .getEdges()
.filter((ns) => ns.source !== idx && ns.target !== idx) .filter((ns) => ns.source !== idx && ns.target !== idx)
); );

View file

@ -16,7 +16,7 @@ function ApiInterceptor() {
const interceptor = api.interceptors.response.use( const interceptor = api.interceptors.response.use(
(response) => response, (response) => response,
async (error: AxiosError) => { async (error: AxiosError) => {
if (URL_EXCLUDED_FROM_ERROR_RETRIES.includes(error.config?.url)) { if (URL_EXCLUDED_FROM_ERROR_RETRIES.includes(error.config?.url!)) {
return Promise.reject(error); return Promise.reject(error);
} }
let retryCount = 0; let retryCount = 0;
@ -25,7 +25,7 @@ function ApiInterceptor() {
await sleep(5000); // Sleep for 5 seconds await sleep(5000); // Sleep for 5 seconds
retryCount++; retryCount++;
try { try {
const response = await axios.request(error.config); const response = await axios.request(error.config!);
return response; return response;
} catch (error) { } catch (error) {
if (retryCount === 3) { if (retryCount === 3) {

View file

@ -1,9 +1,9 @@
import React, { forwardRef } from "react"; import React, { forwardRef } from "react";
import { ReactComponent as PowerPointSVG } from "./PowerPoint.svg"; import SvgPowerPoint from "./PowerPoint";
export const PowerPointIcon = forwardRef< export const PowerPointIcon = forwardRef<
SVGSVGElement, SVGSVGElement,
React.PropsWithChildren<{}> React.PropsWithChildren<{}>
>((props, ref) => { >((props, ref) => {
return <PowerPointSVG ref={ref} {...props} />; return <SvgPowerPoint ref={ref} {...props} />;
}); });

View file

@ -55,7 +55,7 @@ const EditNodeModal = forwardRef(
function changeAdvanced(n: string): void { function changeAdvanced(n: string): void {
setMyData((old) => { setMyData((old) => {
let newData = cloneDeep(old); let newData = cloneDeep(old);
newData.node.template[n].advanced = !newData.node.template[n].advanced; newData.node!.template[n].advanced = !newData.node!.template[n].advanced;
return newData; return newData;
}); });
} }
@ -66,7 +66,7 @@ const EditNodeModal = forwardRef(
) => { ) => {
setMyData((old) => { setMyData((old) => {
let newData = cloneDeep(old); let newData = cloneDeep(old);
newData.node.template[name].value = newValue; newData.node!.template[name].value = newValue;
return newData; return newData;
}); });
}; };
@ -78,7 +78,7 @@ const EditNodeModal = forwardRef(
return ( return (
<BaseModal size="large-h-full" open={modalOpen} setOpen={setModalOpen}> <BaseModal size="large-h-full" open={modalOpen} setOpen={setModalOpen}>
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={myData.node?.description}> <BaseModal.Header description={myData.node?.description!}>
<span className="pr-2">{myData.type}</span> <span className="pr-2">{myData.type}</span>
<Badge variant="secondary">ID: {myData.id}</Badge> <Badge variant="secondary">ID: {myData.id}</Badge>
</BaseModal.Header> </BaseModal.Header>
@ -113,7 +113,7 @@ const EditNodeModal = forwardRef(
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody className="p-0"> <TableBody className="p-0">
{Object.keys(myData.node.template) {Object.keys(myData.node!.template)
.filter( .filter(
(t) => (t) =>
t.charAt(0) !== "_" && t.charAt(0) !== "_" &&
@ -158,7 +158,7 @@ const EditNodeModal = forwardRef(
value={ value={
myData.node.template[n].value ?? "" myData.node.template[n].value ?? ""
} }
onChange={(t: string) => { onChange={(t: string | string[]) => {
handleOnNewValue(t, n); handleOnNewValue(t, n);
}} }}
/> />
@ -233,7 +233,7 @@ const EditNodeModal = forwardRef(
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
value={myData.node.template[n].value ?? ""} value={myData.node.template[n].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
handleOnNewValue(t, n); handleOnNewValue(t, n);
}} }}
fileTypes={ fileTypes={
@ -241,7 +241,7 @@ const EditNodeModal = forwardRef(
} }
suffixes={myData.node.template[n].suffixes} suffixes={myData.node.template[n].suffixes}
onFileChange={(t: string) => { onFileChange={(t: string) => {
data.node.template[n].file_path = t; data.node!.template[n].file_path = t;
}} }}
></InputFileComponent> ></InputFileComponent>
</div> </div>
@ -256,7 +256,7 @@ const EditNodeModal = forwardRef(
myData.node = nodeClass; myData.node = nodeClass;
}} }}
value={myData.node.template[n].value ?? ""} value={myData.node.template[n].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
handleOnNewValue(t, n); handleOnNewValue(t, n);
}} }}
/> />
@ -265,7 +265,7 @@ const EditNodeModal = forwardRef(
<div className="mx-auto"> <div className="mx-auto">
<CodeAreaComponent <CodeAreaComponent
dynamic={ dynamic={
data.node.template[n].dynamic ?? false data.node!.template[n].dynamic ?? false
} }
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
data.node = nodeClass; data.node = nodeClass;
@ -274,7 +274,7 @@ const EditNodeModal = forwardRef(
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={myData.node.template[n].value ?? ""} value={myData.node.template[n].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
handleOnNewValue(t, n); handleOnNewValue(t, n);
}} }}
/> />

View file

@ -75,7 +75,7 @@ export default function ModalField({
<TextAreaComponent <TextAreaComponent
disabled={false} disabled={false}
value={data.node.template[name].value ?? ""} value={data.node.template[name].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
data.node.template[name].value = t; data.node.template[name].value = t;
}} }}
/> />
@ -136,7 +136,7 @@ export default function ModalField({
<InputFileComponent <InputFileComponent
disabled={false} disabled={false}
value={data.node.template[name].value ?? ""} value={data.node.template[name].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
data.node.template[name].value = t; data.node.template[name].value = t;
}} }}
fileTypes={data.node.template[name].fileTypes} fileTypes={data.node.template[name].fileTypes}
@ -152,7 +152,7 @@ export default function ModalField({
field_name={name} field_name={name}
disabled={false} disabled={false}
value={data.node.template[name].value ?? ""} value={data.node.template[name].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
data.node.template[name].value = t; data.node.template[name].value = t;
}} }}
/> />
@ -167,7 +167,7 @@ export default function ModalField({
nodeClass={data.node} nodeClass={data.node}
disabled={false} disabled={false}
value={data.node.template[name].value ?? ""} value={data.node.template[name].value ?? ""}
onChange={(t: string) => { onChange={(t: string | string[]) => {
data.node.template[name].value = t; data.node.template[name].value = t;
}} }}
/> />

View file

@ -28,16 +28,16 @@ export default function CodeAreaModal({
const [code, setCode] = useState(value); const [code, setCode] = useState(value);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const [height, setHeight] = useState(null); const [height, setHeight] = useState<string | null>(null);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const [error, setError] = useState<{ const [error, setError] = useState<{
detail: { error: string; traceback: string }; detail: { error: string | undefined; traceback: string | undefined };
}>(null); } | null>(null);
useEffect(() => { useEffect(() => {
// if nodeClass.template has more fields other than code and dynamic is true // if nodeClass.template has more fields other than code and dynamic is true
// do not run handleClick // do not run handleClick
if (dynamic && Object.keys(nodeClass.template).length > 2) { if (dynamic && Object.keys(nodeClass!.template).length > 2) {
return; return;
} }
processCode(); processCode();
@ -84,7 +84,7 @@ export default function CodeAreaModal({
} }
function processDynamicField() { function processDynamicField() {
postCustomComponent(code, nodeClass) postCustomComponent(code, nodeClass!)
.then((apiReturn) => { .then((apiReturn) => {
const { data } = apiReturn; const { data } = apiReturn;
if (data) { if (data) {

View file

@ -31,8 +31,8 @@ const ExportModal = forwardRef(
</BaseModal.Header> </BaseModal.Header>
<BaseModal.Content> <BaseModal.Content>
<EditFlowSettings <EditFlowSettings
name={name} name={name!}
description={description} description={description!}
flows={flows} flows={flows}
tabId={tabId} tabId={tabId}
setName={setName} setName={setName}
@ -57,14 +57,14 @@ const ExportModal = forwardRef(
onClick={() => { onClick={() => {
if (checked) if (checked)
downloadFlow( downloadFlow(
flows.find((f) => f.id === tabId), flows.find((f) => f.id === tabId)!,
name, name!,
description description
); );
else else
downloadFlow( downloadFlow(
removeApiKeys(flows.find((f) => f.id === tabId)), removeApiKeys(flows.find((f) => f.id === tabId)!),
name, name!,
description description
); );
setOpen(false); setOpen(false);

View file

@ -17,17 +17,17 @@ export default function FlowSettingsModal({
const { flows, tabId, updateFlow, setTabsState, saveFlow } = const { flows, tabId, updateFlow, setTabsState, saveFlow } =
useContext(TabsContext); useContext(TabsContext);
const maxLength = 50; const maxLength = 50;
const [name, setName] = useState(flows.find((f) => f.id === tabId).name); const [name, setName] = useState(flows.find((f) => f.id === tabId)!.name);
const [description, setDescription] = useState( const [description, setDescription] = useState(
flows.find((f) => f.id === tabId).description flows.find((f) => f.id === tabId)!.description
); );
const [invalidName, setInvalidName] = useState(false); const [invalidName, setInvalidName] = useState(false);
function handleClick(): void { function handleClick(): void {
let savedFlow = flows.find((f) => f.id === tabId); let savedFlow = flows.find((f) => f.id === tabId);
savedFlow.name = name; savedFlow!.name = name;
savedFlow.description = description; savedFlow!.description = description;
saveFlow(savedFlow); saveFlow(savedFlow!);
setSuccessData({ title: "Changes saved successfully" }); setSuccessData({ title: "Changes saved successfully" });
setOpen(false); setOpen(false);
} }

View file

@ -45,11 +45,11 @@ export default function FormModal({
const inputKeys = formKeysData.input_keys; const inputKeys = formKeysData.input_keys;
const handleKeys = formKeysData.handle_keys; const handleKeys = formKeysData.handle_keys;
const keyToUse = Object.keys(inputKeys).find( const keyToUse = Object.keys(inputKeys!).find(
(k) => !handleKeys?.some((j) => j === k) && inputKeys[k] === "" (k) => !handleKeys?.some((j) => j === k) && inputKeys![k] === ""
); );
return inputKeys[keyToUse]; return inputKeys![keyToUse!];
} catch (error) { } catch (error) {
console.error(error); console.error(error);
// return a sensible default or `undefined` if no default is possible // return a sensible default or `undefined` if no default is possible
@ -68,10 +68,10 @@ export default function FormModal({
const tabsStateFlowId = tabsState[flow.id]; const tabsStateFlowId = tabsState[flow.id];
const tabsStateFlowIdFormKeysData = tabsStateFlowId.formKeysData; const tabsStateFlowIdFormKeysData = tabsStateFlowId.formKeysData;
const [chatKey, setChatKey] = useState( const [chatKey, setChatKey] = useState(
Object.keys(tabsState[flow.id].formKeysData.input_keys).find( Object.keys(tabsState[flow.id].formKeysData.input_keys!).find(
(k) => (k) =>
!tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k) && !tabsState[flow.id].formKeysData.handle_keys!.some((j) => j === k) &&
tabsState[flow.id].formKeysData.input_keys[k] === "" tabsState[flow.id].formKeysData.input_keys![k] === ""
) )
); );
@ -211,7 +211,7 @@ export default function FormModal({
}); });
} }
if (data.type === "start") { if (data.type === "start") {
addChatHistory("", false, chatKey); addChatHistory("", false, chatKey!);
isStream = true; isStream = true;
} }
if (data.type === "end") { if (data.type === "end") {
@ -335,16 +335,16 @@ export default function FormModal({
}, [open]); }, [open]);
function sendMessage(): void { function sendMessage(): void {
let nodeValidationErrors = validateNodes(reactFlowInstance); let nodeValidationErrors = validateNodes(reactFlowInstance!);
if (nodeValidationErrors.length === 0) { if (nodeValidationErrors.length === 0) {
setLockChat(true); setLockChat(true);
let inputs = tabsState[id.current].formKeysData.input_keys; let inputs = tabsState[id.current].formKeysData.input_keys;
setChatValue(""); setChatValue("");
const message = inputs; const message = inputs;
addChatHistory( addChatHistory(
message, message!,
true, true,
chatKey, chatKey!,
tabsState[flow.id].formKeysData.template tabsState[flow.id].formKeysData.template
); );
sendAll({ sendAll({
@ -357,7 +357,7 @@ export default function FormModal({
setTabsState((old) => { setTabsState((old) => {
if (!chatKey) return old; if (!chatKey) return old;
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys[chatKey] = ""; newTabsState[id.current].formKeysData.input_keys![chatKey] = "";
return newTabsState; return newTabsState;
}); });
} else { } else {
@ -376,9 +376,9 @@ export default function FormModal({
function handleOnCheckedChange(checked: boolean, i: string) { function handleOnCheckedChange(checked: boolean, i: string) {
if (checked === true) { if (checked === true) {
setChatKey(i); setChatKey(i);
setChatValue(tabsState[flow.id].formKeysData.input_keys[i]); setChatValue(tabsState[flow.id].formKeysData.input_keys![i]);
} else { } else {
setChatKey(null); setChatKey(null!);
setChatValue(""); setChatValue("");
} }
} }
@ -422,7 +422,7 @@ export default function FormModal({
</div> </div>
</div> </div>
{Object.keys(tabsState[id.current].formKeysData.input_keys).map( {Object.keys(tabsState[id.current].formKeysData.input_keys!).map(
(i, k) => ( (i, k) => (
<div className="file-component-accordion-div" key={k}> <div className="file-component-accordion-div" key={k}>
<AccordionComponent <AccordionComponent
@ -465,12 +465,12 @@ export default function FormModal({
<Textarea <Textarea
className="custom-scroll" className="custom-scroll"
value={ value={
tabsState[id.current].formKeysData.input_keys[i] tabsState[id.current].formKeysData.input_keys![i]
} }
onChange={(e) => { onChange={(e) => {
setTabsState((old) => { setTabsState((old) => {
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys[ newTabsState[id.current].formKeysData.input_keys![
i i
] = e.target.value; ] = e.target.value;
return newTabsState; return newTabsState;
@ -578,7 +578,7 @@ export default function FormModal({
setChatValue(value); setChatValue(value);
setTabsState((old) => { setTabsState((old) => {
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys[ newTabsState[id.current].formKeysData.input_keys![
chatKey chatKey
] = value; ] = value;
return newTabsState; return newTabsState;

View file

@ -39,7 +39,7 @@ export default function GenericModal({
const [myModalType] = useState(type); const [myModalType] = useState(type);
const [inputValue, setInputValue] = useState(value); const [inputValue, setInputValue] = useState(value);
const [isEdit, setIsEdit] = useState(true); const [isEdit, setIsEdit] = useState(true);
const [wordsHighlight, setWordsHighlight] = useState([]); const [wordsHighlight, setWordsHighlight] = useState<string[]>([]);
const { setErrorData, setSuccessData, setNoticeData } = const { setErrorData, setSuccessData, setNoticeData } =
useContext(alertContext); useContext(alertContext);
const ref = useRef(); const ref = useRef();
@ -48,14 +48,14 @@ export default function GenericModal({
function checkVariables(valueToCheck: string): void { function checkVariables(valueToCheck: string): void {
const regex = /\{([^{}]+)\}/g; const regex = /\{([^{}]+)\}/g;
const matches = []; const matches: string[] = [];
let match; let match;
while ((match = regex.exec(valueToCheck))) { while ((match = regex.exec(valueToCheck))) {
matches.push(`{${match[1]}}`); matches.push(`{${match[1]}}`);
} }
let invalid_chars = []; let invalid_chars: string[] = [];
let fixed_variables = []; let fixed_variables: string[] = [];
let input_variables = matches; let input_variables = matches;
for (let variable of input_variables) { for (let variable of input_variables) {
let new_var = variable; let new_var = variable;
@ -120,7 +120,7 @@ export default function GenericModal({
} }
function validatePrompt(closeModal: boolean): void { function validatePrompt(closeModal: boolean): void {
postValidatePrompt(field_name, inputValue, nodeClass) postValidatePrompt(field_name, inputValue, nodeClass!)
.then((apiReturn) => { .then((apiReturn) => {
if (apiReturn.data) { if (apiReturn.data) {
let inputVariables = apiReturn.data.input_variables ?? []; let inputVariables = apiReturn.data.input_variables ?? [];
@ -134,7 +134,7 @@ export default function GenericModal({
setSuccessData({ setSuccessData({
title: "Prompt is ready", title: "Prompt is ready",
}); });
setNodeClass(apiReturn.data?.frontend_node); setNodeClass!(apiReturn.data?.frontend_node);
setModalOpen(closeModal); setModalOpen(closeModal);
setValue(inputValue); setValue(inputValue);
} }

View file

@ -57,7 +57,7 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
const [position, setPosition] = useState({ x: 0, y: 0 }); const [position, setPosition] = useState({ x: 0, y: 0 });
const [lastSelection, setLastSelection] = const [lastSelection, setLastSelection] =
useState<OnSelectionChangeParams>(null); useState<OnSelectionChangeParams | null>(null);
useEffect(() => { useEffect(() => {
// this effect is used to attach the global event handlers // this effect is used to attach the global event handlers
@ -281,7 +281,7 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
setNodes((nds) => nds.concat(newNode)); setNodes((nds) => nds.concat(newNode));
} else if (event.dataTransfer.types.some((t) => t === "Files")) { } else if (event.dataTransfer.types.some((t) => t === "Files")) {
takeSnapshot(); takeSnapshot();
uploadFlow(false, event.dataTransfer.files.item(0)); uploadFlow(false, event.dataTransfer.files.item(0)!);
} }
}, },
// Specify dependencies for useCallback // Specify dependencies for useCallback
@ -314,7 +314,7 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
const onEdgeUpdate = useCallback( const onEdgeUpdate = useCallback(
(oldEdge: Edge, newConnection: Connection) => { (oldEdge: Edge, newConnection: Connection) => {
if (isValidConnection(newConnection, reactFlowInstance)) { if (isValidConnection(newConnection, reactFlowInstance!)) {
edgeUpdateSuccessful.current = true; edgeUpdateSuccessful.current = true;
setEdges((els) => updateEdge(oldEdge, newConnection, els)); setEdges((els) => updateEdge(oldEdge, newConnection, els));
} }
@ -404,7 +404,7 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
[&>button]:border-b-border hover:[&>button]:bg-border" [&>button]:border-b-border hover:[&>button]:bg-border"
></Controls> ></Controls>
</ReactFlow> </ReactFlow>
<Chat flow={flow} reactFlowInstance={reactFlowInstance} /> <Chat flow={flow} reactFlowInstance={reactFlowInstance!} />
</div> </div>
) : ( ) : (
<></> <></>

View file

@ -120,7 +120,7 @@ export default function ExtraSidebar(): JSX.Element {
"extra-side-bar-buttons " + (isPending ? "" : "button-disable") "extra-side-bar-buttons " + (isPending ? "" : "button-disable")
} }
onClick={(event) => { onClick={(event) => {
saveFlow(flow); saveFlow(flow!);
setSuccessData({ title: "Changes saved successfully" }); setSuccessData({ title: "Changes saved successfully" });
}} }}
> >

View file

@ -13,7 +13,7 @@ export default function NodeToolbarComponent({
deleteNode, deleteNode,
}: nodeToolbarPropsType): JSX.Element { }: nodeToolbarPropsType): JSX.Element {
const [nodeLength, setNodeLength] = useState( const [nodeLength, setNodeLength] = useState(
Object.keys(data.node.template).filter( Object.keys(data.node!.template).filter(
(t) => (t) =>
t.charAt(0) !== "_" && t.charAt(0) !== "_" &&
data.node?.template[t].show && data.node?.template[t].show &&

View file

@ -10,7 +10,7 @@ export default function FlowPage(): JSX.Element {
// Set flow tab id // Set flow tab id
useEffect(() => { useEffect(() => {
setTabId(id); setTabId(id!);
}, [id]); }, [id]);
// Initialize state variable for the version // Initialize state variable for the version
@ -26,7 +26,7 @@ export default function FlowPage(): JSX.Element {
{flows.length > 0 && {flows.length > 0 &&
tabId !== "" && tabId !== "" &&
flows.findIndex((flow) => flow.id === tabId) !== -1 && ( flows.findIndex((flow) => flow.id === tabId) !== -1 && (
<Page flow={flows.find((flow) => flow.id === tabId)} /> <Page flow={flows.find((flow) => flow.id === tabId)!} />
)} )}
<a <a
target={"_blank"} target={"_blank"}

View file

@ -45,7 +45,7 @@ export default function HomePage(): JSX.Element {
<Button <Button
variant="primary" variant="primary"
onClick={() => { onClick={() => {
addFlow(null, true).then((id) => { addFlow(null!, true).then((id) => {
navigate("/flow/" + id); navigate("/flow/" + id);
}); });
}} }}

View file

@ -180,7 +180,7 @@ export type InputProps = {
invalidName: boolean; invalidName: boolean;
setName: (name: string) => void; setName: (name: string) => void;
setDescription: (description: string) => void; setDescription: (description: string) => void;
updateFlow: (flow: { id: string; name: string }) => void; updateFlow: (flow: { id: string; name: string; }) => void;
setInvalidName: (invalidName: boolean) => void; setInvalidName: (invalidName: boolean) => void;
}; };
@ -208,7 +208,6 @@ export interface languageMap {
} }
export type groupedObjType = { export type groupedObjType = {
component: string;
family: string; family: string;
type: string; type: string;
}; };
@ -384,6 +383,7 @@ type tabsArrayType = {
language: string; language: string;
mode: string; mode: string;
name: string; name: string;
description: string;
}; };
type getValueNodeType = { type getValueNodeType = {
@ -427,3 +427,10 @@ export type crashComponentPropsType = {
}; };
resetErrorBoundary: (args) => void; resetErrorBoundary: (args) => void;
}; };
export type validationStatusType = {
id: string;
params: string;
progress: number;
valid: boolean;
};

View file

@ -11,7 +11,7 @@ export type FlowType = {
export type NodeType = { export type NodeType = {
id: string; id: string;
type?: string; type?: string;
position: XYPosition; position: XYPosition | undefined;
data: NodeDataType; data: NodeDataType;
}; };
export type NodeDataType = { export type NodeDataType = {

View file

@ -38,7 +38,7 @@ export function cleanEdges({
const id = [ const id = [
sourceNode.data.type, sourceNode.data.type,
sourceNode.data.id, sourceNode.data.id,
...sourceNode.data.node?.base_classes, ...sourceNode.data.node?.base_classes!,
].join("|"); ].join("|");
if (id !== sourceHandle) { if (id !== sourceHandle) {
newEdges = newEdges.filter((e) => e.id !== edge.id); newEdges = newEdges.filter((e) => e.id !== edge.id);
@ -69,7 +69,7 @@ export function isValidConnection(
) || ) ||
targetHandle?.split("|")[0] === "str" targetHandle?.split("|")[0] === "str"
) { ) {
let targetNode = reactFlowInstance?.getNode(target)?.data?.node; let targetNode = reactFlowInstance?.getNode(target!)?.data?.node;
if (!targetNode) { if (!targetNode) {
if ( if (
!reactFlowInstance !reactFlowInstance
@ -79,11 +79,11 @@ export function isValidConnection(
return true; return true;
} }
} else if ( } else if (
(!targetNode.template[targetHandle?.split("|")[1]].list && (!targetNode.template[targetHandle?.split("|")[1]!].list &&
!reactFlowInstance !reactFlowInstance
.getEdges() .getEdges()
.find((e) => e.targetHandle === targetHandle)) || .find((e) => e.targetHandle === targetHandle)) ||
targetNode.template[targetHandle?.split("|")[1]].list targetNode.template[targetHandle?.split("|")[1]!].list
) { ) {
return true; return true;
} }

View file

@ -5,6 +5,7 @@ import { IVarHighlightType, groupDataType, groupedObjType, tweakType } from "../
import { FlowType, NodeType } from "../types/flow"; import { FlowType, NodeType } from "../types/flow";
import { TabsState } from "../types/tabs"; import { TabsState } from "../types/tabs";
import { buildTweaks } from "./reactflowUtils"; import { buildTweaks } from "./reactflowUtils";
import { APIClassType, APIObjectType } from "../types/api";
export function classNames(...classes: Array<string>): string { export function classNames(...classes: Array<string>): string {
return classes.filter(Boolean).join(" "); return classes.filter(Boolean).join(" ");
@ -88,10 +89,10 @@ export function checkUpperWords(str: string): string {
export const isWrappedWithClass = (event: any, className: string | undefined) => export const isWrappedWithClass = (event: any, className: string | undefined) =>
event.target.closest(`.${className}`); event.target.closest(`.${className}`);
export function groupByFamily(data: groupDataType, baseClasses: string, left: boolean, flow?: NodeType[]): groupedObjType[] { export function groupByFamily(data, baseClasses: string, left: boolean, flow?: NodeType[]): groupedObjType[] {
const baseClassesSet = new Set(baseClasses.split("\n")); const baseClassesSet = new Set(baseClasses.split("\n"));
let arrOfPossibleInputs = []; let arrOfPossibleInputs: Array<{ category: string; nodes: string[]; full: boolean; }> = [];
let arrOfPossibleOutputs = []; let arrOfPossibleOutputs: Array<{ category: string; nodes: string[]; full: boolean; }> = [];
let checkedNodes = new Map(); let checkedNodes = new Map();
const excludeTypes = new Set([ const excludeTypes = new Set([
"str", "str",
@ -116,26 +117,26 @@ export function groupByFamily(data: groupDataType, baseClasses: string, left: bo
checkedNodes.set(nodeData.type, { checkedNodes.set(nodeData.type, {
hasBaseClassInTemplate: hasBaseClassInTemplate:
foundNode?.hasBaseClassInTemplate || foundNode?.hasBaseClassInTemplate ||
Object.values(nodeData.node.template).some(checkBaseClass), Object.values(nodeData.node!.template).some(checkBaseClass),
hasBaseClassInBaseClasses: hasBaseClassInBaseClasses:
foundNode?.hasBaseClassInBaseClasses || foundNode?.hasBaseClassInBaseClasses ||
nodeData.node.base_classes.some((t) => baseClassesSet.has(t)), nodeData.node!.base_classes.some((t) => baseClassesSet.has(t)),
}); });
} }
} }
for (const [d, nodes] of Object.entries(data)) { for (const [d, nodes] of Object.entries(data)) {
let tempInputs = [], let tempInputs: string[] = [],
tempOutputs = []; tempOutputs: string[] = [];
for (const [n, node] of Object.entries(nodes)) { for (const [n, node] of Object.entries(nodes)) {
let foundNode = checkedNodes.get(n); let foundNode = checkedNodes.get(n);
if (!foundNode) { if (!foundNode) {
foundNode = { foundNode = {
hasBaseClassInTemplate: Object.values(node.template).some( hasBaseClassInTemplate: Object.values(node!.template).some(
checkBaseClass checkBaseClass
), ),
hasBaseClassInBaseClasses: node.base_classes.some((t) => hasBaseClassInBaseClasses: node!.base_classes.some((t) =>
baseClassesSet.has(t) baseClassesSet.has(t)
), ),
}; };
@ -177,7 +178,7 @@ export function buildInputs(tabsState: TabsState, id: string): string {
tabsState[id] && tabsState[id] &&
tabsState[id].formKeysData && tabsState[id].formKeysData &&
tabsState[id].formKeysData.input_keys && tabsState[id].formKeysData.input_keys &&
Object.keys(tabsState[id].formKeysData.input_keys).length > 0 Object.keys(tabsState[id].formKeysData.input_keys!).length > 0
? JSON.stringify(tabsState[id].formKeysData.input_keys) ? JSON.stringify(tabsState[id].formKeysData.input_keys)
: '{"input": "message"}'; : '{"input": "message"}';
} }
@ -265,7 +266,7 @@ export function getPythonApiCode(
// node.data.id // node.data.id
// } // }
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id); const inputs = buildInputs(tabsState!, flow.id);
return `import requests return `import requests
from typing import Optional from typing import Optional
@ -317,7 +318,7 @@ export function getCurlCode(
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id); const inputs = buildInputs(tabsState!, flow.id);
return `curl -X POST \\ return `curl -X POST \\
${window.location.protocol}//${ ${window.location.protocol}//${
@ -343,7 +344,7 @@ export function getPythonCode(
): string { ): string {
const flowName = flow.name; const flowName = flow.name;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id); const inputs = buildInputs(tabsState!, flow.id);
return `from langflow import load_flow_from_json return `from langflow import load_flow_from_json
TWEAKS = ${ TWEAKS = ${
tweak && tweak.length > 0 tweak && tweak.length > 0
@ -364,7 +365,7 @@ flow(inputs)`;
export function getWidgetCode(flow: FlowType, tabsState?: TabsState): string { export function getWidgetCode(flow: FlowType, tabsState?: TabsState): string {
const flowId = flow.id; const flowId = flow.id;
const flowName = flow.name; const flowName = flow.name;
const inputs = buildInputs(tabsState, flow.id); const inputs = buildInputs(tabsState!, flow.id);
return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/langflow-embedded-chat@main/dist/build/static/js/bundle.min.js"></script> return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/langflow-embedded-chat@main/dist/build/static/js/bundle.min.js"></script>
@ -375,10 +376,10 @@ chat_input_field: Input key that you want the chat to send the user message with
window_title="${flowName}" window_title="${flowName}"
flow_id="${flowId}" flow_id="${flowId}"
${ ${
tabsState[flow.id] && tabsState[flow.id].formKeysData tabsState![flow.id] && tabsState![flow.id].formKeysData
? `chat_inputs='${inputs}' ? `chat_inputs='${inputs}'
chat_input_field="${ chat_input_field="${
Object.keys(tabsState[flow.id].formKeysData.input_keys)[0] Object.keys(tabsState![flow.id].formKeysData.input_keys!)[0]
}" }"
` `
: "" : ""

View file

@ -6,7 +6,7 @@
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": false, "strict": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"module": "esnext", "module": "esnext",