Feat: Add option to replace saved component or create a new one using confirmation modal
This commit is contained in:
parent
037f7f5b1b
commit
7e4dd16881
15 changed files with 659 additions and 556 deletions
|
|
@ -22,7 +22,10 @@ import PromptAreaComponent from "../../../../components/promptComponent";
|
||||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||||
import { Button } from "../../../../components/ui/button";
|
import { Button } from "../../../../components/ui/button";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES, TOOLTIP_EMPTY } from "../../../../constants/constants";
|
import {
|
||||||
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
|
TOOLTIP_EMPTY,
|
||||||
|
} from "../../../../constants/constants";
|
||||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
import { ParameterComponentType } from "../../../../types/components";
|
import { ParameterComponentType } from "../../../../types/components";
|
||||||
|
|
@ -222,9 +225,7 @@ export default function ParameterComponent({
|
||||||
}, [tooltipTitle, flow]);
|
}, [tooltipTitle, flow]);
|
||||||
|
|
||||||
return !showNode ? (
|
return !showNode ? (
|
||||||
left &&
|
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
(LANGFLOW_SUPPORTED_TYPES.has(type??"")) &&
|
|
||||||
!optionalHandle ? (
|
|
||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
<Button className="h-7 truncate bg-muted p-0 text-sm font-normal text-black hover:bg-muted">
|
<Button className="h-7 truncate bg-muted p-0 text-sm font-normal text-black hover:bg-muted">
|
||||||
|
|
@ -297,9 +298,7 @@ export default function ParameterComponent({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{left &&
|
{left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
(LANGFLOW_SUPPORTED_TYPES.has(type??"")) &&
|
|
||||||
!optionalHandle ? (
|
|
||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
<Button className="h-7 truncate bg-muted p-0 text-sm font-normal text-black hover:bg-muted">
|
<Button className="h-7 truncate bg-muted p-0 text-sm font-normal text-black hover:bg-muted">
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
TabsList,
|
TabsList,
|
||||||
TabsTrigger,
|
TabsTrigger,
|
||||||
} from "../../components/ui/tabs";
|
} from "../../components/ui/tabs";
|
||||||
|
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
||||||
import { darkContext } from "../../contexts/darkContext";
|
import { darkContext } from "../../contexts/darkContext";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
import { codeTabsPropsType } from "../../types/components";
|
import { codeTabsPropsType } from "../../types/components";
|
||||||
|
|
@ -40,7 +41,6 @@ import { classNames } from "../../utils/utils";
|
||||||
import DictComponent from "../dictComponent";
|
import DictComponent from "../dictComponent";
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
import KeypairListComponent from "../keypairListComponent";
|
import KeypairListComponent from "../keypairListComponent";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
|
||||||
|
|
||||||
export default function CodeTabsComponent({
|
export default function CodeTabsComponent({
|
||||||
flow,
|
flow,
|
||||||
|
|
@ -243,7 +243,10 @@ export default function CodeTabsComponent({
|
||||||
templateField.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
node.data.node.template[templateField]
|
node.data.node.template[templateField]
|
||||||
.show &&
|
.show &&
|
||||||
(LANGFLOW_SUPPORTED_TYPES.has(node.data.node.template[templateField].type))
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
|
node.data.node.template[templateField]
|
||||||
|
.type
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.map((templateField, indx) => {
|
.map((templateField, indx) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -664,5 +664,14 @@ export const LAST_USED_SPAN_1 = "The last time this key was used.";
|
||||||
export const LAST_USED_SPAN_2 =
|
export const LAST_USED_SPAN_2 =
|
||||||
"Accurate to within the hour from the most recent usage.";
|
"Accurate to within the hour from the most recent usage.";
|
||||||
|
|
||||||
export const LANGFLOW_SUPPORTED_TYPES= new Set(["str","bool","float","code",
|
export const LANGFLOW_SUPPORTED_TYPES = new Set([
|
||||||
"prompt","file","int","dict","NestedDict"])
|
"str",
|
||||||
|
"bool",
|
||||||
|
"float",
|
||||||
|
"code",
|
||||||
|
"prompt",
|
||||||
|
"file",
|
||||||
|
"int",
|
||||||
|
"dict",
|
||||||
|
"NestedDict",
|
||||||
|
]);
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,11 @@ const FlowsContextInitialValue: FlowsContextType = {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
flows: [],
|
flows: [],
|
||||||
removeFlow: (id: string) => {},
|
removeFlow: (id: string) => {},
|
||||||
addFlow: async (newProject: boolean, flowData?: FlowType) => "",
|
addFlow: async (
|
||||||
|
newProject: boolean,
|
||||||
|
flowData?: FlowType,
|
||||||
|
override?: boolean
|
||||||
|
) => "",
|
||||||
updateFlow: (newFlow: FlowType) => {},
|
updateFlow: (newFlow: FlowType) => {},
|
||||||
incrementNodeId: () => uid(),
|
incrementNodeId: () => uid(),
|
||||||
downloadFlow: (flow: FlowType) => {},
|
downloadFlow: (flow: FlowType) => {},
|
||||||
|
|
@ -78,7 +82,7 @@ const FlowsContextInitialValue: FlowsContextType = {
|
||||||
selection: { nodes: any; edges: any },
|
selection: { nodes: any; edges: any },
|
||||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
position: { x: number; y: number; paneX?: number; paneY?: number }
|
||||||
) => {},
|
) => {},
|
||||||
saveComponent: async (component: NodeDataType) => "",
|
saveComponent: async (component: NodeDataType, override: boolean) => "",
|
||||||
deleteComponent: (key: string) => {},
|
deleteComponent: (key: string) => {},
|
||||||
version: "",
|
version: "",
|
||||||
};
|
};
|
||||||
|
|
@ -496,7 +500,8 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
|
|
||||||
const addFlow = async (
|
const addFlow = async (
|
||||||
newProject: Boolean,
|
newProject: Boolean,
|
||||||
flow?: FlowType
|
flow?: FlowType,
|
||||||
|
override?: boolean
|
||||||
): Promise<String | undefined> => {
|
): Promise<String | undefined> => {
|
||||||
if (newProject) {
|
if (newProject) {
|
||||||
let flowData = flow
|
let flowData = flow
|
||||||
|
|
@ -505,6 +510,15 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
|
|
||||||
// Create a new flow with a default name if no flow is provided.
|
// Create a new flow with a default name if no flow is provided.
|
||||||
|
|
||||||
|
if (override) {
|
||||||
|
deleteComponent(flow!.name);
|
||||||
|
const newFlow = createNewFlow(flowData, flow!);
|
||||||
|
const { id } = await saveFlowToDatabase(newFlow);
|
||||||
|
newFlow.id = id;
|
||||||
|
addFlowToLocalState(newFlow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const newFlow = createNewFlow(flowData, flow!);
|
const newFlow = createNewFlow(flowData, flow!);
|
||||||
|
|
||||||
const newName = addVersionToDuplicates(newFlow, flows);
|
const newName = addVersionToDuplicates(newFlow, flows);
|
||||||
|
|
@ -642,9 +656,9 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveComponent(component: NodeDataType) {
|
function saveComponent(component: NodeDataType, override: boolean) {
|
||||||
component.node!.official = false;
|
component.node!.official = false;
|
||||||
return addFlow(true, createFlowComponent(component, version));
|
return addFlow(true, createFlowComponent(component, version), override);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteComponent(key: string) {
|
function deleteComponent(key: string) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,10 @@ import {
|
||||||
// import "ace-builds/webpack-resolver";
|
// import "ace-builds/webpack-resolver";
|
||||||
import CodeTabsComponent from "../../components/codeTabsComponent";
|
import CodeTabsComponent from "../../components/codeTabsComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { EXPORT_CODE_DIALOG, LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
import {
|
||||||
|
EXPORT_CODE_DIALOG,
|
||||||
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
|
} from "../../constants/constants";
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
import { FlowsContext } from "../../contexts/flowsContext";
|
import { FlowsContext } from "../../contexts/flowsContext";
|
||||||
import { TemplateVariableType } from "../../types/api";
|
import { TemplateVariableType } from "../../types/api";
|
||||||
|
|
@ -99,7 +102,9 @@ const ApiModal = forwardRef(
|
||||||
(templateField) =>
|
(templateField) =>
|
||||||
templateField.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
node.data.node.template[templateField].show &&
|
node.data.node.template[templateField].show &&
|
||||||
(LANGFLOW_SUPPORTED_TYPES.has(node.data.node.template[templateField].type))
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
|
node.data.node.template[templateField].type
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.map((n, i) => {
|
.map((n, i) => {
|
||||||
arrNodesWithValues.push(node["id"]);
|
arrNodesWithValues.push(node["id"]);
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,15 @@ function ConfirmationModal({
|
||||||
size,
|
size,
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
|
onCancel,
|
||||||
}: ConfirmationModalType) {
|
}: ConfirmationModalType) {
|
||||||
const Icon: any = nodeIconsLucide[icon];
|
const Icon: any = nodeIconsLucide[icon];
|
||||||
const [modalOpen, setModalOpen] = useState(open ?? false);
|
const [modalOpen, setModalOpen] = useState(open ?? false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) setModalOpen(open);
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onClose) onClose!(modalOpen);
|
if (onClose) onClose!(modalOpen);
|
||||||
}, [modalOpen]);
|
}, [modalOpen]);
|
||||||
|
|
@ -86,6 +91,7 @@ function ConfirmationModal({
|
||||||
className="mt-5"
|
className="mt-5"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (onCancel) onCancel();
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,10 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "../../components/ui/table";
|
} from "../../components/ui/table";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES, limitScrollFieldsModal } from "../../constants/constants";
|
import {
|
||||||
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
|
limitScrollFieldsModal,
|
||||||
|
} from "../../constants/constants";
|
||||||
import { FlowsContext } from "../../contexts/flowsContext";
|
import { FlowsContext } from "../../contexts/flowsContext";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
|
|
@ -145,7 +148,9 @@ const EditNodeModal = forwardRef(
|
||||||
(templateParam) =>
|
(templateParam) =>
|
||||||
templateParam.charAt(0) !== "_" &&
|
templateParam.charAt(0) !== "_" &&
|
||||||
myData.current.node?.template[templateParam].show &&
|
myData.current.node?.template[templateParam].show &&
|
||||||
(LANGFLOW_SUPPORTED_TYPES.has(myData.current.node.template[templateParam].type))
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
|
myData.current.node.template[templateParam].type
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.map((templateParam, index) => (
|
.map((templateParam, index) => (
|
||||||
<TableRow key={index} className="h-10">
|
<TableRow key={index} className="h-10">
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Button } from "../../components/ui/button";
|
||||||
import { Checkbox } from "../../components/ui/checkbox";
|
import { Checkbox } from "../../components/ui/checkbox";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { FlowsContext } from "../../contexts/flowsContext";
|
import { FlowsContext } from "../../contexts/flowsContext";
|
||||||
|
import { StoreContext } from "../../contexts/storeContext";
|
||||||
import {
|
import {
|
||||||
getStoreComponents,
|
getStoreComponents,
|
||||||
getStoreTags,
|
getStoreTags,
|
||||||
|
|
@ -15,7 +16,6 @@ import { FlowType } from "../../types/flow";
|
||||||
import { removeApiKeys } from "../../utils/reactflowUtils";
|
import { removeApiKeys } from "../../utils/reactflowUtils";
|
||||||
import { getTagsIds } from "../../utils/storeUtils";
|
import { getTagsIds } from "../../utils/storeUtils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
import { StoreContext } from "../../contexts/storeContext";
|
|
||||||
|
|
||||||
export default function ShareModal({
|
export default function ShareModal({
|
||||||
component,
|
component,
|
||||||
|
|
@ -23,7 +23,7 @@ export default function ShareModal({
|
||||||
children,
|
children,
|
||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
disabled
|
disabled,
|
||||||
}: {
|
}: {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
is_component: boolean;
|
is_component: boolean;
|
||||||
|
|
@ -33,7 +33,7 @@ export default function ShareModal({
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { version, addFlow } = useContext(FlowsContext);
|
const { version, addFlow } = useContext(FlowsContext);
|
||||||
const {hasApiKey} = useContext(StoreContext)
|
const { hasApiKey } = useContext(StoreContext);
|
||||||
const { setSuccessData, setErrorData } = useContext(alertContext);
|
const { setSuccessData, setErrorData } = useContext(alertContext);
|
||||||
const [checked, setChecked] = useState(true);
|
const [checked, setChecked] = useState(true);
|
||||||
const [name, setName] = useState(component?.name ?? "");
|
const [name, setName] = useState(component?.name ?? "");
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ export default function Page({
|
||||||
// Calculate the position where the node should be created
|
// Calculate the position where the node should be created
|
||||||
const position = reactFlowInstance!.screenToFlowPosition({
|
const position = reactFlowInstance!.screenToFlowPosition({
|
||||||
x: event.clientX,
|
x: event.clientX,
|
||||||
y: event.clientY
|
y: event.clientY,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate a unique node ID
|
// Generate a unique node ID
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Input } from "../../../../components/ui/input";
|
||||||
import { Separator } from "../../../../components/ui/separator";
|
import { Separator } from "../../../../components/ui/separator";
|
||||||
import { alertContext } from "../../../../contexts/alertContext";
|
import { alertContext } from "../../../../contexts/alertContext";
|
||||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||||
|
import { StoreContext } from "../../../../contexts/storeContext";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
import ApiModal from "../../../../modals/ApiModal";
|
import ApiModal from "../../../../modals/ApiModal";
|
||||||
import ExportModal from "../../../../modals/exportModal";
|
import ExportModal from "../../../../modals/exportModal";
|
||||||
|
|
@ -23,14 +24,13 @@ import {
|
||||||
} from "../../../../utils/utils";
|
} from "../../../../utils/utils";
|
||||||
import DisclosureComponent from "../DisclosureComponent";
|
import DisclosureComponent from "../DisclosureComponent";
|
||||||
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
||||||
import { StoreContext } from "../../../../contexts/storeContext";
|
|
||||||
|
|
||||||
export default function ExtraSidebar(): JSX.Element {
|
export default function ExtraSidebar(): JSX.Element {
|
||||||
const { data, templates, getFilterEdge, setFilterEdge, reactFlowInstance } =
|
const { data, templates, getFilterEdge, setFilterEdge, reactFlowInstance } =
|
||||||
useContext(typesContext);
|
useContext(typesContext);
|
||||||
const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt, version } =
|
const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt, version } =
|
||||||
useContext(FlowsContext);
|
useContext(FlowsContext);
|
||||||
const {hasApiKey} = useContext(StoreContext)
|
const { hasApiKey } = useContext(StoreContext);
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const [dataFilter, setFilterData] = useState(data);
|
const [dataFilter, setFilterData] = useState(data);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
|
@ -50,8 +50,6 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
event.dataTransfer.setData("nodedata", JSON.stringify(data));
|
event.dataTransfer.setData("nodedata", JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handle showing components after use search input
|
// Handle showing components after use search input
|
||||||
function handleSearchInput(e: string) {
|
function handleSearchInput(e: string) {
|
||||||
if (e === "") {
|
if (e === "") {
|
||||||
|
|
@ -199,7 +197,10 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
() => (
|
() => (
|
||||||
<ExportModal>
|
<ExportModal>
|
||||||
<ShadTooltip content="Export" side="top">
|
<ShadTooltip content="Export" side="top">
|
||||||
<button disabled={!hasApiKey} className={classNames("extra-side-bar-buttons")}>
|
<button
|
||||||
|
disabled={!hasApiKey}
|
||||||
|
className={classNames("extra-side-bar-buttons")}
|
||||||
|
>
|
||||||
<IconComponent name="FileDown" className="side-bar-button-size" />
|
<IconComponent name="FileDown" className="side-bar-button-size" />
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,7 @@ export default function SidebarDraggableComponent({
|
||||||
name="Menu"
|
name="Menu"
|
||||||
className="side-bar-components-icon "
|
className="side-bar-components-icon "
|
||||||
/>
|
/>
|
||||||
<SelectTrigger>
|
<SelectTrigger></SelectTrigger>
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value={"download"}>
|
<SelectItem value={"download"}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
} from "../../../../components/ui/select-custom";
|
} from "../../../../components/ui/select-custom";
|
||||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||||
|
import { StoreContext } from "../../../../contexts/storeContext";
|
||||||
|
import ConfirmationModal from "../../../../modals/ConfirmationModal";
|
||||||
import EditNodeModal from "../../../../modals/EditNodeModal";
|
import EditNodeModal from "../../../../modals/EditNodeModal";
|
||||||
import ShareModal from "../../../../modals/shareModal";
|
import ShareModal from "../../../../modals/shareModal";
|
||||||
import { nodeToolbarPropsType } from "../../../../types/components";
|
import { nodeToolbarPropsType } from "../../../../types/components";
|
||||||
|
|
@ -21,7 +23,6 @@ import {
|
||||||
updateFlowPosition,
|
updateFlowPosition,
|
||||||
} from "../../../../utils/reactflowUtils";
|
} from "../../../../utils/reactflowUtils";
|
||||||
import { classNames } from "../../../../utils/utils";
|
import { classNames } from "../../../../utils/utils";
|
||||||
import { StoreContext } from "../../../../contexts/storeContext";
|
|
||||||
|
|
||||||
export default function NodeToolbarComponent({
|
export default function NodeToolbarComponent({
|
||||||
data,
|
data,
|
||||||
|
|
@ -51,7 +52,7 @@ export default function NodeToolbarComponent({
|
||||||
);
|
);
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const { getNodeId } = useContext(FlowsContext);
|
const { getNodeId } = useContext(FlowsContext);
|
||||||
const {hasApiKey} = useContext(StoreContext)
|
const { hasApiKey } = useContext(StoreContext);
|
||||||
|
|
||||||
function canMinimize() {
|
function canMinimize() {
|
||||||
let countHandles: number = 0;
|
let countHandles: number = 0;
|
||||||
|
|
@ -64,11 +65,12 @@ export default function NodeToolbarComponent({
|
||||||
const isMinimal = canMinimize();
|
const isMinimal = canMinimize();
|
||||||
const isGroup = data.node?.flow ? true : false;
|
const isGroup = data.node?.flow ? true : false;
|
||||||
|
|
||||||
const { paste, saveComponent, version } = useContext(FlowsContext);
|
const { paste, saveComponent, version, flows } = useContext(FlowsContext);
|
||||||
const reactFlowInstance = useReactFlow();
|
const reactFlowInstance = useReactFlow();
|
||||||
const [showModalAdvanced, setShowModalAdvanced] = useState(false);
|
const [showModalAdvanced, setShowModalAdvanced] = useState(false);
|
||||||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||||
const [selectedValue, setSelectedValue] = useState("");
|
const [selectedValue, setSelectedValue] = useState("");
|
||||||
|
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
||||||
|
|
||||||
const [flowComponent, setFlowComponent] = useState<FlowType>();
|
const [flowComponent, setFlowComponent] = useState<FlowType>();
|
||||||
|
|
||||||
|
|
@ -76,6 +78,11 @@ export default function NodeToolbarComponent({
|
||||||
setFlowComponent(createFlowComponent(cloneDeep(data), version));
|
setFlowComponent(createFlowComponent(cloneDeep(data), version));
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
function onOverrideModalConfirmation(override: boolean): void {
|
||||||
|
if (override) saveComponent(cloneDeep(data), true);
|
||||||
|
saveComponent(cloneDeep(data), false);
|
||||||
|
}
|
||||||
|
|
||||||
const handleSelectChange = (event) => {
|
const handleSelectChange = (event) => {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case "advanced":
|
case "advanced":
|
||||||
|
|
@ -92,7 +99,7 @@ export default function NodeToolbarComponent({
|
||||||
if (hasApiKey) setShowconfirmShare(true);
|
if (hasApiKey) setShowconfirmShare(true);
|
||||||
break;
|
break;
|
||||||
case "SaveAll":
|
case "SaveAll":
|
||||||
saveComponent(cloneDeep(data));
|
saveComponent(cloneDeep(data), false);
|
||||||
break;
|
break;
|
||||||
case "disabled":
|
case "disabled":
|
||||||
break;
|
break;
|
||||||
|
|
@ -100,9 +107,16 @@ export default function NodeToolbarComponent({
|
||||||
updateFlowPosition(position, data.node?.flow!);
|
updateFlowPosition(position, data.node?.flow!);
|
||||||
expandGroupNode(data, reactFlowInstance, getNodeId);
|
expandGroupNode(data, reactFlowInstance, getNodeId);
|
||||||
break;
|
break;
|
||||||
|
case "override":
|
||||||
|
setShowOverrideModal(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isSaved = flows.some((flow) =>
|
||||||
|
Object.values(flow).includes(data.node?.display_name!)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-26 h-10">
|
<div className="w-26 h-10">
|
||||||
|
|
@ -204,6 +218,17 @@ export default function NodeToolbarComponent({
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isSaved ? (
|
||||||
|
<SelectItem value={"override"}>
|
||||||
|
<div className="flex">
|
||||||
|
<IconComponent
|
||||||
|
name="SaveAll"
|
||||||
|
className="relative top-0.5 mr-2 h-4 w-4"
|
||||||
|
/>{" "}
|
||||||
|
Save{" "}
|
||||||
|
</div>{" "}
|
||||||
|
</SelectItem>
|
||||||
|
) : (
|
||||||
<SelectItem value={"SaveAll"}>
|
<SelectItem value={"SaveAll"}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
@ -213,7 +238,9 @@ export default function NodeToolbarComponent({
|
||||||
Save{" "}
|
Save{" "}
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
{hasApiKey && <SelectItem value={"Share"}>
|
)}
|
||||||
|
{hasApiKey && (
|
||||||
|
<SelectItem value={"Share"}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="Share2"
|
name="Share2"
|
||||||
|
|
@ -221,7 +248,8 @@ export default function NodeToolbarComponent({
|
||||||
/>{" "}
|
/>{" "}
|
||||||
Share{" "}
|
Share{" "}
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
</SelectItem>}
|
</SelectItem>
|
||||||
|
)}
|
||||||
<SelectItem value={"Download"}>
|
<SelectItem value={"Download"}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
@ -255,6 +283,32 @@ export default function NodeToolbarComponent({
|
||||||
)}
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
asChild
|
||||||
|
open={showOverrideModal}
|
||||||
|
title={`Replace ${data.node?.display_name}`}
|
||||||
|
titleHeader={`Please, confirm your save actions`}
|
||||||
|
modalContentTitle="Attention!"
|
||||||
|
cancelText="New"
|
||||||
|
confirmationText="Replace"
|
||||||
|
icon={"SaveAll"}
|
||||||
|
index={6}
|
||||||
|
onConfirm={(index, user) => {
|
||||||
|
saveComponent(cloneDeep(data), true);
|
||||||
|
}}
|
||||||
|
onClose={setShowOverrideModal}
|
||||||
|
onCancel={() => saveComponent(cloneDeep(data), false)}
|
||||||
|
>
|
||||||
|
<ConfirmationModal.Content>
|
||||||
|
<span>
|
||||||
|
It seems {data.node?.display_name} already exists. Replacing it
|
||||||
|
will switch the current component. Proceed with replacement?
|
||||||
|
</span>
|
||||||
|
</ConfirmationModal.Content>
|
||||||
|
<ConfirmationModal.Trigger>
|
||||||
|
</ConfirmationModal.Trigger>
|
||||||
|
</ConfirmationModal>
|
||||||
<EditNodeModal
|
<EditNodeModal
|
||||||
data={data}
|
data={data}
|
||||||
setData={setData}
|
setData={setData}
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,7 @@ export type PaginatorComponentType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConfirmationModalType = {
|
export type ConfirmationModalType = {
|
||||||
|
onCancel?: () => void;
|
||||||
title: string;
|
title: string;
|
||||||
titleHeader: string;
|
titleHeader: string;
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ export type FlowsContextType = {
|
||||||
removeFlow: (id: string) => void;
|
removeFlow: (id: string) => void;
|
||||||
addFlow: (
|
addFlow: (
|
||||||
newProject: boolean,
|
newProject: boolean,
|
||||||
flow?: FlowType
|
flow?: FlowType,
|
||||||
|
override?: boolean
|
||||||
) => Promise<String | undefined>;
|
) => Promise<String | undefined>;
|
||||||
updateFlow: (newFlow: FlowType) => void;
|
updateFlow: (newFlow: FlowType) => void;
|
||||||
incrementNodeId: () => string;
|
incrementNodeId: () => string;
|
||||||
|
|
@ -44,7 +45,10 @@ export type FlowsContextType = {
|
||||||
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
||||||
setTweak: (tweak: tweakType) => tweakType | void;
|
setTweak: (tweak: tweakType) => tweakType | void;
|
||||||
getTweak: tweakType;
|
getTweak: tweakType;
|
||||||
saveComponent: (component: NodeDataType) => Promise<String | undefined>;
|
saveComponent: (
|
||||||
|
component: NodeDataType,
|
||||||
|
override: boolean
|
||||||
|
) => Promise<String | undefined>;
|
||||||
deleteComponent: (key: string) => void;
|
deleteComponent: (key: string) => void;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ import {
|
||||||
XYPosition,
|
XYPosition,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import ShortUniqueId from "short-unique-id";
|
import ShortUniqueId from "short-unique-id";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES, specialCharsRegex } from "../constants/constants";
|
import {
|
||||||
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
|
specialCharsRegex,
|
||||||
|
} from "../constants/constants";
|
||||||
import { APITemplateType, TemplateVariableType } from "../types/api";
|
import { APITemplateType, TemplateVariableType } from "../types/api";
|
||||||
import {
|
import {
|
||||||
FlowType,
|
FlowType,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue