From 80c6f7cec616e301874038c42def80eff44e23e6 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 8 Dec 2023 16:05:14 -0300 Subject: [PATCH 1/2] fix(shareModal/index.tsx): fix conditional rendering of button text to display loader when loadingNames is true feat(shareModal/index.tsx): add loader animation to button when loadingNames is true to provide visual feedback to the user --- src/frontend/src/modals/shareModal/index.tsx | 29 +++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/modals/shareModal/index.tsx b/src/frontend/src/modals/shareModal/index.tsx index e64c650d4..4c6c23ea6 100644 --- a/src/frontend/src/modals/shareModal/index.tsx +++ b/src/frontend/src/modals/shareModal/index.tsx @@ -1,3 +1,4 @@ +import { Loader2 } from "lucide-react"; import { ReactNode, useContext, useEffect, useMemo, useState } from "react"; import EditFlowSettings from "../../components/EditFlowSettingsComponent"; import IconComponent from "../../components/genericIconComponent"; @@ -168,8 +169,18 @@ export default function ShareModal({
@@ -185,8 +196,18 @@ export default function ShareModal({ }} type="button" > - {is_component ? "Save and " : ""}Share{" "} - {!is_component ? "Flow" : ""} + {loadingNames ? ( + <> +
+ +
+ + ) : ( + <> + {is_component && !loadingNames ? "Save and " : ""}Share{" "} + {!is_component && !loadingNames ? "Flow" : ""} + + )} )} From b88968f85903399693d23824f916bcf0037a8f3e Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 8 Dec 2023 16:28:51 -0300 Subject: [PATCH 2/2] feat(API): add updateFlowStore function to update an existing flow in the Store feat(shareModal): add functionality to update a shared component or flow --- src/frontend/src/controllers/API/index.ts | 43 ++++++++++++ src/frontend/src/modals/shareModal/index.tsx | 69 +++++++++++++------- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 4bcdf2779..ddb007047 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -817,3 +817,46 @@ export async function getStoreTags() { export const postLikeComponent = (componentId: string) => { return api.post(`${BASE_URL_API}store/users/likes/${componentId}`); }; + +/** + * Updates an existing flow in the Store. + * + * @param {FlowType} updatedFlow - The updated flow data. + * @returns {Promise} The updated flow data. + * @throws Will throw an error if the update fails. + */ +export async function updateFlowStore( + newFlow: { + name?: string; + data: ReactFlowJsonObject | null; + description?: string; + style?: FlowStyleType; + is_component?: boolean; + parent?: string; + last_tested_version?: string; + }, + tags: string[], + publicFlow = false, + id: string +): Promise { + try { + const response = await api.patch(`${BASE_URL_API}store/components/${id}`, { + name: newFlow.name, + data: newFlow.data, + description: newFlow.description, + is_component: newFlow.is_component, + parent: newFlow.parent, + tags: tags, + private: !publicFlow, + last_tested_version: newFlow.last_tested_version, + }); + + if (response.status !== 201) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.data; + } catch (error) { + console.error(error); + throw error; + } +} diff --git a/src/frontend/src/modals/shareModal/index.tsx b/src/frontend/src/modals/shareModal/index.tsx index 8e24b0189..d0c747863 100644 --- a/src/frontend/src/modals/shareModal/index.tsx +++ b/src/frontend/src/modals/shareModal/index.tsx @@ -11,6 +11,7 @@ import { getStoreComponents, getStoreTags, saveFlowStore, + updateFlowStore, } from "../../controllers/API"; import { FlowType } from "../../types/flow"; import { @@ -50,7 +51,9 @@ export default function ShareModal({ const [loadingTags, setLoadingTags] = useState(false); const [sharePublic, setSharePublic] = useState(true); const [selectedTags, setSelectedTags] = useState([]); - const [unavaliableNames, setUnavaliableNames] = useState([]); + const [unavaliableNames, setUnavaliableNames] = useState< + { id: string; name: string }[] + >([]); const { saveFlow, flows, tabId } = useContext(FlowsContext); useEffect(() => { @@ -70,13 +73,15 @@ export default function ShareModal({ }); } function handleGetNames() { - const unavaliableNames: Array = []; - getStoreComponents({ fields: ["name"], filterByUser: true }).then((res) => { - res?.results?.forEach((element: any) => { - unavaliableNames.push(element.name); - }); - setUnavaliableNames(unavaliableNames); - }); + const unavaliableNames: Array<{ id: string; name: string }> = []; + getStoreComponents({ fields: ["name", "id"], filterByUser: true }).then( + (res) => { + res?.results?.forEach((element: any) => { + unavaliableNames.push({ name: element.name, id: element.id }); + }); + setUnavaliableNames(unavaliableNames); + } + ); } useEffect(() => { @@ -84,7 +89,7 @@ export default function ShareModal({ setDescription(component?.description ?? ""); }, [component, open, internalOpen]); - const handleShareComponent = () => { + const handleShareComponent = (update = false) => { //remove file names from flows before sharing removeFileNameFromComponents(component); const flow: FlowType = checked @@ -105,28 +110,42 @@ export default function ShareModal({ is_component: is_component, }); - saveFlow(flows.find((flow) => flow.id === tabId)!, true); + function successShare() { + if (is_component) { + addFlow(true, flow); + } + setSuccessData({ + title: `${nameComponent} shared successfully`, + }); + } - saveFlowStore(flow!, getTagsIds(selectedTags, tags), sharePublic).then( - () => { - if (is_component) { - addFlow(true, flow); + saveFlow(flows.find((flow) => flow.id === tabId)!, true); + if (!update) + saveFlowStore(flow!, getTagsIds(selectedTags, tags), sharePublic).then( + successShare, + (err) => { + setErrorData({ + title: "Error sharing " + is_component ? "component" : "flow", + list: [err["response"]["data"]["detail"]], + }); } - setSuccessData({ - title: `${nameComponent} shared successfully`, - }); - }, - (err) => { + ); + else + updateFlowStore( + flow!, + getTagsIds(selectedTags, tags), + sharePublic, + unavaliableNames.find((e) => e.name === name)!.id + ).then(successShare, (err) => { setErrorData({ title: "Error sharing " + is_component ? "component" : "flow", list: [err["response"]["data"]["detail"]], }); - } - ); + }); }; const handleUpdateComponent = () => { - handleShareComponent(); + handleShareComponent(true); if (setOpen) setOpen(false); else internalSetOpen(false); }; @@ -134,7 +153,7 @@ export default function ShareModal({ let modalConfirmationButton = useMemo(() => { return ( <> - {unavaliableNames.includes(name) ? ( + {unavaliableNames.find((element) => element.name === name) ? ( ); - }, [unavaliableNames]); + }, [unavaliableNames, name]); return ( element.name)} description={description} setName={setName} setDescription={setDescription}