diff --git a/packages/web/package.json b/packages/web/package.json index 6856221b6..bc71241db 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -74,6 +74,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-navigation-menu": "^1.2.0", "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.0", diff --git a/packages/web/src/app/[domain]/chat/[id]/components/shareChatDialogButton.tsx b/packages/web/src/app/[domain]/chat/[id]/components/shareChatDialogButton.tsx new file mode 100644 index 000000000..903535e30 --- /dev/null +++ b/packages/web/src/app/[domain]/chat/[id]/components/shareChatDialogButton.tsx @@ -0,0 +1,121 @@ +'use client'; + +import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Label } from "@/components/ui/label"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import { cn, isServiceError } from "@/lib/utils"; +import { ChatVisibility } from "@sourcebot/db"; +import { GlobeIcon } from "@radix-ui/react-icons"; +import { LockIcon, Router } from "lucide-react"; +import { useEffect, useState } from "react"; +import { changeChatVisibility } from "@/features/chat/actions"; +import { toast } from "@/components/hooks/use-toast"; +import { useRouter } from "next/navigation"; + +interface ShareChatDialogButtonProps { + visibility: ChatVisibility; + chatId: string; +} + +export const ShareChatDialogButton = ({ visibility,chatId }: ShareChatDialogButtonProps) => { + const [isOpen, setIsOpen] = useState(false); + const [selectedVisibility, setSelectedVisibility] = useState(visibility); + const router=useRouter() + + useEffect(() => { + setSelectedVisibility(visibility); + }, [visibility]); + + const onChangeVisibility = (visibility: ChatVisibility) => { + changeChatVisibility({ + chatId: chatId, + visibility, + }).then((response)=>{ + if (isServiceError(response)) { + toast({ + description: `❌ Failed to change chat visibility. Reason: ${response.message}`, + variant: "destructive", + }); + } + + toast({ + description: `Chat visibility changed to ${visibility}`, + }); + setSelectedVisibility(visibility); + router.refresh() + }) + }; + + return ( + + + + + Share chat + + Choose who can access this chat. + + + onChangeVisibility(value as ChatVisibility)} + > + + + + + + + + + ); +}; diff --git a/packages/web/src/app/[domain]/chat/[id]/page.tsx b/packages/web/src/app/[domain]/chat/[id]/page.tsx index c22cbd0c9..2ec20ed03 100644 --- a/packages/web/src/app/[domain]/chat/[id]/page.tsx +++ b/packages/web/src/app/[domain]/chat/[id]/page.tsx @@ -11,6 +11,7 @@ import { auth } from '@/auth'; import { AnimatedResizableHandle } from '@/components/ui/animatedResizableHandle'; import { ChatSidePanel } from '../components/chatSidePanel'; import { ResizablePanelGroup } from '@/components/ui/resizable'; +import { ShareChatDialogButton } from './components/shareChatDialogButton'; interface PageProps { params: Promise<{ @@ -58,14 +59,17 @@ export default async function Page(props: PageProps) { domain={params.domain} homePath={`/${params.domain}/chat`} > -
- / - +
+
+ / + +
+
, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + + + + + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + +export { RadioGroup, RadioGroupItem } diff --git a/packages/web/src/features/chat/actions.ts b/packages/web/src/features/chat/actions.ts index 85084e9e3..11a0cdd07 100644 --- a/packages/web/src/features/chat/actions.ts +++ b/packages/web/src/features/chat/actions.ts @@ -346,6 +346,41 @@ export const submitFeedback = async ({ }) ) +export const changeChatVisibility=async ({chatId,visibility}:{chatId:string,visibility:ChatVisibility})=>sew(()=> + withOptionalAuthV2(async ({org,user,prisma})=>{ + const chat=await prisma.chat.findUnique({ + where:{ + id:chatId, + orgId:org.id, + } + }) + + if (!chat) { + return notFound(); + } + + if (chat.createdById !== user?.id) { + return notFound(); + } + + console.log(chat) + + await prisma.chat.update({ + where: { + id: chatId, + orgId: org.id, + }, + data: { + visibility, + }, + }); + + return { + success: true, + } + }) +) + /** * Returns the subset of information about the configured language models * that we can safely send to the client. diff --git a/yarn.lock b/yarn.lock index 49b180d47..55391f51c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4900,6 +4900,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/primitive@npm:1.1.3": + version: 1.1.3 + resolution: "@radix-ui/primitive@npm:1.1.3" + checksum: 10c0/88860165ee7066fa2c179f32ffcd3ee6d527d9dcdc0e8be85e9cb0e2c84834be8e3c1a976c74ba44b193f709544e12f54455d892b28e32f0708d89deda6b9f1d + languageName: node + linkType: hard + "@radix-ui/react-accordion@npm:^1.2.11": version: 1.2.11 resolution: "@radix-ui/react-accordion@npm:1.2.11" @@ -5735,6 +5742,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-presence@npm:1.1.5": + version: 1.1.5 + resolution: "@radix-ui/react-presence@npm:1.1.5" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/d0e61d314250eeaef5369983cb790701d667f51734bafd98cf759072755562018052c594e6cdc5389789f4543cb0a4d98f03ff4e8f37338d6b5bf51a1700c1d1 + languageName: node + linkType: hard + "@radix-ui/react-primitive@npm:1.0.3": version: 1.0.3 resolution: "@radix-ui/react-primitive@npm:1.0.3" @@ -5812,6 +5839,61 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-radio-group@npm:^1.3.8": + version: 1.3.8 + resolution: "@radix-ui/react-radio-group@npm:1.3.8" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-roving-focus": "npm:1.1.11" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + "@radix-ui/react-use-previous": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/23af8e8b833da1fc4aa4e67c3607dedee4fc5b39278d2e2b820bec7f7b3c0891b006a8a35c57ba436ddf18735bbd8dad9a598d14632a328753a875fde447975c + languageName: node + linkType: hard + +"@radix-ui/react-roving-focus@npm:1.1.11": + version: 1.1.11 + resolution: "@radix-ui/react-roving-focus@npm:1.1.11" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/2cd43339c36e89a3bf1db8aab34b939113dfbde56bf3a33df2d74757c78c9489b847b1962f1e2441c67e41817d120cb6177943e0f655f47bc1ff8e44fd55b1a2 + languageName: node + linkType: hard + "@radix-ui/react-roving-focus@npm:1.1.2": version: 1.1.2 resolution: "@radix-ui/react-roving-focus@npm:1.1.2" @@ -6145,6 +6227,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-use-callback-ref@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-use-callback-ref@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/5f6aff8592dea6a7e46589808912aba3fb3b626cf6edd2b14f01638b61dbbe49eeb9f67cd5601f4c15b2fb547b9a7e825f7c4961acd4dd70176c969ae405f8d8 + languageName: node + linkType: hard + "@radix-ui/react-use-controllable-state@npm:1.0.1": version: 1.0.1 resolution: "@radix-ui/react-use-controllable-state@npm:1.0.1" @@ -8305,6 +8400,7 @@ __metadata: "@radix-ui/react-label": "npm:^2.1.0" "@radix-ui/react-navigation-menu": "npm:^1.2.0" "@radix-ui/react-popover": "npm:^1.1.6" + "@radix-ui/react-radio-group": "npm:^1.3.8" "@radix-ui/react-scroll-area": "npm:^1.1.0" "@radix-ui/react-select": "npm:^2.1.6" "@radix-ui/react-separator": "npm:^1.1.0"