feat: Implement a new dashboard layout with sidebar, introduce project and data source management, and add various UI components.

This commit is contained in:
2026-02-03 15:11:53 +00:00
parent a795e92ef3
commit 7e3854d7d6
29 changed files with 2460 additions and 645 deletions

75
convex/dataSources.ts Normal file
View File

@@ -0,0 +1,75 @@
import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
import { getAuthUserId } from "@convex-dev/auth/server";
export const getProjectDataSources = query({
args: { projectId: v.id("projects") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (!userId) return [];
// Verify project ownership
const project = await ctx.db.get(args.projectId);
if (!project || project.userId !== userId) return [];
return await ctx.db
.query("dataSources")
.filter((q) => q.eq(q.field("projectId"), args.projectId))
.collect();
},
});
export const addDataSource = mutation({
args: {
projectId: v.optional(v.id("projects")), // Optional, if not provided, use default
url: v.string(),
name: v.string(),
type: v.literal("website"),
},
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (!userId) throw new Error("Unauthorized");
let projectId = args.projectId;
// Use default project if not provided
if (!projectId) {
const defaultProject = await ctx.db
.query("projects")
.filter((q) => q.and(q.eq(q.field("userId"), userId), q.eq(q.field("isDefault"), true)))
.first();
if (!defaultProject) {
// Create a default project if none exists (First onboarding)
projectId = await ctx.db.insert("projects", {
userId,
name: "My Project",
isDefault: true,
dorkingConfig: { selectedSourceIds: [] },
});
} else {
projectId = defaultProject._id;
}
}
const sourceId = await ctx.db.insert("dataSources", {
projectId: projectId!, // Assert exists
type: args.type,
url: args.url,
name: args.name,
analysisStatus: "pending",
// analysisResults not set initially
});
// Auto-select this source in the project config
const project = await ctx.db.get(projectId!);
if (project) {
const currentSelected = project.dorkingConfig.selectedSourceIds;
await ctx.db.patch(projectId!, {
dorkingConfig: { selectedSourceIds: [...currentSelected, sourceId] }
});
}
return sourceId;
},
});