Skip to content

Commit 6306f3c

Browse files
authored
chore(DATAGO-120962): replacing custom components with standard ones in project (and prompt) UI (#740)
* chore: replacing custom components with standard ones * chore: tidying * chore: tidying * chore: tidying * chore: responding to UX feedback * chore: switching to standard dialog to support linear progress display * chore: tidying * chore: making titles uniform * chore: tidying delete dialog * chore: tidying * chore: making dialog more consistent with prompt import * chore: improving badge for ux feedback * chore: tweaking for dark mode
1 parent 886c0f5 commit 6306f3c

27 files changed

+558
-576
lines changed

client/webui/frontend/src/lib/components/chat/SessionList.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,28 @@ import { useNavigate } from "react-router-dom";
44

55
import { Trash2, Check, X, Pencil, MessageCircle, FolderInput, MoreHorizontal, PanelsTopLeft, Loader2 } from "lucide-react";
66

7-
import { useChatContext, useConfigContext } from "@/lib/hooks";
87
import { api } from "@/lib/api";
9-
import { getErrorMessage } from "@/lib/utils/api";
10-
import { formatTimestamp } from "@/lib/utils/format";
11-
import { Button } from "@/lib/components/ui/button";
12-
import { Badge } from "@/lib/components/ui/badge";
13-
import { Spinner } from "@/lib/components/ui/spinner";
14-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/lib/components/ui/select";
15-
import { Tooltip, TooltipContent, TooltipTrigger } from "@/lib/components/ui/tooltip";
16-
import { MoveSessionDialog } from "@/lib/components/chat/MoveSessionDialog";
17-
import { SessionSearch } from "@/lib/components/chat/SessionSearch";
18-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/lib/components/ui/dropdown-menu";
8+
import { useChatContext, useConfigContext } from "@/lib/hooks";
199
import type { Project, Session } from "@/lib/types";
10+
import { formatTimestamp, getErrorMessage } from "@/lib/utils";
11+
import { MoveSessionDialog, ProjectBadge, SessionSearch } from "@/lib/components/chat";
12+
import {
13+
Button,
14+
DropdownMenu,
15+
DropdownMenuContent,
16+
DropdownMenuItem,
17+
DropdownMenuSeparator,
18+
DropdownMenuTrigger,
19+
Select,
20+
SelectContent,
21+
SelectItem,
22+
SelectTrigger,
23+
SelectValue,
24+
Spinner,
25+
Tooltip,
26+
TooltipContent,
27+
TooltipTrigger,
28+
} from "@/lib/components/ui";
2029

2130
interface PaginatedSessionsResponse {
2231
data: Session[];
@@ -310,7 +319,7 @@ export const SessionList: React.FC<SessionListProps> = ({ projects = [] }) => {
310319
<ul>
311320
{filteredSessions.map(session => (
312321
<li key={session.id} className="group my-2 pr-4">
313-
<div className={`flex items-center gap-2 rounded px-2 py-2 ${session.id === sessionId ? "bg-muted" : ""}`}>
322+
<div className={`flex items-center gap-2 rounded-sm px-2 py-2 ${session.id === sessionId ? "bg-muted dark:bg-muted/50" : ""}`}>
314323
{editingSessionId === session.id ? (
315324
<input
316325
ref={inputRef}
@@ -342,16 +351,7 @@ export const SessionList: React.FC<SessionListProps> = ({ projects = [] }) => {
342351
</div>
343352
<span className="text-muted-foreground truncate text-xs">{formatSessionDate(session.updatedTime)}</span>
344353
</div>
345-
{session.projectName && (
346-
<Tooltip>
347-
<TooltipTrigger asChild>
348-
<Badge variant="outline" className="bg-primary/10 border-primary/30 text-primary max-w-[120px] flex-shrink-0 justify-start px-2 py-0.5 text-xs font-semibold shadow-sm">
349-
<span className="block truncate">{session.projectName}</span>
350-
</Badge>
351-
</TooltipTrigger>
352-
<TooltipContent>{session.projectName}</TooltipContent>
353-
</Tooltip>
354-
)}
354+
{session.projectName && <ProjectBadge text={session.projectName} />}
355355
</div>
356356
</button>
357357
)}

client/webui/frontend/src/lib/components/chat/SessionSearch.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { useState, useCallback, useEffect } from "react";
22
import { Search, X } from "lucide-react";
3-
import { Input } from "@/lib/components/ui/input";
4-
import { Button } from "@/lib/components/ui/button";
5-
import { Badge } from "@/lib/components/ui/badge";
6-
import { useDebounce } from "@/lib/hooks/useDebounce";
7-
import type { Session } from "@/lib/types";
3+
84
import { api } from "@/lib/api";
5+
import { ProjectBadge } from "@/lib/components/chat";
6+
import { Button, Input } from "@/lib/components/ui";
7+
import { useDebounce } from "@/lib/hooks";
8+
import type { Session } from "@/lib/types";
99

1010
interface SessionSearchProps {
1111
onSessionSelect: (sessionId: string) => void;
@@ -98,11 +98,7 @@ export const SessionSearch = ({ onSessionSelect, projectId }: SessionSearchProps
9898
<button key={session.id} onClick={() => handleSessionClick(session.id)} className="hover:bg-accent hover:text-accent-foreground w-full rounded-sm px-3 py-2 text-left text-sm">
9999
<div className="mb-1 flex items-center justify-between gap-2">
100100
<div className="flex-1 truncate font-medium">{session.name || "Untitled Session"}</div>
101-
{session.projectName && (
102-
<Badge variant="outline" className="bg-primary/10 border-primary/30 text-primary flex-shrink-0 px-2 py-0.5 text-xs font-semibold shadow-sm">
103-
{session.projectName}
104-
</Badge>
105-
)}
101+
{session.projectName && <ProjectBadge text={session.projectName} />}
106102
</div>
107103
<div className="text-muted-foreground text-xs">{new Date(session.updatedTime).toLocaleDateString()}</div>
108104
</button>

client/webui/frontend/src/lib/components/chat/artifact/ArtifactBar.tsx

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import React, { useState, useEffect } from "react";
2-
import { Download, ChevronDown, Trash, Info, ChevronUp, CircleAlert } from "lucide-react";
2+
import { Download, ChevronDown, Trash, Info, ChevronUp, CircleAlert, Pencil } from "lucide-react";
33

4-
import { Button, Spinner, Badge } from "@/lib/components/ui";
5-
import { FileIcon } from "../file/FileIcon";
4+
import { Button, Spinner } from "@/lib/components/ui";
65
import { cn } from "@/lib/utils";
76

7+
import { FileIcon, ProjectBadge } from "../file";
8+
89
const ErrorState: React.FC<{ message: string }> = ({ message }) => (
910
<div className="w-full rounded-lg border border-[var(--color-error-w100)] bg-[var(--color-error-wMain-50)] p-3">
1011
<div className="text-sm text-[var(--color-error-wMain)]">Error: {message}</div>
@@ -26,6 +27,7 @@ export interface ArtifactBarProps {
2627
onDelete?: () => void;
2728
onInfo?: () => void;
2829
onExpand?: () => void;
30+
onEdit?: () => void;
2931
};
3032
// For creation progress
3133
bytesTransferred?: number;
@@ -211,11 +213,7 @@ export const ArtifactBar: React.FC<ArtifactBarProps> = ({
211213
{hasDescription ? displayDescription : filename.length > 50 ? `${filename.substring(0, 47)}...` : filename}
212214
</div>
213215
{/* Project badge */}
214-
{source === "project" && (
215-
<Badge variant="outline" className="bg-primary/10 border-primary/30 text-primary px-2 py-0.5 text-xs font-semibold shadow-sm">
216-
Project
217-
</Badge>
218-
)}
216+
{source === "project" && <ProjectBadge />}
219217
</div>
220218

221219
{/* Secondary line: Filename (if description shown) or status */}
@@ -298,6 +296,24 @@ export const ArtifactBar: React.FC<ArtifactBarProps> = ({
298296
</Button>
299297
)}
300298

299+
{status === "completed" && actions?.onEdit && !isDeleted && (
300+
<Button
301+
variant="ghost"
302+
size="icon"
303+
onClick={e => {
304+
e.stopPropagation();
305+
try {
306+
actions.onEdit?.();
307+
} catch (error) {
308+
console.error("Edit failed:", error);
309+
}
310+
}}
311+
tooltip="Edit Description"
312+
>
313+
<Pencil className="h-4 w-4" />
314+
</Button>
315+
)}
316+
301317
{status === "completed" && actions?.onDelete && !isDeleted && (
302318
<Button
303319
variant="ghost"

client/webui/frontend/src/lib/components/chat/file/ArtifactMessage.tsx

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { useProjectContext } from "@/lib/providers";
55
import type { FileAttachment } from "@/lib/types";
66
import { api } from "@/lib/api";
77
import { downloadFile, parseArtifactUri } from "@/lib/utils/download";
8-
import { formatBytes, formatRelativeTime } from "@/lib/utils/format";
8+
import { Spinner } from "@/lib/components/ui/spinner";
99

1010
import { MessageBanner } from "../../common";
1111
import { ContentRenderer } from "../preview/ContentRenderer";
1212
import { getFileContent, getRenderType } from "../preview/previewUtils";
1313
import { ArtifactBar } from "../artifact/ArtifactBar";
1414
import { ArtifactTransitionOverlay } from "../artifact/ArtifactTransitionOverlay";
15-
import { Spinner } from "../../ui";
15+
import { FileDetails } from "./FileDetails";
1616

1717
type ArtifactMessageProps = (
1818
| {
@@ -417,32 +417,7 @@ export const ArtifactMessage: React.FC<ArtifactMessageProps> = props => {
417417
const infoContent = useMemo(() => {
418418
if (!isInfoExpanded || !artifact) return null;
419419

420-
return (
421-
<div className="space-y-2 text-sm">
422-
{artifact.description && (
423-
<div>
424-
<span className="text-secondary-foreground">Description:</span>
425-
<div className="mt-1">{artifact.description}</div>
426-
</div>
427-
)}
428-
<div className="grid grid-cols-2 gap-2">
429-
<div>
430-
<span className="text-secondary-foreground">Size:</span>
431-
<div>{formatBytes(artifact.size)}</div>
432-
</div>
433-
<div>
434-
<span className="text-secondary-foreground">Modified:</span>
435-
<div>{formatRelativeTime(artifact.last_modified)}</div>
436-
</div>
437-
</div>
438-
{artifact.mime_type && (
439-
<div>
440-
<span className="text-secondary-foreground">Type:</span>
441-
<div>{artifact.mime_type}</div>
442-
</div>
443-
)}
444-
</div>
445-
);
420+
return <FileDetails description={artifact.description ?? undefined} size={artifact.size} lastModified={artifact.last_modified} mimeType={artifact.mime_type} />;
446421
}, [isInfoExpanded, artifact]);
447422

448423
// Determine what content to show in expanded area - can show both info and content
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from "react";
2+
3+
import { formatBytes, formatRelativeTime } from "@/lib/utils/format";
4+
5+
interface FileDetailsProps {
6+
description?: string;
7+
size: number;
8+
lastModified: string;
9+
mimeType?: string;
10+
}
11+
12+
export const FileDetails: React.FC<FileDetailsProps> = ({ description, size, lastModified, mimeType }) => {
13+
return (
14+
<div className="space-y-2 text-sm">
15+
{description && (
16+
<div>
17+
<span className="text-secondary-foreground">Description:</span>
18+
<div className="mt-1">{description}</div>
19+
</div>
20+
)}
21+
<div className="grid grid-cols-2 gap-2">
22+
<div>
23+
<span className="text-secondary-foreground">Size:</span>
24+
<div>{formatBytes(size)}</div>
25+
</div>
26+
<div>
27+
<span className="text-secondary-foreground">Modified:</span>
28+
<div>{formatRelativeTime(lastModified)}</div>
29+
</div>
30+
</div>
31+
{mimeType && (
32+
<div>
33+
<span className="text-secondary-foreground">Type:</span>
34+
<div>{mimeType}</div>
35+
</div>
36+
)}
37+
</div>
38+
);
39+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { File } from "lucide-react";
2+
3+
export const FileLabel = ({ fileName, fileSize }: { fileName: string; fileSize: number }) => {
4+
return (
5+
<div className="flex items-center gap-3">
6+
<File className="text-muted-foreground size-5 shrink-0" />
7+
<div className="overflow-hidden">
8+
<div className="truncate" title={fileName}>
9+
{fileName}
10+
</div>
11+
<div className="text-muted-foreground text-xs">{(fileSize / 1024).toFixed(1)} KB</div>
12+
</div>
13+
</div>
14+
);
15+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Badge, Tooltip, TooltipContent, TooltipTrigger } from "@/lib";
2+
3+
export const ProjectBadge = ({ text = "Project", className = "" }: { text?: string; className?: string }) => {
4+
return (
5+
<Tooltip>
6+
<TooltipTrigger asChild>
7+
<Badge variant="default" className={`max-w-[120px] ${className}`}>
8+
<span className="block truncate font-semibold">{text}</span>
9+
</Badge>
10+
</TooltipTrigger>
11+
<TooltipContent>{text}</TooltipContent>
12+
</Tooltip>
13+
);
14+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export * from "./ArtifactMessage";
22
export * from "./FileBadge";
3+
export * from "./FileDetails";
34
export * from "./FileIcon";
45
export * from "./FileMessage";
56
export * from "./fileUtils";
7+
export * from "./ProjectBadge";

client/webui/frontend/src/lib/components/chat/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export { AudioRecorder } from "./AudioRecorder";
22
export { ChatInputArea } from "./ChatInputArea";
33
export { ChatMessage } from "./ChatMessage";
4+
export { ChatSessionDeleteDialog } from "./ChatSessionDeleteDialog";
5+
export { ChatSessionDialog } from "./ChatSessionDialog";
46
export { ChatSessions } from "./ChatSessions";
57
export { ChatSidePanel } from "./ChatSidePanel";
68
export { LoadingMessageRow } from "./LoadingMessageRow";
@@ -9,4 +11,5 @@ export { MoveSessionDialog } from "./MoveSessionDialog";
911
export { VariableDialog } from "./VariableDialog";
1012
export { SessionSearch } from "./SessionSearch";
1113
export { MessageHoverButtons } from "./MessageHoverButtons";
14+
export * from "./file";
1215
export * from "./selection";

0 commit comments

Comments
 (0)