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
2 changes: 1 addition & 1 deletion databricks-builder-app/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
Expand Down
Binary file added databricks-builder-app/client/public/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion databricks-builder-app/client/src/components/FunLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function FunLoader({ todos = [], className }: FunLoaderProps) {
const currentTodo = todos.find((t) => t.status === 'in_progress');

return (
<div className={cn('flex flex-col items-center gap-3', className)}>
<div className={cn('flex flex-col items-start gap-3', className)}>
{/* Main loader with rotating message */}
<div className="flex items-center gap-3 rounded-xl bg-[var(--color-bg-secondary)] border border-[var(--color-border)]/50 px-4 py-3 shadow-sm">
<Loader2 className="h-5 w-5 animate-spin text-[var(--color-accent-primary)]" />
Expand Down
10 changes: 10 additions & 0 deletions databricks-builder-app/client/src/contexts/ProjectsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import {
createProject as apiCreateProject,
deleteProject as apiDeleteProject,
renameProject as apiRenameProject,
fetchProjects,
} from "@/lib/api";
import type { Project } from "@/lib/types";
Expand All @@ -20,6 +21,7 @@ interface ProjectsContextType {
refresh: () => Promise<void>;
createProject: (name: string) => Promise<Project>;
deleteProject: (projectId: string) => Promise<void>;
renameProject: (projectId: string, name: string) => Promise<void>;
}

const ProjectsContext = createContext<ProjectsContextType | null>(null);
Expand Down Expand Up @@ -53,6 +55,13 @@ export function ProjectsProvider({ children }: { children: ReactNode }) {
setProjects((prev) => prev.filter((p) => p.id !== projectId));
}, []);

const renameProject = useCallback(async (projectId: string, name: string): Promise<void> => {
await apiRenameProject(projectId, name);
setProjects((prev) =>
prev.map((p) => (p.id === projectId ? { ...p, name } : p))
);
}, []);

useEffect(() => {
refresh();
}, [refresh]);
Expand All @@ -64,6 +73,7 @@ export function ProjectsProvider({ children }: { children: ReactNode }) {
refresh,
createProject,
deleteProject,
renameProject,
};

return (
Expand Down
4 changes: 4 additions & 0 deletions databricks-builder-app/client/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export async function createProject(name: string): Promise<Project> {
return request<Project>('/projects', { method: 'POST', body: { name } });
}

export async function renameProject(projectId: string, name: string): Promise<void> {
return request(`/projects/${projectId}`, { method: 'PATCH', body: { name } });
}

export async function deleteProject(projectId: string): Promise<void> {
return request(`/projects/${projectId}`, { method: 'DELETE' });
}
Expand Down
244 changes: 28 additions & 216 deletions databricks-builder-app/client/src/pages/DocPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import {
Home,
Database,
Expand All @@ -13,8 +12,9 @@ import {
Terminal,
Sparkles
} from 'lucide-react';
import { MainLayout } from '@/components/layout/MainLayout';

type DocSection = 'overview' | 'tools-skills' | 'app';
type DocSection = 'overview' | 'app';

interface NavItem {
id: DocSection;
Expand All @@ -24,7 +24,6 @@ interface NavItem {

const navItems: NavItem[] = [
{ id: 'overview', label: 'Overview', icon: <Home className="h-4 w-4" /> },
{ id: 'tools-skills', label: 'Tools & Skills', icon: <Database className="h-4 w-4" /> },
{ id: 'app', label: 'MCP App', icon: <Sparkles className="h-4 w-4" /> },
];

Expand Down Expand Up @@ -356,162 +355,6 @@ function OverviewSection() {
);
}

type CoverageStatus = 'done' | 'in-progress' | 'not-started' | 'tbd';

interface CoverageItem {
product: string;
skills: CoverageStatus;
mcpFunctions: CoverageStatus;
tested: CoverageStatus;
functionalInApp?: CoverageStatus;
owner?: string;
testLink?: string;
date?: string;
comments?: string;
}

interface CoverageSection {
title: string;
items: CoverageItem[];
}

const coverageSections: CoverageSection[] = [
{
title: 'Ingestion / ETL',
items: [
{ product: 'Lakeflow Spark Declarative Pipelines', skills: 'done', mcpFunctions: 'done', tested: 'done', functionalInApp: 'in-progress', owner: 'Cal Reynolds', date: 'Jan 13', comments: 'Tested with State Street example. Successful locally in deploying pipelines of python, sql and modifiable varieties (SCP, Iceberg, Clustering). \n\nNeeds claude-agent-sdk bug to be fixed to work with app' },
{ product: 'Lakeflow Jobs', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
{ product: 'Synthetic Data Generation', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '' },
{ product: 'PDF / Unstructured Data Generation', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: 'Quentin', comments: 'Generate realistic PDFs (invoices, contracts, reports) and unstructured data files. Uses LLM for content generation.' },
],
},
{
title: 'ML / AI',
items: [
{ product: 'Agent Bricks - Knowledge Assistant', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '', comments: 'Knowledge Assistant tile management' },
{ product: 'Agent Bricks - Supervisor Agent', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '', comments: 'Supervisor Agent tile management' },
{ product: 'Agent Bricks - Genie', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '', comments: 'Genie tile management' },
{ product: 'Model Serving', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
{ product: 'Classic ML and MLFlow', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
],
},
{
title: 'AI/BI - SQL',
items: [
{ product: 'DBSQL', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '' },
{ product: 'Unity Catalog', skills: 'done', mcpFunctions: 'done', tested: 'done', owner: '' },
{ product: 'AI/BI Dashboards', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
],
},
{
title: 'Other',
items: [
{ product: 'Databricks Asset Bundles', skills: 'done', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
{ product: 'Notebook Creation', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
{ product: 'Lakebase', skills: 'not-started', mcpFunctions: 'not-started', tested: 'not-started', owner: '' },
{ product: 'Apps', skills: 'tbd', mcpFunctions: 'tbd', tested: 'tbd', owner: 'Ivan' },
],
},
];

function StatusBadge({ status }: { status: CoverageStatus }) {
const config = {
'done': { label: 'Initial Coverage', bg: 'bg-green-500/20', text: 'text-green-400', dot: 'bg-green-400' },
'in-progress': { label: 'In Progress', bg: 'bg-yellow-500/20', text: 'text-yellow-400', dot: 'bg-yellow-400' },
'not-started': { label: 'Not Started', bg: 'bg-[var(--color-text-muted)]/20', text: 'text-[var(--color-text-muted)]', dot: 'bg-[var(--color-text-muted)]' },
'tbd': { label: 'TBD', bg: 'bg-purple-500/20', text: 'text-purple-400', dot: 'bg-purple-400' },
};
const { label, bg, text, dot } = config[status];

return (
<span className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-full text-xs ${bg} ${text}`}>
<span className={`w-1.5 h-1.5 rounded-full ${dot}`} />
{label}
</span>
);
}

function ToolsSkillsSection() {
return (
<div className="space-y-8">
<div>
<h1 className="text-3xl font-bold text-[var(--color-text-heading)]">
Tools & Skills Coverage
</h1>
<p className="mt-2 text-lg text-[var(--color-text-muted)]">
Current status of Databricks product coverage in the AI Dev Kit
</p>
</div>

{/* Coverage Table */}
<div className="rounded-xl border border-[var(--color-border)] overflow-hidden">
<table className="w-full">
<thead>
<tr className="bg-[var(--color-bg-secondary)] border-b border-[var(--color-border)]">
<th className="text-left px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Product</th>
<th className="text-center px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Skills</th>
<th className="text-center px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">MCP Functions</th>
<th className="text-center px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Tested on Local Terminal</th>
<th className="text-center px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Functional in App</th>
<th className="text-left px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Owner</th>
<th className="text-left px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Date</th>
<th className="text-left px-6 py-4 text-sm font-semibold text-[var(--color-text-heading)]">Comments</th>
</tr>
</thead>
<tbody>
{coverageSections.map((section) => (
<React.Fragment key={section.title}>
{/* Section Header */}
<tr className="bg-[var(--color-accent-primary)]/10 border-b border-[var(--color-border)]">
<td colSpan={8} className="px-6 py-3 text-sm font-semibold text-[var(--color-accent-primary)]">
{section.title}
</td>
</tr>
{/* Section Items */}
{section.items.map((item, idx) => (
<tr
key={item.product}
className={`border-b border-[var(--color-border)] last:border-b-0 ${idx % 2 === 0 ? 'bg-[var(--color-background)]' : 'bg-[var(--color-bg-secondary)]/50'}`}
>
<td className="px-6 py-4 text-sm text-[var(--color-text-primary)]">{item.product}</td>
<td className="px-6 py-4 text-center"><StatusBadge status={item.skills} /></td>
<td className="px-6 py-4 text-center"><StatusBadge status={item.mcpFunctions} /></td>
<td className="px-6 py-4 text-center"><StatusBadge status={item.tested} /></td>
<td className="px-6 py-4 text-center">{item.functionalInApp ? <StatusBadge status={item.functionalInApp} /> : '-'}</td>
<td className="px-6 py-4 text-sm text-[var(--color-text-muted)]">{item.owner || '-'}</td>
<td className="px-6 py-4 text-sm text-[var(--color-text-muted)]">{item.date || '-'}</td>
<td className="px-6 py-4 text-sm text-[var(--color-text-muted)] whitespace-pre-line max-w-md">{item.comments || '-'}</td>
</tr>
))}
</React.Fragment>
))}
</tbody>
</table>
</div>

{/* Legend */}
<div className="flex items-center gap-6 text-sm text-[var(--color-text-muted)]">
<div className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-green-400" />
<span>Initial Coverage</span>
</div>
<div className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-yellow-400" />
<span>In Progress</span>
</div>
<div className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-[var(--color-text-muted)]" />
<span>Not Started</span>
</div>
<div className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-purple-400" />
<span>TBD</span>
</div>
</div>
</div>
);
}

function AppSection() {
return (
<div className="space-y-8">
Expand Down Expand Up @@ -840,72 +683,41 @@ export default function DocPage() {
switch (activeSection) {
case 'overview':
return <OverviewSection />;
case 'tools-skills':
return <ToolsSkillsSection />;
case 'app':
return <AppSection />;
default:
return <OverviewSection />;
}
};

return (
<div className="h-screen bg-[var(--color-background)] flex flex-col overflow-hidden">
{/* Top Bar */}
<header className="fixed top-0 left-0 right-0 z-50 h-[var(--header-height)] border-b border-[var(--color-border)] bg-[var(--color-bg-secondary)]">
<div className="h-full px-4 flex items-center justify-between">
<div className="flex items-center gap-3">
<Link to="/" className="flex items-center gap-2 hover:opacity-80 transition-opacity">
<div className="h-8 w-8 rounded-lg bg-[var(--color-accent-primary)] flex items-center justify-center">
<Database className="h-4 w-4 text-white" />
</div>
<span className="font-semibold text-[var(--color-text-heading)]">AI Dev Kit</span>
</Link>
<span className="text-[var(--color-text-muted)]">/</span>
<span className="text-[var(--color-text-secondary)]">Documentation</span>
</div>
<Link
to="/"
className="flex items-center gap-2 text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-heading)] transition-colors"
const docSidebar = (
<nav className="w-64 h-full border-r border-[var(--color-border)] bg-[var(--color-bg-secondary)] overflow-y-auto">
<div className="p-4 space-y-1">
{navItems.map((item) => (
<button
key={item.id}
onClick={() => setActiveSection(item.id)}
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-colors ${
activeSection === item.id
? 'bg-[var(--color-accent-primary)]/10 text-[var(--color-accent-primary)]'
: 'text-[var(--color-text-muted)] hover:bg-[var(--color-background)] hover:text-[var(--color-text-heading)]'
}`}
>
<Home className="h-4 w-4" />
Back to Projects
</Link>
</div>
</header>

{/* Spacer for fixed header */}
<div className="flex-shrink-0 h-[var(--header-height)]" />

{/* Main Layout */}
<div className="flex-1 flex overflow-hidden">
{/* Left Navigation */}
<nav className="w-64 flex-shrink-0 border-r border-[var(--color-border)] bg-[var(--color-bg-secondary)] overflow-y-auto">
<div className="p-4 space-y-1">
{navItems.map((item) => (
<button
key={item.id}
onClick={() => setActiveSection(item.id)}
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-colors ${
activeSection === item.id
? 'bg-[var(--color-accent-primary)]/10 text-[var(--color-accent-primary)]'
: 'text-[var(--color-text-muted)] hover:bg-[var(--color-background)] hover:text-[var(--color-text-heading)]'
}`}
>
{item.icon}
{item.label}
</button>
))}
</div>
</nav>
{item.icon}
{item.label}
</button>
))}
</div>
</nav>
);

{/* Content Area */}
<main className="flex-1 overflow-y-auto">
<div className="max-w-7xl mx-auto px-8 py-8">
{renderSection()}
</div>
</main>
return (
<MainLayout sidebar={docSidebar}>
<div className="flex-1 overflow-y-auto">
<div className="max-w-7xl mx-auto px-8 py-8">
{renderSection()}
</div>
</div>
</div>
</MainLayout>
);
}
Loading