From 85dc34d8d746cdfb44f8f639fc08683ceb2e96f1 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Sat, 18 Nov 2023 22:09:41 -0300 Subject: [PATCH] Modularized shareModal to be used with components and flows --- .../EditFlowSettingsComponent/index.tsx | 2 - src/frontend/src/modals/exportModal/index.tsx | 4 +- .../src/modals/flowSettingsModal/index.tsx | 2 - src/frontend/src/modals/shareModal/index.tsx | 211 ++++++++++++++++++ .../extraSidebarComponent/index.tsx | 128 +---------- .../components/nodeToolbarComponent/index.tsx | 116 ++-------- src/frontend/src/types/components/index.ts | 2 - 7 files changed, 234 insertions(+), 231 deletions(-) create mode 100644 src/frontend/src/modals/shareModal/index.tsx diff --git a/src/frontend/src/components/EditFlowSettingsComponent/index.tsx b/src/frontend/src/components/EditFlowSettingsComponent/index.tsx index fafb0f3d3..ac3932132 100644 --- a/src/frontend/src/components/EditFlowSettingsComponent/index.tsx +++ b/src/frontend/src/components/EditFlowSettingsComponent/index.tsx @@ -12,8 +12,6 @@ export const EditFlowSettings: React.FC = ({ setInvalidName, description, maxLength = 50, - flows, - tabId, setName, setDescription, }: InputProps): JSX.Element => { diff --git a/src/frontend/src/modals/exportModal/index.tsx b/src/frontend/src/modals/exportModal/index.tsx index 9d4da4a12..f58a9cac2 100644 --- a/src/frontend/src/modals/exportModal/index.tsx +++ b/src/frontend/src/modals/exportModal/index.tsx @@ -40,8 +40,6 @@ const ExportModal = forwardRef( @@ -74,6 +72,7 @@ const ExportModal = forwardRef( description, name, last_tested_version: version, + is_component: false, }, name!, description @@ -90,6 +89,7 @@ const ExportModal = forwardRef( description, name, last_tested_version: version, + is_component: false, }), name!, description diff --git a/src/frontend/src/modals/flowSettingsModal/index.tsx b/src/frontend/src/modals/flowSettingsModal/index.tsx index 1d514adc9..9cd42ad61 100644 --- a/src/frontend/src/modals/flowSettingsModal/index.tsx +++ b/src/frontend/src/modals/flowSettingsModal/index.tsx @@ -40,8 +40,6 @@ export default function FlowSettingsModal({ setInvalidName={setInvalidName} name={name} description={description} - flows={flows} - tabId={tabId} setName={setName} setDescription={setDescription} /> diff --git a/src/frontend/src/modals/shareModal/index.tsx b/src/frontend/src/modals/shareModal/index.tsx new file mode 100644 index 000000000..4d958992c --- /dev/null +++ b/src/frontend/src/modals/shareModal/index.tsx @@ -0,0 +1,211 @@ +import { + ReactNode, + forwardRef, + useContext, + useEffect, + useRef, + useState, +} from "react"; +import EditFlowSettings from "../../components/EditFlowSettingsComponent"; +import IconComponent from "../../components/genericIconComponent"; +import { TagsSelector } from "../../components/tagsSelectorComponent"; +import ToggleShadComponent from "../../components/toggleShadComponent"; +import { Button } from "../../components/ui/button"; +import { Checkbox } from "../../components/ui/checkbox"; +import { alertContext } from "../../contexts/alertContext"; +import { FlowsContext } from "../../contexts/flowsContext"; +import { getStoreTags, saveFlowStore } from "../../controllers/API"; +import { FlowType } from "../../types/flow"; +import { removeApiKeys } from "../../utils/reactflowUtils"; +import { getTagsIds } from "../../utils/storeUtils"; +import BaseModal from "../baseModal"; + +const ShareModal = forwardRef( + ( + props: { + children?: ReactNode; + is_component: boolean; + component: FlowType; + open?: boolean; + setOpen?: (open: boolean) => void; + }, + ref + ): JSX.Element => { + const { version, addFlow } = useContext(FlowsContext); + const { setSuccessData, setErrorData } = useContext(alertContext); + const [checked, setChecked] = useState(true); + const [name, setName] = useState(props.component?.name ?? ""); + const [description, setDescription] = useState( + props.component?.description ?? "" + ); + const [open, setOpen] = useState(props.children ? false : true); + + const nameComponent = props.is_component ? "Component" : "Flow"; + + const [tags, setTags] = useState([]); + const [sharePublic, setSharePublic] = useState(true); + const [selectedTags, setSelectedTags] = useState>(new Set()); + const tagListId = useRef<{ id: string; name: string }[]>([]); + + useEffect(() => { + getStoreTags().then((res) => { + tagListId.current = res; + let tags = res.map((tag) => tag.name); + setTags(tags); + }); + }, []); + + useEffect(() => { + setName(props.component?.name ?? ""); + setDescription(props.component?.description ?? ""); + }, [props.component]); + + function handleTagSelection(tag: string) { + setSelectedTags((prev) => { + const newSet = new Set(prev); + if (newSet.has(tag)) { + newSet.delete(tag); + } else { + newSet.add(tag); + } + return newSet; + }); + } + + const handleShareComponent = () => { + const saveFlow: FlowType = checked + ? { + id: props.component!.id, + data: props.component!.data, + description, + name, + last_tested_version: version, + is_component: props.is_component, + } + : removeApiKeys({ + id: props.component!.id, + data: props.component!.data, + description, + name, + last_tested_version: version, + is_component: props.is_component, + }); + saveFlowStore( + saveFlow, + getTagsIds(Array.from(selectedTags), tagListId), + sharePublic + ).then( + () => { + if (props.is_component) { + addFlow(true, saveFlow); + } + setSuccessData({ + title: `${nameComponent} shared successfully`, + }); + }, + (err) => { + setErrorData({ + title: "Error sharing flow", + list: [err["response"]["data"]["detail"]], + }); + } + ); + }; + + return ( + + + {props.children ? props.children : <>} + + + Share + + + +
+ { + setChecked(event); + }} + /> + +
+ + Caution: Uncheck this box only removes API keys from fields + specifically designated for API keys. + +
+
+ +
{ + setSharePublic(!sharePublic); + }} + > + {sharePublic ? ( + + This flow will be avaliable for everyone + + ) : ( + + This flow will be avaliable just for you + + )} +
+
+
+ + Add some tags to your {nameComponent} + + +
+
+
+ + + + +
+ ); + } +); +export default ShareModal; diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx index a3c068935..35e1d78bd 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx @@ -1,22 +1,16 @@ import { cloneDeep } from "lodash"; -import { useContext, useEffect, useMemo, useRef, useState } from "react"; -import { ReactFlowJsonObject } from "reactflow"; +import { useContext, useEffect, useMemo, useState } from "react"; import ShadTooltip from "../../../../components/ShadTooltipComponent"; import IconComponent from "../../../../components/genericIconComponent"; -import { TagsSelector } from "../../../../components/tagsSelectorComponent"; -import ToggleShadComponent from "../../../../components/toggleShadComponent"; import { Input } from "../../../../components/ui/input"; import { Separator } from "../../../../components/ui/separator"; import { alertContext } from "../../../../contexts/alertContext"; import { FlowsContext } from "../../../../contexts/flowsContext"; import { typesContext } from "../../../../contexts/typesContext"; -import { getStoreTags, saveFlowStore } from "../../../../controllers/API"; import ApiModal from "../../../../modals/ApiModal"; -import ConfirmationModal from "../../../../modals/ConfirmationModal"; import ExportModal from "../../../../modals/exportModal"; +import ShareModal from "../../../../modals/shareModal"; import { APIClassType, APIObjectType } from "../../../../types/api"; -import { FlowType } from "../../../../types/flow"; -import { getTagsIds } from "../../../../utils/storeUtils"; import { nodeColors, nodeIconsLucide, @@ -35,10 +29,9 @@ export default function ExtraSidebar(): JSX.Element { useContext(typesContext); const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt, version } = useContext(FlowsContext); - const { setSuccessData, setErrorData } = useContext(alertContext); + const { setErrorData } = useContext(alertContext); const [dataFilter, setFilterData] = useState(data); const [search, setSearch] = useState(""); - const [sharePublic, setSharePublic] = useState(true); const isPending = tabsState[tabId]?.isPending; function onDragStart( event: React.DragEvent, @@ -55,30 +48,6 @@ export default function ExtraSidebar(): JSX.Element { event.dataTransfer.setData("nodedata", JSON.stringify(data)); } - const [tags, setTags] = useState([]); - const [selectedTags, setSelectedTags] = useState>(new Set()); - const tagListId = useRef<{ id: string; name: string }[]>([]); - - useEffect(() => { - getStoreTags().then((res) => { - tagListId.current = res; - let tags = res.map((tag) => tag.name); - setTags(tags); - }); - }, []); - - function handleTagSelection(tag: string) { - setSelectedTags((prev) => { - const newSet = new Set(prev); - if (newSet.has(tag)) { - newSet.delete(tag); - } else { - newSet.add(tag); - } - return newSet; - }); - } - // Handle showing components after use search input function handleSearchInput(e: string) { if (e === "") { @@ -172,39 +141,6 @@ export default function ExtraSidebar(): JSX.Element { } }, [getFilterEdge]); - const handleShareFlow = () => { - const reactFlow = reactFlowInstance - ? reactFlowInstance.toObject() - : (flow!.data as ReactFlowJsonObject); - const saveFlow: FlowType = { - name: flow!.name, - id: flow!.id, - description: flow!.description, - data: { - ...reactFlow, - }, - is_component: false, - last_tested_version: version, - }; - saveFlowStore( - saveFlow, - getTagsIds(Array.from(selectedTags), tagListId), - sharePublic - ).then( - () => { - setSuccessData({ - title: "Flow shared successfully", - }); - }, - (err) => { - setErrorData({ - title: "Error sharing flow", - list: [err["response"]["data"]["detail"]], - }); - } - ); - }; - useEffect(() => { if (getFilterEdge?.length > 0) { setFilterData((_) => { @@ -244,63 +180,15 @@ export default function ExtraSidebar(): JSX.Element { const ModalMemo = useMemo( () => ( - { - handleShareFlow(); - }} - titleHeader="" - cancelText="Cancel" - > - -
-
- -
{ - setSharePublic(!sharePublic); - }} - > - {sharePublic ? ( - - This flow will be avaliable for everyone - - ) : ( - - This flow will be avaliable just for you - - )} -
-
-
- Add some tags to your Flow - -
-
-
- + +
-
-
+ + ), - [sharePublic, tags, selectedTags] + [] ); const ExportMemo = useMemo( diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 7c903b369..82dea077f 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -1,29 +1,25 @@ import { cloneDeep } from "lodash"; -import { useContext, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { useReactFlow, useUpdateNodeInternals } from "reactflow"; import ShadTooltip from "../../../../components/ShadTooltipComponent"; import IconComponent from "../../../../components/genericIconComponent"; -import { TagsSelector } from "../../../../components/tagsSelectorComponent"; -import ToggleShadComponent from "../../../../components/toggleShadComponent"; import { Select, SelectContent, SelectItem, SelectTrigger, } from "../../../../components/ui/select-custom"; -import { alertContext } from "../../../../contexts/alertContext"; import { FlowsContext } from "../../../../contexts/flowsContext"; -import { getStoreTags, saveFlowStore } from "../../../../controllers/API"; -import ConfirmationModal from "../../../../modals/ConfirmationModal"; import EditNodeModal from "../../../../modals/EditNodeModal"; +import ShareModal from "../../../../modals/shareModal"; import { nodeToolbarPropsType } from "../../../../types/components"; +import { FlowType } from "../../../../types/flow"; import { createFlowComponent, downloadNode, expandGroupNode, updateFlowPosition, } from "../../../../utils/reactflowUtils"; -import { getTagsIds } from "../../../../utils/storeUtils"; import { classNames } from "../../../../utils/utils"; export default function NodeToolbarComponent({ @@ -52,7 +48,6 @@ export default function NodeToolbarComponent({ ); const updateNodeInternals = useUpdateNodeInternals(); const { getNodeId } = useContext(FlowsContext); - const { setErrorData, setSuccessData } = useContext(alertContext); function canMinimize() { let countHandles: number = 0; @@ -70,53 +65,13 @@ export default function NodeToolbarComponent({ const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [showconfirmShare, setShowconfirmShare] = useState(false); const [selectedValue, setSelectedValue] = useState(""); - const [sharePublic, setSharePublic] = useState(true); - const [tags, setTags] = useState([]); - const [selectedTags, setSelectedTags] = useState>(new Set()); - const tagListId = useRef<{ id: string; name: string }[]>([]); + + const [flowComponent, setFlowComponent] = useState(); useEffect(() => { - getStoreTags().then((res) => { - tagListId.current = res; - let tags = res.map((tag) => tag.name); - setTags(tags); - }); - }, []); + setFlowComponent(createFlowComponent(data, version)); + }, [data]); - function handleTagSelection(tag: string) { - setSelectedTags((prev) => { - const newSet = new Set(prev); - if (newSet.has(tag)) { - newSet.delete(tag); - } else { - newSet.add(tag); - } - return newSet; - }); - } - - function handleShareComponent() { - const componentFlow = cloneDeep(data); - saveComponent(componentFlow).then(() => { - saveFlowStore( - createFlowComponent(componentFlow, version), - getTagsIds(Array.from(selectedTags), tagListId), - sharePublic - ).then( - (_) => { - setSuccessData({ - title: "Component shared successfully", - }); - }, - (err) => { - setErrorData({ - title: "Error sharing component", - list: [err["response"]["data"]["detail"]], - }); - } - ); - }); - } const handleSelectChange = (event) => { switch (event) { case "advanced": @@ -306,57 +261,12 @@ export default function NodeToolbarComponent({ <> )} - {showconfirmShare && ( - { - handleShareComponent(); - }} - titleHeader="" - cancelText="Cancel" - open={showconfirmShare} - onClose={(modal) => { - setShowconfirmShare(modal); - }} - > - -
-
- -
- {sharePublic - ? "This component will be avaliable for everyone" - : "This component will be avaliable just for you"} -
-
-
- - Add some tags to your component - - -
-
{" "} -
- -
-
-
- )} + diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 472311907..4c96c91e9 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -223,8 +223,6 @@ export type InputProps = { name: string | null; description: string | null; maxLength?: number; - flows: Array<{ id: string; name: string; description: string }>; - tabId: string; invalidName?: boolean; setName: (name: string) => void; setDescription: (description: string) => void;