Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 662213c

Browse files
committed
fix: address settings consolidation
GitOrigin-RevId: daa412b4b7348a038fe57d4426821209ba0278e9
1 parent 1996a77 commit 662213c

3 files changed

Lines changed: 177 additions & 2 deletions

File tree

studio/web/src/app/dashboard/[workspace_slug]/layout.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ const navItems = [
2424
icon: CallInternal02Icon,
2525
},
2626
{ href: "/dashboard/integrations", label: "Integrations", icon: ConnectIcon },
27-
{ href: "/dashboard/settings", label: "Settings", icon: Settings01Icon },
2827
];
2928

3029
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
@@ -74,6 +73,22 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
7473
</Link>
7574
);
7675
})}
76+
<div className="hidden in-[.open-source]:block">
77+
<Link
78+
href={getNavHref("/settings")}
79+
className={`flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors ${
80+
pathname === getNavHref("/settings")
81+
? "bg-sidebar-accent text-sidebar-accent-foreground font-medium"
82+
: "text-sidebar-foreground hover:bg-sidebar-muted hover:text-sidebar-accent-foreground"
83+
}`}
84+
>
85+
<HugeiconsIcon
86+
icon={Settings01Icon}
87+
className={`size-4 ${pathname === getNavHref("/settings") ? "text-primary" : "text-sidebar-muted-foreground"}`}
88+
/>
89+
Settings
90+
</Link>
91+
</div>
7792
</div>
7893
</nav>
7994

studio/web/src/app/dashboard/[workspace_slug]/settings/page.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ import {
5959
} from "@/lib/api/client";
6060
import { toast } from "sonner";
6161

62+
63+
64+
65+
6266
// ── Provider metadata ──────────────────────────────────────────
6367

6468
const PROVIDER_HELP: Record<string, { models: string[]; docs: string; placeholder: string }> = {
@@ -1456,7 +1460,7 @@ function SettingsPageContent({ params }: { params: Promise<{ workspace_slug: str
14561460
<div ref={headerRef} className="flex items-center justify-between">
14571461
<PageHeader
14581462
icon={Settings01Icon}
1459-
title="Settings"
1463+
title="Platform Settings"
14601464
description="Configure your workspace, LLM providers, and voice pipeline"
14611465
/>
14621466
<div className="flex items-center gap-2">

studio/web/src/app/dashboard/[workspace_slug]/workspace/page.tsx

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"use client";
22

3+
import { Button } from "@/components/ui/button";
4+
import { Input } from "@/components/ui/input";
5+
import { ArrowRight01Icon, Building03Icon, Plus, PlusSignIcon } from "@hugeicons/core-free-icons";
6+
import { HugeiconsIcon } from "@hugeicons/react";
37
import { PageHeader } from "@/components/ui/page-header";
48

59
export default function WorkspaceSettingsPage() {
@@ -11,6 +15,158 @@ export default function WorkspaceSettingsPage() {
1115
icon={Building03Icon}
1216
/>
1317

18+
<div className="flex-1 max-w-4xl grid grid-cols-1 md:grid-cols-12 gap-8 items-start">
19+
20+
{/* Workspaces List */}
21+
<div className="md:col-span-7 space-y-6">
22+
<div className="bg-card/50 backdrop-blur-xl ring-1 ring-border/75 shadow-lg rounded-2xl overflow-hidden transition-all duration-300">
23+
<div className="p-6 border-b border-border/50 bg-muted/20">
24+
<h2 className="text-lg font-semibold tracking-tight text-foreground flex items-center gap-2">
25+
<HugeiconsIcon icon={Building03Icon} className="w-5 h-5 text-primary" />
26+
Active Workspaces
27+
</h2>
28+
<p className="text-sm text-muted-foreground mt-1">Select a workspace to switch contexts.</p>
29+
</div>
30+
<div className="p-6">
31+
{isLoading ? (
32+
<div className="flex items-center justify-center py-8 text-muted-foreground animate-pulse">
33+
Loading workspaces...
34+
</div>
35+
) : !organization ? (
36+
<div className="flex flex-col items-center justify-center py-12 text-center text-destructive">
37+
<div className="bg-destructive/10 p-4 rounded-full mb-4">
38+
<HugeiconsIcon icon={Building03Icon} className="w-6 h-6 text-destructive" />
39+
</div>
40+
<p className="font-medium">Failed to load organization.</p>
41+
<p className="text-sm opacity-80 mt-1">Please try refreshing the page.</p>
42+
</div>
43+
) : workspaces.length === 0 ? (
44+
<div className="flex flex-col items-center justify-center py-12 text-center text-muted-foreground">
45+
<div className="bg-muted p-4 rounded-full mb-4">
46+
<HugeiconsIcon icon={Building03Icon} className="w-6 h-6 opacity-50" />
47+
</div>
48+
<p>No workspaces found.</p>
49+
</div>
50+
) : (
51+
<ul className="space-y-3">
52+
{workspaces.map((ws) => {
53+
const isActive = activeWorkspaceId === ws.id;
54+
return (
55+
<li
56+
key={ws.id}
57+
className={`group flex items-center justify-between p-4 rounded-xl transition-all duration-300 ring-1 ${
58+
isActive
59+
? "bg-primary/5 ring-primary/20 shadow-sm ring-1"
60+
: "bg-background ring-border/75 hover:border-primary/30 hover:shadow-md hover:-translate-y-0.5 cursor-pointer"
61+
}`}
62+
onClick={() => !isActive && setActiveWorkspaceId(ws.id)}
63+
>
64+
<div className="flex items-center gap-4">
65+
<div>
66+
<div className="font-semibold text-foreground">{ws.name}</div>
67+
{isMultiOrg && (
68+
<div className="text-xs text-muted-foreground mt-0.5">
69+
{ws.org_name}
70+
</div>
71+
)}
72+
</div>
73+
</div>
74+
{isActive ? (
75+
<div className="px-3 py-1 bg-primary text-primary-foreground text-xs font-medium rounded-full shadow-sm">
76+
Active
77+
</div>
78+
) : (
79+
<Button variant="ghost" size="sm" className="opacity-0 group-hover:opacity-100 transition-opacity -mr-2">
80+
Switch <HugeiconsIcon icon={ArrowRight01Icon} className="w-4 h-4 ml-1" />
81+
</Button>
82+
)}
83+
</li>
84+
);
85+
})}
86+
</ul>
87+
)}
88+
</div>
89+
</div>
90+
</div>
91+
92+
{/* Create Workspace */}
93+
<div className="md:col-span-5 flex flex-col">
94+
<div className="flex-1 bg-linear-to-br from-card to-card/50 backdrop-blur-xl ring ring-border/75 shadow-lg rounded-2xl p-6 relative overflow-hidden">
95+
{/* Decorative background accent */}
96+
<div className="absolute top-0 right-0 -mr-8 -mt-8 w-32 h-32 bg-primary/10 rounded-full blur-3xl pointer-events-none"></div>
97+
98+
<div className="mb-6 relative z-10">
99+
<div className="inline-flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10 text-primary mb-4">
100+
<HugeiconsIcon icon={Plus} className="w-5 h-5" />
101+
</div>
102+
<h2 className="text-lg font-semibold tracking-tight text-foreground">Create New Workspace</h2>
103+
<p className="text-sm text-muted-foreground mt-1">
104+
Spin up a new environment for a different project, team, or client.
105+
</p>
106+
</div>
107+
108+
<form onSubmit={handleCreate} className="space-y-4 relative z-10">
109+
{isMultiOrg && (
110+
<div className="space-y-1.5">
111+
<label className="text-sm font-medium text-foreground">Organization</label>
112+
<div className="flex flex-wrap gap-2">
113+
{Array.from(new Set(workspaces.map(w => w.org_id))).map(orgId => {
114+
const orgName = workspaces.find(w => w.org_id === orgId)?.org_name || orgId;
115+
return (
116+
<button
117+
key={orgId}
118+
type="button"
119+
onClick={() => setSelectedOrgId(orgId)}
120+
className={`px-3 py-1 rounded-full text-xs border transition-colors ${
121+
(selectedOrgId || organization?.id) === orgId
122+
? "bg-primary text-primary-foreground border-primary"
123+
: "bg-transparent text-muted-foreground border-border hover:border-foreground/40"
124+
}`}
125+
>
126+
{orgName}
127+
</button>
128+
);
129+
})}
130+
</div>
131+
</div>
132+
)}
133+
<div className="space-y-2">
134+
<label className="text-sm font-medium text-foreground">Workspace Name</label>
135+
<Input
136+
value={newWorkspaceName}
137+
onChange={(e) => setNewWorkspaceName(e.target.value)}
138+
placeholder="e.g. Acme Corp Production"
139+
className="bg-background/50 border-border/50 focus-visible:ring-primary/50 transition-all h-11"
140+
disabled={isCreating}
141+
/>
142+
</div>
143+
<Button
144+
type="submit"
145+
className="w-full h-11 font-medium shadow-md transition-all hover:shadow-lg active:scale-[0.98]"
146+
disabled={isCreating || !newWorkspaceName.trim() || !organization}
147+
>
148+
{isCreating ? (
149+
<span className="flex items-center">
150+
<svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
151+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
152+
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
153+
</svg>
154+
Creating...
155+
</span>
156+
) : (
157+
<span className="flex items-center">
158+
<HugeiconsIcon icon={PlusSignIcon} className="w-5 h-5 mr-2" />
159+
Create Workspace
160+
</span>
161+
)}
162+
</Button>
163+
</form>
164+
</div>
165+
</div>
166+
167+
</div>
168+
{/* END-INTERNAL */}
169+
14170
<div className="hidden in-[.open-source]:block text-sm text-muted-foreground">
15171
Workspace management is not available in the open source version.
16172
</div>

0 commit comments

Comments
 (0)