From cf434eb7baab9f9c32f50ecbd7b12aafd3e820cb Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Fri, 27 Oct 2023 01:11:01 -0300 Subject: [PATCH] feat(tagsSelectorComponent): add TagsSelector component to allow users to select tags for a flow feat(tagsSelectorComponent): add TagComponent to render individual tags in the TagsSelector component fix(API): add tags and publicFlow parameters to saveFlowStore function to save tags and set flow visibility fix(ConfirmationModal): add size prop to allow customizing the size of the modal feat(ExtraSidebar): add TagsSelector component to the Share Flow confirmation modal to allow users to select tags for the flow feat(ExtraSidebar): add ToggleShadComponent to allow users to toggle the visibility of the shared flow fix(ExtraSidebar): pass selected tags and sharePublic value to saveFlowStore function when sharing a flow fix(ExtraSidebar): add useEffect to fetch tags from API and initialize tags state fix(ExtraSidebar): add handleTagSelection function to handle tag selection in TagsSelector component fix(ExtraSidebar): update handleShareFlow function to pass selected tags and sharePublic value to saveFlowStore function fix(ExtraSidebar): update ConfirmationModal size prop to use size prop from component props fix(ExtraSidebar): update ConfirmationModal dependency array to include sharePublic value fix(NodeToolbarComponent): pass empty array as tags parameter to saveFlowStore function when sharing a component fix(MarketCardComponent): pass tags parameter to saveFlowStore function when saving a flow from the store fix(ConfirmationModal): add size prop to ConfirmationModalType to allow customizing the size of the modal --- .../tagsSelectorComponent/index.tsx | 26 ++++++++++ .../tagComponent/index.tsx | 30 +++++++++++ src/frontend/src/controllers/API/index.ts | 22 +++++--- .../src/modals/ConfirmationModal/index.tsx | 3 +- .../extraSidebarComponent/index.tsx | 52 +++++++++++++++++-- .../components/nodeToolbarComponent/index.tsx | 2 +- .../StorePage/components/market-card.tsx | 2 +- src/frontend/src/types/components/index.ts | 9 ++++ 8 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 src/frontend/src/components/tagsSelectorComponent/index.tsx create mode 100644 src/frontend/src/components/tagsSelectorComponent/tagComponent/index.tsx diff --git a/src/frontend/src/components/tagsSelectorComponent/index.tsx b/src/frontend/src/components/tagsSelectorComponent/index.tsx new file mode 100644 index 000000000..ed9ad6684 --- /dev/null +++ b/src/frontend/src/components/tagsSelectorComponent/index.tsx @@ -0,0 +1,26 @@ +import TagComponent from "./tagComponent"; + +export function TagsSelector({ + tags, + selectedTags, + setSelectedTags, +}: { + tags: string[]; + selectedTags: Set; + setSelectedTags: (tag: string) => void; +}) { + return ( +
+ {tags.map((tag, index) => { + return ( + + ); + })} +
+ ); +} diff --git a/src/frontend/src/components/tagsSelectorComponent/tagComponent/index.tsx b/src/frontend/src/components/tagsSelectorComponent/tagComponent/index.tsx new file mode 100644 index 000000000..e1436f642 --- /dev/null +++ b/src/frontend/src/components/tagsSelectorComponent/tagComponent/index.tsx @@ -0,0 +1,30 @@ +import { useState } from "react"; +import { Badge } from "../../ui/badge"; + +export default function TagComponent({ + tag, + handleClick, + selected, +}: { + tag: string; + handleClick: (tag: string) => void; + selected: boolean; +}) { + const [selectedTag, setSelectedTag] = useState(selected); + return ( + + ); +} diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index e0aceb9cd..2eac63dce 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -547,14 +547,18 @@ export async function addApiKeyStore(key: string) { * @returns {Promise} The saved flow data. * @throws Will throw an error if saving fails. */ -export async function saveFlowStore(newFlow: { - name?: string; - data: ReactFlowJsonObject | null; - description?: string; - style?: FlowStyleType; - is_component?: boolean; - parent?: string; -}): Promise { +export async function saveFlowStore( + newFlow: { + name?: string; + data: ReactFlowJsonObject | null; + description?: string; + style?: FlowStyleType; + is_component?: boolean; + parent?: string; + }, + tags: string[], + publicFlow = false +): Promise { try { const response = await api.post(`${BASE_URL_API}store/components/`, { name: newFlow.name, @@ -562,6 +566,8 @@ export async function saveFlowStore(newFlow: { description: newFlow.description, is_component: newFlow.is_component, parent: newFlow.parent, + tags: tags, + public: publicFlow, }); if (response.status !== 201) { diff --git a/src/frontend/src/modals/ConfirmationModal/index.tsx b/src/frontend/src/modals/ConfirmationModal/index.tsx index 349e42439..667245264 100644 --- a/src/frontend/src/modals/ConfirmationModal/index.tsx +++ b/src/frontend/src/modals/ConfirmationModal/index.tsx @@ -33,6 +33,7 @@ function ConfirmationModal({ data, index, onConfirm, + size, open, onClose, }: ConfirmationModalType) { @@ -50,7 +51,7 @@ function ConfirmationModal({ ); return ( - + {triggerChild} {title} diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx index 3347c02ab..ba516f7b7 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx @@ -3,6 +3,8 @@ import { useContext, useEffect, useMemo, useState } from "react"; import { ReactFlowJsonObject } from "reactflow"; 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"; @@ -35,6 +37,7 @@ export default function ExtraSidebar(): JSX.Element { const { setSuccessData, 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, @@ -51,6 +54,26 @@ export default function ExtraSidebar(): JSX.Element { event.dataTransfer.setData("nodedata", JSON.stringify(data)); } + const [tags, setTags] = useState([]); + const [selectedTags, setSelectedTags] = useState>(new Set()); + + useEffect(() => { + //TODO: get tags from api + setTags(["teste1", "teste2"]); + }, [setTags]); + + 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 === "") { @@ -116,7 +139,7 @@ export default function ExtraSidebar(): JSX.Element { }, is_component: false, }; - saveFlowStore(saveFlow).then( + saveFlowStore(saveFlow, Array.from(selectedTags), sharePublic).then( () => { setSuccessData({ title: "Flow shared successfully", @@ -176,6 +199,7 @@ export default function ExtraSidebar(): JSX.Element { title="Share Flow" confirmationText="Share" icon="Share2" + size="smaller" onConfirm={() => { handleShareFlow(); }} @@ -183,7 +207,29 @@ export default function ExtraSidebar(): JSX.Element { cancelText="Cancel" > - This flow will be available for everyone to use. +
+
+ +
+ {sharePublic + ? "This flow will be avaliable for everyone" + : "This flow will be avaliable just for you"} +
+
+
+ Add some tags to your Flow + +
+
@@ -192,7 +238,7 @@ export default function ExtraSidebar(): JSX.Element { ), - [] + [sharePublic] ); 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 4a2741587..340ca36e3 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -71,7 +71,7 @@ export default function NodeToolbarComponent({ function handleShareComponent() { const componentFlow = cloneDeep(data); saveComponent(componentFlow).then(() => { - saveFlowStore(createFlowComponent(componentFlow)).then( + saveFlowStore(createFlowComponent(componentFlow), []).then( (_) => { setSuccessData({ title: "Component shared successfully", diff --git a/src/frontend/src/pages/StorePage/components/market-card.tsx b/src/frontend/src/pages/StorePage/components/market-card.tsx index 8816c63df..ced232517 100644 --- a/src/frontend/src/pages/StorePage/components/market-card.tsx +++ b/src/frontend/src/pages/StorePage/components/market-card.tsx @@ -38,7 +38,7 @@ export const MarketCardComponent = ({ data }: { data: storeComponent }) => { const newFLow = cloneFLowWithParent(res, res.id, data.is_component); flowData.current = newFLow; console.log(newFLow); - saveFlowStore(newFLow) + saveFlowStore(newFLow, data.tags) .then(() => { setAdded(true); setLoading(false); diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index e6975ea73..a2cec293d 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -298,6 +298,15 @@ export type ConfirmationModalType = { onConfirm: (index, data) => void; open?: boolean; onClose?: (close: boolean) => void; + size?: + | "x-small" + | "smaller" + | "small" + | "medium" + | "large" + | "large-h-full" + | "small-h-full" + | "medium-h-full"; }; export type UserManagementType = {