Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add EmbedModal for sharing embed code in PublishDropdown #6103

Draft
wants to merge 12 commits into
base: PlaygroundPage
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,32 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { ENABLE_WIDGET } from "@/customization/feature-flags";
import getWidgetCode from "@/modals/apiModal/utils/get-widget-code";
import EmbedModal from "@/modals/EmbedModal/embed-modal";
import { Switch } from "@/components/ui/switch";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import useFlowStore from "@/stores/flowStore";

import useAuthStore from "@/stores/authStore";
import { useState } from "react";
export default function PublishDropdown() {
const domain = window.location.origin;
const flowName = useFlowsManagerStore((state) => state.currentFlow?.name);
const [openEmbedModal, setOpenEmbedModal] = useState(false);
const flowId = useFlowsManagerStore((state) => state.currentFlow?.id);
const flowName = useFlowsManagerStore((state) => state.currentFlow?.name);
const isPublished = useFlowsManagerStore(
(state) => state.currentFlow?.public,
);
const hasIO = useFlowStore((state) => state.hasIO);
const isAuth = useAuthStore((state) => !!state.autoLogin);

// using js const instead of applies.css because of group tag
const groupStyle = "text-muted-foreground group-hover:text-foreground";
const externalUrlStyle =
"opacity-0 transition-all duration-300 group-hover:translate-x-3 group-hover:opacity-100 group-focus-visible:translate-x-3 group-focus-visible:opacity-100";

return (
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="default" className="!h-8 !w-[95px] font-medium">
Expand All @@ -30,6 +41,7 @@ export default function PublishDropdown() {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
forceMount
sideOffset={10}
alignOffset={-10}
align="end"
Expand Down Expand Up @@ -60,10 +72,21 @@ export default function PublishDropdown() {
className={`${groupStyle} icon-size mr-2`}
/>
<span>Standalone app</span>
<IconComponent
name="ExternalLink"
className={`icon-size ml-auto mr-3 ${externalUrlStyle} text-foreground`}
/>
<div
className={`icon-size ml-auto pr-8 text-foreground`}
>
<Switch
className="w-9 h-5"
checked={isPublished}
onCheckedChange={(checked) => {
console.log(checked);
}}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
/>
</div>
</div>
</DropdownMenuItem>
</div>
Expand All @@ -77,15 +100,15 @@ export default function PublishDropdown() {
<span>API access</span>
</div>
</DropdownMenuItem>
<DropdownMenuItem className="deploy-dropdown-item group">
{ENABLE_WIDGET && <DropdownMenuItem onClick={() => setOpenEmbedModal(true)} className="deploy-dropdown-item group">
<div className="group-hover:bg-accent">
<IconComponent
name="Columns2"
className={`${groupStyle} icon-size mr-2`}
/>
<span>Embed into site</span>
</div>
</DropdownMenuItem>
</DropdownMenuItem>}
<DropdownMenuItem className="deploy-dropdown-item group">
<div className="group-hover:bg-accent">
<IconComponent
Expand All @@ -101,5 +124,7 @@ export default function PublishDropdown() {
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<EmbedModal open={openEmbedModal} setOpen={setOpenEmbedModal} flowId={flowId ?? ""} flowName={flowName ?? ""} isAuth={isAuth} tweaksBuildedObject={{}} activeTweaks={false}></EmbedModal>
</>
);
}
1 change: 1 addition & 0 deletions src/frontend/src/customization/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export const ENABLE_NEW_LOGO = true;
export const ENABLE_DATASTAX_LANGFLOW = false;
export const ENABLE_HOMEPAGE = true;
export const ENABLE_PUBLISH = true;
export const ENABLE_WIDGET = true;
82 changes: 82 additions & 0 deletions src/frontend/src/modals/EmbedModal/embed-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { useState } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark,oneLight } from "react-syntax-highlighter/dist/cjs/styles/prism";
import BaseModal from "../baseModal";
import IconComponent from "../../components/common/genericIconComponent";
import { Button } from "../../components/ui/button";
import getWidgetCode from "../apiModal/utils/get-widget-code";
import { useDarkStore } from "@/stores/darkStore";

interface EmbedModalProps {
open: boolean;
setOpen: (open: boolean) => void;
flowId: string;
flowName: string;
isAuth: boolean;
tweaksBuildedObject: {};
activeTweaks: boolean;
}

export default function EmbedModal({ open, setOpen, flowId, flowName, isAuth, tweaksBuildedObject, activeTweaks }: EmbedModalProps) {
const isDark = useDarkStore((state) => state.dark);
const [isCopied, setIsCopied] = useState<boolean>(false);
const widgetProps = { flowId: flowId, flowName: flowName, isAuth: isAuth, tweaksBuildedObject: tweaksBuildedObject, activeTweaks: activeTweaks }
const embedCode = getWidgetCode({...widgetProps, copy: false })
const copyCode = getWidgetCode({...widgetProps, copy: true });
const copyToClipboard = () => {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
return;
}

navigator.clipboard.writeText(copyCode).then(() => {
setIsCopied(true);

setTimeout(() => {
setIsCopied(false);
}, 2000);
});
};

return (
<BaseModal open={open} setOpen={setOpen} size="retangular">
<BaseModal.Header>
<div className="flex items-center gap-2 text-[16px] font-semibold">
<IconComponent name="Columns2" className="icon-size" />
Embed into site
</div>
</BaseModal.Header>
<BaseModal.Content className="">
<div className=" flex h-full w-full relative">
<Button
variant="ghost"
size="icon"
onClick={copyToClipboard}
data-testid="btn-copy-code"
className="absolute top-2 right-2 group !hover:bg-foreground bg-muted-foreground"
>
{isCopied ? (
<IconComponent
name="Check"
className="h-5 w-5 text-muted group-hover:text-muted-foreground"
/>
) : (
<IconComponent
name="Copy"
className="!h-6 !w-6 text-muted group-hover:text-muted-foreground"
/>
)}
</Button>
<SyntaxHighlighter
showLineNumbers={true}
wrapLongLines={true}
language="html"
style={isDark ? oneDark : oneLight}
className="!mt-0 h-full w-full overflow-scroll !rounded-b-md border border-border text-left !custom-scroll"
>
{embedCode}
</SyntaxHighlighter>
</div>
</BaseModal.Content>
</BaseModal>
);
}
20 changes: 15 additions & 5 deletions src/frontend/src/modals/apiModal/utils/get-widget-code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,20 @@ export default function getWidgetCode({
flowId,
flowName,
isAuth,
copy = false,
}: GetCodeType): string {
return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/[email protected]/dist/build/static/js/bundle.min.js""></script>

const source = copy? `<script
src="https://cdn.jsdelivr.net/gh/logspace-ai/[email protected]/dist/build/static/js/bundle.min.js">
</script>`:
`<script
src="https://cdn.jsdelivr.net/gh/logspace-ai/[email protected]/dist/
build/static/js/bundle.min.js">
</script>`



return `${source}
<langflow-chat
window_title="${flowName}"
flow_id="${flowId}"
Expand All @@ -20,7 +31,6 @@ export default function getWidgetCode({
? `
api_key="..."`
: ""
}
></langflow-chat>`;
}
}>
</langflow-chat>`;
}
5 changes: 5 additions & 0 deletions src/frontend/src/modals/baseModal/helpers/switch-case-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export const switchCaseModalSize = (size: string) => {
height = "h-[95vh]";
break;

case "retangular":
minWidth = "!min-w-[900px]";
height = "min-h-[232px]";
break;

default:
minWidth = "min-w-[80vw]";
height = "h-[90vh]";
Expand Down
11 changes: 7 additions & 4 deletions src/frontend/src/modals/baseModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,18 @@ const Trigger: React.FC<TriggerProps> = ({

const Header: React.FC<{
children: ReactNode;
description: string | JSX.Element | null;
description?: string | JSX.Element | null;
}> = ({ children, description }: modalHeaderType): JSX.Element => {
return (
<DialogHeader>
<DialogTitle className="line-clamp-1 flex items-center pb-0.5 text-base">
{children}
</DialogTitle>
<DialogDescription className="line-clamp-2 text-sm">
{description}
</DialogDescription>
{description && (
<DialogDescription className="line-clamp-2 text-sm">
{description}
</DialogDescription>
)}
</DialogHeader>
);
};
Expand Down Expand Up @@ -159,6 +161,7 @@ interface BaseModalProps {
setOpen?: (open: boolean) => void;
size?:
| "x-small"
| "retangular"
| "smaller"
| "small"
| "medium"
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/style/classes.css
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,13 @@ pre code {
display: inline-block;
width: 100%;
/* Background color */
background-color: hsl(var(--code-background)) !important;
background-color: hsl(var(--muted)) !important;
color: hsl(var(--code-foreground)) !important;
}

pre {
/* Background color */
background-color: hsl(var(--code-background)) !important;
background-color: hsl(var(--muted)) !important;
}

.prose li::marker {
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/types/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ export type iconsType = {

export type modalHeaderType = {
children: ReactNode;
description: string | JSX.Element | null;
description?: string | JSX.Element | null;
};

export type codeAreaModalPropsType = {
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/types/flow/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type FlowType = {
folder_id?: string;
webhook?: boolean;
locked?: boolean | null;
public?: boolean;
};

export type GenericNodeType = Node<NodeDataType, "genericNode">;
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/types/tweaks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export type GetCodeType = {
tweaksBuildedObject: {};
endpointName?: string | null;
activeTweaks: boolean;
copy?: boolean;
};