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
This commit is contained in:
anovazzi1 2023-10-27 01:11:01 -03:00
commit cf434eb7ba
8 changed files with 132 additions and 14 deletions

View file

@ -0,0 +1,26 @@
import TagComponent from "./tagComponent";
export function TagsSelector({
tags,
selectedTags,
setSelectedTags,
}: {
tags: string[];
selectedTags: Set<string>;
setSelectedTags: (tag: string) => void;
}) {
return (
<div className=" flex h-full w-full flex-row flex-wrap gap-3 align-middle">
{tags.map((tag, index) => {
return (
<TagComponent
tag={tag}
selected={selectedTags.has(tag)}
key={index}
handleClick={setSelectedTags}
/>
);
})}
</div>
);
}

View file

@ -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 (
<button
onClick={() => {
setSelectedTag((prev) => !prev);
handleClick(tag);
}}
>
<Badge
size="md"
className={selectedTag ? "shadow-md" : ""}
variant={selectedTag ? "gray" : "secondary"}
>
{tag}
</Badge>
</button>
);
}

View file

@ -547,14 +547,18 @@ export async function addApiKeyStore(key: string) {
* @returns {Promise<any>} 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<FlowType> {
export async function saveFlowStore(
newFlow: {
name?: string;
data: ReactFlowJsonObject | null;
description?: string;
style?: FlowStyleType;
is_component?: boolean;
parent?: string;
},
tags: string[],
publicFlow = false
): Promise<FlowType> {
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) {

View file

@ -33,6 +33,7 @@ function ConfirmationModal({
data,
index,
onConfirm,
size,
open,
onClose,
}: ConfirmationModalType) {
@ -50,7 +51,7 @@ function ConfirmationModal({
);
return (
<BaseModal size="x-small" open={modalOpen} setOpen={setModalOpen}>
<BaseModal size={size ?? "x-small"} open={modalOpen} setOpen={setModalOpen}>
<BaseModal.Trigger asChild={asChild}>{triggerChild}</BaseModal.Trigger>
<BaseModal.Header description={titleHeader}>
<span className="pr-2">{title}</span>

View file

@ -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<any>,
@ -51,6 +54,26 @@ export default function ExtraSidebar(): JSX.Element {
event.dataTransfer.setData("nodedata", JSON.stringify(data));
}
const [tags, setTags] = useState<string[]>([]);
const [selectedTags, setSelectedTags] = useState<Set<string>>(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"
>
<ConfirmationModal.Content>
<span>This flow will be available for everyone to use.</span>
<div className="flex h-full w-full flex-col gap-7">
<div className="flex justify-start align-middle">
<ToggleShadComponent
disabled={false}
size="medium"
setEnabled={setSharePublic}
enabled={sharePublic}
/>
<div>
{sharePublic
? "This flow will be avaliable for everyone"
: "This flow will be avaliable just for you"}
</div>
</div>
<div className="w-full pt-2">
<span className="text-sm">Add some tags to your Flow</span>
<TagsSelector
tags={["teste1", "teste2"]}
selectedTags={new Set()}
setSelectedTags={handleTagSelection}
/>
</div>
</div>
</ConfirmationModal.Content>
<ConfirmationModal.Trigger tolltipContent="Share" side="top">
<div className={classNames("extra-side-bar-buttons")}>
@ -192,7 +238,7 @@ export default function ExtraSidebar(): JSX.Element {
</ConfirmationModal.Trigger>
</ConfirmationModal>
),
[]
[sharePublic]
);
const ExportMemo = useMemo(

View file

@ -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",

View file

@ -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);

View file

@ -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 = {