Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions typescript-sdk/apps/dojo/scripts/run-dojo-everything.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const dojo = {
LLAMA_INDEX_URL: 'http://localhost:8007',
MASTRA_URL: 'http://localhost:8008',
PYDANTIC_AI_URL: 'http://localhost:8009',
NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE: 'cpkdojo.local___CopilotKit Feature Viewer',
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Menu, X } from "lucide-react";
import { Button } from "@/components/ui/button";

import { useURLParams } from "@/contexts/url-params-context";
import { getTitleForCurrentDomain } from "@/utils/domain-config";

export function MainLayout({ children }: { children: React.ReactNode }) {
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
Expand Down Expand Up @@ -52,7 +53,7 @@ export function MainLayout({ children }: { children: React.ReactNode }) {
>
{isMobileSidebarOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
</Button>
<h1 className="text-sm font-medium text-center flex-1">AG-UI Dojo</h1>
<h1 className="text-sm font-medium text-center flex-1">{getTitleForCurrentDomain() || "AG-UI Dojo"}</h1>
<div className="w-9" /> {/* Spacer for centering */}
</div>
</div>
Expand Down Expand Up @@ -100,8 +101,8 @@ function MaybeSidebar({ isMobile, isMobileSidebarOpen, onMobileClose }: MaybeSid

return (
<div className={`
${isMobile
? 'absolute left-0 top-0 z-50 h-full w-80 transform transition-transform duration-300 ease-in-out'
${isMobile
? 'absolute left-0 top-0 z-50 h-full w-80 transform transition-transform duration-300 ease-in-out'
: 'relative'
}
`}>
Expand Down
15 changes: 10 additions & 5 deletions typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { menuIntegrations } from "@/menu";
import { Feature } from "@/types/integration";
import { useURLParams } from "@/contexts/url-params-context";
import { View } from "@/types/interface";
import { getTitleForCurrentDomain } from "@/utils/domain-config";

interface SidebarProps {
isMobile?: boolean;
Expand All @@ -28,7 +29,7 @@ interface SidebarProps {
export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
const router = useRouter();
const pathname = usePathname();
const { view, pickerDisabled, setView } = useURLParams();
const { view, frameworkPickerHidden, viewPickerHidden, featurePickerHidden, setView} = useURLParams();
const [isDarkTheme, setIsDarkTheme] = useState<boolean>(false);

// Extract the current integration ID from the pathname
Expand Down Expand Up @@ -98,15 +99,15 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
}, []);

return (
<div className={`flex flex-col h-full bg-background border-r
<div className={`flex flex-col h-full bg-background border-r
${isMobile ? 'w-80 shadow-xl' : 'w-74 min-w-[296px] flex-shrink-0'}
`}>
{/* Sidebar Header */}
<div className="p-4 border-b bg-background">
<div className="flex items-center justify-between ml-1">
<div className="flex items-start flex-col">
<h1 className={`text-lg font-light ${isDarkTheme ? "text-white" : "text-gray-900"}`}>
AG-UI Interactive Dojo
{getTitleForCurrentDomain() || "AG-UI Interactive Dojo"}
</h1>
</div>

Expand All @@ -115,9 +116,10 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
</div>

{/* Controls Section */}
{(!frameworkPickerHidden|| !viewPickerHidden) && (
<div className="p-4 border-b bg-background">
{/* Integration picker */}
{!pickerDisabled && (
{!frameworkPickerHidden&& (
<div className="mb-1">
<label className="block text-sm font-medium text-muted-foreground mb-2">Integrations</label>
<DropdownMenu>
Expand All @@ -143,6 +145,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
)}

{/* Preview/Code Tabs */}
{!viewPickerHidden &&
<div className="mb-1">
<label className="block text-sm font-medium text-muted-foreground mb-2">View</label>
<Tabs
Expand Down Expand Up @@ -175,11 +178,13 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
</TabsList>
</Tabs>
</div>
}
</div>
)}

{/* Demo List */}
<div className="flex-1 overflow-auto">
{currentIntegration ? (
{(currentIntegration && !featurePickerHidden) ? (
<DemoList
demos={filteredDemos}
selectedDemo={currentDemoId}
Expand Down
77 changes: 58 additions & 19 deletions typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import { View } from "@/types/interface";
interface URLParamsState {
view: View;
sidebarHidden: boolean;
pickerDisabled: boolean;
frameworkPickerHidden: boolean;
viewPickerHidden: boolean;
featurePickerHidden: boolean;
file?: string;
}

interface URLParamsContextType extends URLParamsState {
setView: (view: View) => void;
setSidebarHidden: (disabled: boolean) => void;
setPickerDisabled: (disabled: boolean) => void;
setFrameworkPickerHidden: (disabled: boolean) => void;
setViewPickerHidden: (disabled: boolean) => void;
setFeaturePickerHidden: (disabled: boolean) => void;
setCodeFile: (fileName: string) => void;
}

Expand All @@ -32,14 +36,16 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
// Initialize state from URL params
const [state, setState] = useState<URLParamsState>(() => ({
view: (searchParams.get("view") as View) || "preview",
sidebarHidden: searchParams.get("sidebar") === "disabled",
pickerDisabled: searchParams.get("picker") === "false",
sidebarHidden: searchParams.get("sidebar") === "false",
frameworkPickerHidden: searchParams.get("frameworkPicker") === "false",
viewPickerHidden: searchParams.get("viewPicker") === "false",
featurePickerHidden: searchParams.get("featurePicker") === "false",
}));

// Update URL when state changes
const updateURL = (newState: Partial<URLParamsState>) => {
const params = new URLSearchParams(searchParams.toString());

// Update view param
if (newState.view !== undefined) {
if (newState.view === "preview") {
Expand All @@ -48,22 +54,39 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
params.set("view", newState.view);
}
}

// Update sidebar param
if (newState.sidebarHidden !== undefined) {
if (newState.sidebarHidden) {
params.set("sidebar", "disabled");
params.set("sidebar", "false");
} else {
params.delete("sidebar");
}
}
// Update picker param
if (newState.pickerDisabled !== undefined) {
if (newState.pickerDisabled) {
params.set("picker", "false");

// Update frameworkPicker param
if (newState.frameworkPickerHidden !== undefined) {
if (newState.frameworkPickerHidden) {
params.set("frameworkPicker", "false");
} else {
params.delete("picker");
params.delete("frameworkPicker");
}
}

// Update viewPicker param
if (newState.viewPickerHidden !== undefined) {
if (newState.viewPickerHidden) {
params.set("viewPicker", "false");
} else {
params.delete("viewPicker");
}
}
// Update featurePicker param
if (newState.featurePickerHidden !== undefined) {
if (newState.featurePickerHidden) {
params.set("featurePicker", "false");
} else {
params.delete("features");
}
}

Expand All @@ -76,9 +99,11 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
const newState: URLParamsState = {
view: (searchParams.get("view") as View) || "preview",
sidebarHidden: searchParams.get("sidebar") === "disabled",
pickerDisabled: searchParams.get("picker") === "false",
frameworkPickerHidden: searchParams.get("frameworkPicker") === "false",
viewPickerHidden: searchParams.get("viewPicker") === "false",
featurePickerHidden: searchParams.get("featurePicker") === "false",
};

setState(newState);
}, [searchParams]);

Expand All @@ -95,10 +120,22 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
updateURL({ sidebarHidden });
};

const setPickerDisabled = (pickerDisabled: boolean) => {
const newState = { ...state, pickerDisabled };
const setFrameworkPickerHidden = (frameworkPickerHidden: boolean) => {
const newState = { ...state, frameworkPickerHidden };
setState(newState);
updateURL({ frameworkPickerHidden });
};

const setViewPickerHidden = (viewPickerHidden: boolean) => {
const newState = { ...state, viewPickerHidden };
setState(newState);
updateURL({ viewPickerHidden });
};

const setFeaturePickerHidden = (featurePickerHidden: boolean) => {
const newState = { ...state, featurePickerHidden };
setState(newState);
updateURL({ pickerDisabled });
updateURL({ featurePickerHidden });
};

const setCodeFile = (fileName: string) => {
Expand All @@ -111,7 +148,9 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
...state,
setView,
setSidebarHidden,
setPickerDisabled,
setFrameworkPickerHidden,
setViewPickerHidden,
setFeaturePickerHidden,
setCodeFile,
};

Expand Down
30 changes: 20 additions & 10 deletions typescript-sdk/apps/dojo/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ type envVars = {
llamaIndexUrl: string;
crewAiUrl: string;
pydanticAIUrl: string;
customDomainTitle: Record<string, string>;
}

export default function getEnvVars(): envVars {
return {
serverStarterUrl: process.env.SERVER_STARTER_URL || 'http://localhost:8000',
serverStarterAllFeaturesUrl: process.env.SERVER_STARTER_ALL_FEATURES_URL || 'http://localhost:8000',
mastraUrl: process.env.MASTRA_URL || 'http://localhost:4111',
langgraphUrl: process.env.LANGGRAPH_URL || 'http://localhost:2024',
langgraphFastApiUrl: process.env.LANGGRAPH_FAST_API_URL || 'http://localhost:8000',
agnoUrl: process.env.AGNO_URL || 'http://localhost:9001',
llamaIndexUrl: process.env.LLAMA_INDEX_URL || 'http://localhost:9000',
crewAiUrl: process.env.CREW_AI_URL || 'http://localhost:9002',
pydanticAIUrl: process.env.PYDANTIC_AI_URL || 'http://localhost:9000',
const customDomainTitle: Record<string, string> = {};
if (process.env.NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE) {
const [domain, title] = process.env.NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE.split('___');
if (domain && title) {
customDomainTitle[domain] = title;
}
}

return {
serverStarterUrl: process.env.SERVER_STARTER_URL || 'http://localhost:8000',
serverStarterAllFeaturesUrl: process.env.SERVER_STARTER_ALL_FEATURES_URL || 'http://localhost:8000',
mastraUrl: process.env.MASTRA_URL || 'http://localhost:4111',
langgraphUrl: process.env.LANGGRAPH_URL || 'http://localhost:2024',
langgraphFastApiUrl: process.env.LANGGRAPH_FAST_API_URL || 'http://localhost:8000',
agnoUrl: process.env.AGNO_URL || 'http://localhost:9001',
llamaIndexUrl: process.env.LLAMA_INDEX_URL || 'http://localhost:9000',
crewAiUrl: process.env.CREW_AI_URL || 'http://localhost:9002',
pydanticAIUrl: process.env.PYDANTIC_AI_URL || 'http://localhost:9000',
customDomainTitle: customDomainTitle,
}
}
14 changes: 14 additions & 0 deletions typescript-sdk/apps/dojo/src/utils/domain-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import getEnvVars from "@/env";


export function getTitleForCurrentDomain(): string | undefined {
const envVars = getEnvVars();

// Check if we're in the browser
if (typeof window == "undefined") {
return undefined;
}

const host = window.location.hostname;
return envVars.customDomainTitle[host] || undefined;
}
Loading