Skip to content

Commit cd67eb9

Browse files
authored
Merge pull request #793 from cnoe-io/feat/ui-customization
feat(ui): rename Agentic Workflows to Skills and add icon customization
2 parents 09eab8a + 9a4b0f3 commit cd67eb9

File tree

13 files changed

+89
-41
lines changed

13 files changed

+89
-41
lines changed

ui/.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,17 @@ OIDC_CLIENT_SECRET=your-client-secret
6262

6363
# MongoDB database name (optional, default: caipe)
6464
# MONGODB_DB=caipe
65+
66+
# ============================================
67+
# UI Customization
68+
# ============================================
69+
# Application name displayed throughout the UI (default: CAIPE)
70+
# NEXT_PUBLIC_APP_NAME=My Platform
71+
72+
# Custom favicon URL for browser tab (default: /favicon.ico)
73+
# NEXT_PUBLIC_FAVICON_URL=https://example.com/my-favicon.png
74+
75+
# Enabled integration icons on login page orbit (comma-separated)
76+
# If not set, all icons are shown (backwards compatible)
77+
# Available icons: argocd, aws, github, gitlab, jira, splunk, confluence, webex, kubernetes, slack, backstage, command line, workflows, pagerduty, linux
78+
# NEXT_PUBLIC_ENABLED_INTEGRATION_ICONS=github,gitlab,slack,aws,kubernetes

ui/src/app/(app)/agent-builder/history/page.tsx renamed to ui/src/app/(app)/skills/history/page.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useRouter } from "next/navigation";
55
import { motion } from "framer-motion";
66
import { ArrowLeft, LayoutGrid } from "lucide-react";
77
import { Button } from "@/components/ui/button";
8-
import { WorkflowHistoryView } from "@/components/agent-builder/WorkflowHistoryView";
8+
import { WorkflowHistoryView } from "@/components/skills/WorkflowHistoryView";
99
import { AuthGuard } from "@/components/auth-guard";
1010
import type { WorkflowRun } from "@/types/workflow-run";
1111

@@ -21,7 +21,7 @@ export default function WorkflowHistoryPage() {
2121
const handleReRun = (run: WorkflowRun) => {
2222
// Navigate to agent builder with the workflow ID
2323
// The agent-builder page will need to handle the runWorkflow query param
24-
router.push(`/agent-builder?workflow=${run.workflow_id}&autorun=true`);
24+
router.push(`/skills?workflow=${run.workflow_id}&autorun=true`);
2525
};
2626

2727
return (
@@ -41,17 +41,17 @@ export default function WorkflowHistoryPage() {
4141
<Button
4242
variant="ghost"
4343
size="icon"
44-
onClick={() => router.push('/agent-builder')}
45-
title="Back to workflows"
44+
onClick={() => router.push('/skills')}
45+
title="Back to Skills"
4646
>
4747
<ArrowLeft className="h-5 w-5" />
4848
</Button>
4949

5050
{/* Title */}
5151
<div>
52-
<h1 className="text-2xl font-bold">Workflow Run History</h1>
52+
<h1 className="text-2xl font-bold">Skills Run History</h1>
5353
<p className="text-sm text-muted-foreground">
54-
View and manage all your workflow executions
54+
View and manage all your skill executions
5555
</p>
5656
</div>
5757
</div>

ui/src/app/api/agent-configs/route.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ async function getAgentConfigByIdFromMongoDB(
182182
// POST /api/agent-configs - Create a new agent config
183183
export const POST = withErrorHandler(async (request: NextRequest) => {
184184
if (STORAGE_TYPE !== "mongodb") {
185-
throw new ApiError("Agent Skills requires MongoDB to be configured", 503);
185+
throw new ApiError("Skills requires MongoDB to be configured", 503);
186186
}
187187

188188
return await withAuth(request, async (req, user) => {
@@ -230,7 +230,7 @@ export const POST = withErrorHandler(async (request: NextRequest) => {
230230
// GET /api/agent-configs - Retrieve all agent configs (system + user's own)
231231
export const GET = withErrorHandler(async (request: NextRequest) => {
232232
if (STORAGE_TYPE !== "mongodb") {
233-
throw new ApiError("Agent Skills requires MongoDB to be configured", 503);
233+
throw new ApiError("Skills requires MongoDB to be configured", 503);
234234
}
235235

236236
const { searchParams } = new URL(request.url);
@@ -268,7 +268,7 @@ export const GET = withErrorHandler(async (request: NextRequest) => {
268268
// PUT /api/agent-configs?id=<configId> - Update an existing agent config
269269
export const PUT = withErrorHandler(async (request: NextRequest) => {
270270
if (STORAGE_TYPE !== "mongodb") {
271-
throw new ApiError("Agent Skills requires MongoDB to be configured", 503);
271+
throw new ApiError("Skills requires MongoDB to be configured", 503);
272272
}
273273

274274
const { searchParams } = new URL(request.url);
@@ -324,7 +324,7 @@ export const PUT = withErrorHandler(async (request: NextRequest) => {
324324
// DELETE /api/agent-configs?id=<configId> - Delete an agent config
325325
export const DELETE = withErrorHandler(async (request: NextRequest) => {
326326
if (STORAGE_TYPE !== "mongodb") {
327-
throw new ApiError("Agent Skills requires MongoDB to be configured", 503);
327+
throw new ApiError("Skills requires MongoDB to be configured", 503);
328328
}
329329

330330
const { searchParams } = new URL(request.url);

ui/src/app/layout.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,17 @@ export async function generateMetadata(): Promise<Metadata> {
5050
const cfg = getServerConfig();
5151
const fullDescription = `${cfg.tagline} - ${cfg.description}`;
5252

53+
const faviconUrl = cfg.faviconUrl || "/favicon.ico";
54+
5355
return {
5456
title: `${cfg.appName} UI`,
5557
description: fullDescription,
5658
icons: {
5759
icon: [
58-
{ url: "/favicon.ico", sizes: "any" },
59-
{ url: "/icon.ico", sizes: "any" },
60+
{ url: faviconUrl, sizes: "any" },
6061
],
61-
shortcut: "/favicon.ico",
62-
apple: "/favicon.ico",
62+
shortcut: faviconUrl,
63+
apple: faviconUrl,
6364
},
6465
openGraph: {
6566
title: `${cfg.appName} UI`,

ui/src/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ export default function Home() {
77
const router = useRouter();
88

99
useEffect(() => {
10-
// Redirect to workflows (agent-builder) by default
11-
router.replace("/agent-builder");
10+
// Redirect to skills by default
11+
router.replace("/skills");
1212
}, [router]);
1313

1414
return null;

ui/src/components/agent-builder/AgentBuilderGallery.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,9 @@ export function AgentBuilderGallery({
378378
<Zap className="h-6 w-6 text-white" />
379379
</div>
380380
<div>
381-
<h1 className="text-2xl font-bold gradient-text">Agent Skills</h1>
381+
<h1 className="text-2xl font-bold gradient-text">Skills</h1>
382382
<p className="text-sm text-muted-foreground">
383-
Quick-start templates and multi-step agent workflows
383+
Quick-start templates and multi-step workflows
384384
</p>
385385
</div>
386386
</div>
@@ -392,7 +392,7 @@ export function AgentBuilderGallery({
392392
</Button>
393393
<Button size="sm" onClick={onCreateNew} className="gap-2 gradient-primary text-white">
394394
<Plus className="h-4 w-4" />
395-
Agent Skill Builder
395+
Skills Builder
396396
</Button>
397397
</div>
398398
</div>
@@ -428,7 +428,7 @@ export function AgentBuilderGallery({
428428
<Button
429429
variant="ghost"
430430
size="sm"
431-
onClick={() => router.push('/agent-builder/history')}
431+
onClick={() => router.push('/skills/history')}
432432
className="rounded-full text-xs gap-1"
433433
>
434434
<History className="h-3 w-3" />

ui/src/components/agent-builder/AgentBuilderRunner.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,7 @@ export function AgentBuilderRunner({
15471547
<Button
15481548
variant="ghost"
15491549
size="icon"
1550-
onClick={() => router.push('/agent-builder/history')}
1550+
onClick={() => router.push('/skills/history')}
15511551
title="View workflow history"
15521552
>
15531553
<ArrowLeft className="h-5 w-5" />

ui/src/components/gallery/IntegrationOrbit.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React from "react";
3+
import React, { useMemo } from "react";
44
import { motion } from "framer-motion";
55
import { getConfig, getLogoFilterClass } from "@/lib/config";
66

@@ -230,12 +230,31 @@ const integrations = [
230230
},
231231
];
232232

233-
// Outer orbit integrations (8 items)
234-
const outerOrbit = integrations.slice(0, 8);
235-
// Inner orbit integrations (7 items)
236-
const innerOrbit = integrations.slice(8, 15);
237-
238233
export function IntegrationOrbit() {
234+
// Filter integrations based on config
235+
const filteredIntegrations = useMemo(() => {
236+
const enabledIcons = getConfig('enabledIntegrationIcons');
237+
if (!enabledIcons) {
238+
// Show all icons if not configured
239+
return integrations;
240+
}
241+
// Filter to only show enabled icons (case-insensitive match)
242+
return integrations.filter((integration) =>
243+
enabledIcons.includes(integration.name.toLowerCase())
244+
);
245+
}, []);
246+
247+
// Split filtered integrations between outer and inner orbits
248+
const outerOrbit = useMemo(() => {
249+
const count = Math.min(8, Math.ceil(filteredIntegrations.length * 0.55));
250+
return filteredIntegrations.slice(0, count);
251+
}, [filteredIntegrations]);
252+
253+
const innerOrbit = useMemo(() => {
254+
const outerCount = Math.min(8, Math.ceil(filteredIntegrations.length * 0.55));
255+
return filteredIntegrations.slice(outerCount);
256+
}, [filteredIntegrations]);
257+
239258
return (
240259
<div className="relative w-[400px] h-[400px] flex items-center justify-center">
241260
{/* Subtle center glow only - blends with page background */}

ui/src/components/layout/AppHeader.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ export function AppHeader() {
9090
const getActiveTab = () => {
9191
if (pathname?.startsWith("/chat")) return "chat";
9292
if (pathname?.startsWith("/knowledge-bases")) return "knowledge";
93-
if (pathname?.startsWith("/agent-builder") || pathname?.startsWith("/use-cases")) return "agent-builder";
93+
if (pathname?.startsWith("/skills") || pathname?.startsWith("/use-cases")) return "skills";
9494
if (pathname?.startsWith("/admin")) return "admin";
95-
return "agent-builder"; // Default to Agent Skills (formerly use-cases)
95+
return "skills"; // Default to Skills
9696
};
9797

9898
const activeTab = getActiveTab();
@@ -119,20 +119,20 @@ export function AppHeader() {
119119
)}
120120
</Link>
121121

122-
{/* Navigation Pills - Agent Skills first for prominence */}
122+
{/* Navigation Pills - Skills first for prominence */}
123123
<div className="flex items-center bg-muted/50 rounded-full p-1">
124124
<Link
125-
href="/agent-builder"
125+
href="/skills"
126126
prefetch={true}
127127
className={cn(
128128
"flex items-center gap-1.5 px-4 py-1.5 rounded-full text-sm font-medium transition-all",
129-
activeTab === "agent-builder"
129+
activeTab === "skills"
130130
? "gradient-primary text-white shadow-sm"
131131
: "text-muted-foreground hover:text-foreground"
132132
)}
133133
>
134134
<Zap className="h-3.5 w-3.5" />
135-
Agent Skills
135+
Skills
136136
</Link>
137137
<Link
138138
href="/chat"

0 commit comments

Comments
 (0)