Skip to content

Commit

Permalink
add sharing manage feature
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Oct 23, 2023
1 parent 248e204 commit 3bc8b89
Show file tree
Hide file tree
Showing 19 changed files with 594 additions and 50 deletions.
8 changes: 8 additions & 0 deletions app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Boxes,
CalendarPlus,
Cloud,
ListStart,
Menu,
Plug,
} from "lucide-react";
Expand Down Expand Up @@ -39,9 +40,11 @@ import { openDialog as openQuotaDialog, quotaSelector } from "./store/quota.ts";
import { openDialog as openPackageDialog } from "./store/package.ts";
import { openDialog as openSub } from "./store/subscription.ts";
import { openDialog as openApiDialog } from "./store/api.ts";
import { openDialog as openSharingDialog } from "./store/sharing.ts";
import Package from "./routes/Package.tsx";
import Subscription from "./routes/Subscription.tsx";
import ApiKey from "./routes/ApiKey.tsx";
import ShareManagement from "./routes/ShareManagement.tsx";

function Settings() {
const { t } = useTranslation();
Expand Down Expand Up @@ -78,6 +81,10 @@ function Settings() {
<Boxes className={`h-4 w-4 mr-1`} />
{t("pkg.title")}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => dispatch(openSharingDialog())}>
<ListStart className={`h-4 w-4 mr-1`} />
{t("share.manage")}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => dispatch(openApiDialog())}>
<Plug className={`h-4 w-4 mr-1`} />
{t("api.title")}
Expand Down Expand Up @@ -149,6 +156,7 @@ function App() {
<ApiKey />
<Package />
<Subscription />
<ShareManagement />
</Provider>
);
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/assets/globals.less
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 240 4.8% 95.9%;
--muted: 60 26% 92%;
--muted-foreground: 240 3.8% 46.1%;

--accent: 37 26% 90%;
Expand Down
11 changes: 11 additions & 0 deletions app/src/assets/share-manager.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.share-table {
max-height: 60vh;
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: thin;
padding: 0 0.5rem;

&::-webkit-scrollbar {
width: 0.5rem;
}
}
14 changes: 7 additions & 7 deletions app/src/components/home/ChatInterface.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {useEffect, useRef, useState} from "react";
import {Message} from "../../conversation/types.ts";
import {useSelector} from "react-redux";
import {selectCurrent, selectMessages} from "../../store/chat.ts";
import {Button} from "../ui/button.tsx";
import {ChevronDown} from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { Message } from "../../conversation/types.ts";
import { useSelector } from "react-redux";
import { selectCurrent, selectMessages } from "../../store/chat.ts";
import { Button } from "../ui/button.tsx";
import { ChevronDown } from "lucide-react";
import MessageSegment from "../Message.tsx";
import {connectionEvent} from "../../events/connection.ts";
import { connectionEvent } from "../../events/connection.ts";

function ChatInterface() {
const ref = useRef(null);
Expand Down
36 changes: 23 additions & 13 deletions app/src/components/home/ChatWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import {useTranslation} from "react-i18next";
import React, {useEffect, useRef, useState} from "react";
import FileProvider, {FileObject} from "../FileProvider.tsx";
import {useDispatch, useSelector} from "react-redux";
import {selectAuthenticated, selectInit} from "../../store/auth.ts";
import {selectMessages, selectModel, selectWeb, setWeb} from "../../store/chat.ts";
import {manager} from "../../conversation/manager.ts";
import {formatMessage} from "../../utils.ts";
import { useTranslation } from "react-i18next";
import React, { useEffect, useRef, useState } from "react";
import FileProvider, { FileObject } from "../FileProvider.tsx";
import { useDispatch, useSelector } from "react-redux";
import { selectAuthenticated, selectInit } from "../../store/auth.ts";
import {
selectMessages,
selectModel,
selectWeb,
setWeb,
} from "../../store/chat.ts";
import { manager } from "../../conversation/manager.ts";
import { formatMessage } from "../../utils.ts";
import ChatInterface from "./ChatInterface.tsx";
import {Button} from "../ui/button.tsx";
import { Button } from "../ui/button.tsx";
import router from "../../router.ts";
import {BookMarked, ChevronRight, FolderKanban, Globe} from "lucide-react";
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "../ui/tooltip.tsx";
import {Toggle} from "../ui/toggle.tsx";
import {Input} from "../ui/input.tsx";
import { BookMarked, ChevronRight, FolderKanban, Globe } from "lucide-react";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "../ui/tooltip.tsx";
import { Toggle } from "../ui/toggle.tsx";
import { Input } from "../ui/input.tsx";
import EditorProvider from "../EditorProvider.tsx";
import ModelSelector from "./ModelSelector.tsx";

Expand Down
54 changes: 34 additions & 20 deletions app/src/components/home/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
import {useTranslation} from "react-i18next";
import {useDispatch, useSelector} from "react-redux";
import {RootState} from "../../store";
import {selectAuthenticated} from "../../store/auth.ts";
import {selectCurrent, selectHistory} from "../../store/chat.ts";
import {useRef, useState} from "react";
import {ConversationInstance} from "../../conversation/types.ts";
import {useToast} from "../ui/use-toast.ts";
import {copyClipboard, extractMessage, filterMessage, mobile, useAnimation, useEffectAsync} from "../../utils.ts";
import {deleteConversation, toggleConversation, updateConversationList} from "../../conversation/history.ts";
import {Button} from "../ui/button.tsx";
import {setMenu} from "../../store/menu.ts";
import {Copy, LogIn, Plus, RotateCw} from "lucide-react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../../store";
import { selectAuthenticated } from "../../store/auth.ts";
import { selectCurrent, selectHistory } from "../../store/chat.ts";
import { useRef, useState } from "react";
import { ConversationInstance } from "../../conversation/types.ts";
import { useToast } from "../ui/use-toast.ts";
import {
copyClipboard,
extractMessage,
filterMessage,
mobile,
useAnimation,
useEffectAsync,
} from "../../utils.ts";
import {
deleteConversation,
toggleConversation,
updateConversationList,
} from "../../conversation/history.ts";
import { Button } from "../ui/button.tsx";
import { setMenu } from "../../store/menu.ts";
import { Copy, LogIn, Plus, RotateCw } from "lucide-react";
import ConversationSegment from "./ConversationSegment.tsx";
import {
AlertDialog, AlertDialogAction, AlertDialogCancel,
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription, AlertDialogFooter,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle
AlertDialogTitle,
} from "../ui/alert-dialog.tsx";
import {shareConversation} from "../../conversation/sharing.ts";
import {Input} from "../ui/input.tsx";
import {login} from "../../conf.ts";
import {getSharedLink, shareConversation} from "../../conversation/sharing.ts";
import { Input } from "../ui/input.tsx";
import { login } from "../../conf.ts";

function SideBar() {
const { t } = useTranslation();
Expand Down Expand Up @@ -185,7 +199,7 @@ function SideBar() {
operateConversation?.target?.id || -1,
);
if (resp.status)
setShared(`${location.origin}/share/${resp.data}`);
setShared(getSharedLink(resp.data));
else
toast({
title: t("share.failed"),
Expand Down
114 changes: 114 additions & 0 deletions app/src/components/ui/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import * as React from "react"

import { cn } from "./lib/utils.ts"

const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
))
Table.displayName = "Table"

const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
))
TableHeader.displayName = "TableHeader"

const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
))
TableBody.displayName = "TableBody"

const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn("bg-primary font-medium text-primary-foreground", className)}
{...props}
/>
))
TableFooter.displayName = "TableFooter"

const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
)}
{...props}
/>
))
TableRow.displayName = "TableRow"

const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className
)}
{...props}
/>
))
TableHead.displayName = "TableHead"

const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props}
/>
))
TableCell.displayName = "TableCell"

const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
))
TableCaption.displayName = "TableCaption"

export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}
2 changes: 1 addition & 1 deletion app/src/conf.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from "axios";
import { Model } from "./conversation/types.ts";

export const version = "3.4.6";
export const version = "3.5.0";
export const deploy: boolean = true;
export let rest_api: string = "http://localhost:8094";
export let ws_api: string = "ws://localhost:8094";
Expand Down
48 changes: 48 additions & 0 deletions app/src/conversation/sharing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export type SharingForm = {
data: string;
};

export type SharingPreviewForm = {
name: string;
conversation_id: number;
hash: string;
time: string;
};

export type ViewData = {
name: string;
username: string;
Expand All @@ -20,6 +27,17 @@ export type ViewForm = {
data: ViewData | null;
};

export type ListSharingResponse = {
status: boolean;
message: string;
data?: SharingPreviewForm[];
};

export type DeleteSharingResponse = {
status: boolean;
message: string;
};

export async function shareConversation(
id: number,
refs: number[] = [-1],
Expand All @@ -44,3 +62,33 @@ export async function viewConversation(hash: string): Promise<ViewForm> {
};
}
}

export async function listSharing(): Promise<ListSharingResponse> {
try {
const resp = await axios.get("/conversation/share/list");
return resp.data as ListSharingResponse;
} catch (e) {
return {
status: false,
message: (e as Error).message,
};
}
}

export async function deleteSharing(
hash: string,
): Promise<DeleteSharingResponse> {
try {
const resp = await axios.get(`/conversation/share/delete?hash=${hash}`);
return resp.data as DeleteSharingResponse;
} catch (e) {
return {
status: false,
message: (e as Error).message,
};
}
}

export function getSharedLink(hash: string): string {
return `${location.origin}/share/${hash}`;
}
Loading

0 comments on commit 3bc8b89

Please sign in to comment.