From 194396940e285e6aef6e84e514739a790e9ff109 Mon Sep 17 00:00:00 2001 From: averel10 Date: Sun, 8 Mar 2026 09:47:12 +0100 Subject: [PATCH] removed utterance system atm --- .../2026-02-27T12-45-33.464Z.sql | 13 -- package-lock.json | 160 ++++++++----- package.json | 3 +- src/app/actions/get-dataset-entries.ts | 5 - src/app/actions/get-filter-options.ts | 2 - src/app/actions/upload-utterances.ts | 119 ---------- src/app/actions/upload.ts | 3 - .../datasets/[id]/entries/[entryId]/page.tsx | 19 -- src/app/admin/datasets/[id]/page.tsx | 2 - src/components/DatasetEntriesList.tsx | 43 ---- src/components/UploadUtterancesModal.tsx | 215 ------------------ src/lib/auth.ts | 7 +- src/lib/model/auth-schema.ts | 107 +++++++++ src/lib/model/dataset_entry.ts | 7 - src/lib/model/index.ts | 2 +- src/lib/model/utterance.ts | 29 --- 16 files changed, 220 insertions(+), 516 deletions(-) delete mode 100644 better-auth_migrations/2026-02-27T12-45-33.464Z.sql delete mode 100644 src/app/actions/upload-utterances.ts delete mode 100644 src/components/UploadUtterancesModal.tsx create mode 100644 src/lib/model/auth-schema.ts delete mode 100644 src/lib/model/utterance.ts diff --git a/better-auth_migrations/2026-02-27T12-45-33.464Z.sql b/better-auth_migrations/2026-02-27T12-45-33.464Z.sql deleted file mode 100644 index eb97fb6..0000000 --- a/better-auth_migrations/2026-02-27T12-45-33.464Z.sql +++ /dev/null @@ -1,13 +0,0 @@ -create table "user" ("id" text not null primary key, "name" text not null, "email" text not null unique, "emailVerified" integer not null, "image" text, "createdAt" date not null, "updatedAt" date not null); - -create table "session" ("id" text not null primary key, "expiresAt" date not null, "token" text not null unique, "createdAt" date not null, "updatedAt" date not null, "ipAddress" text, "userAgent" text, "userId" text not null references "user" ("id") on delete cascade); - -create table "account" ("id" text not null primary key, "accountId" text not null, "providerId" text not null, "userId" text not null references "user" ("id") on delete cascade, "accessToken" text, "refreshToken" text, "idToken" text, "accessTokenExpiresAt" date, "refreshTokenExpiresAt" date, "scope" text, "password" text, "createdAt" date not null, "updatedAt" date not null); - -create table "verification" ("id" text not null primary key, "identifier" text not null, "value" text not null, "expiresAt" date not null, "createdAt" date not null, "updatedAt" date not null); - -create index "session_userId_idx" on "session" ("userId"); - -create index "account_userId_idx" on "account" ("userId"); - -create index "verification_identifier_idx" on "verification" ("identifier"); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f796946..c4ed8c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "ba-tts-dialect-annotation-plattform", "version": "0.1.0", "dependencies": { + "@better-auth/drizzle-adapter": "^1.5.4", "@libsql/client": "^0.17.0", "@tailwindcss/postcss": "^4.2.1", "auth": "^1.5.3", @@ -558,38 +559,45 @@ } }, "node_modules/@better-auth/core": { - "version": "1.4.19", - "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.19.tgz", - "integrity": "sha512-uADLHG1jc5BnEJi7f6ijUN5DmPPRSj++7m/G19z3UqA3MVCo4Y4t1MMa4IIxLCqGDFv22drdfxescgW+HnIowA==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.5.4.tgz", + "integrity": "sha512-k5AdwPRQETZn0vdB60EB9CDxxfllpJXKqVxTjyXIUSRz7delNGlU0cR/iRP3VfVJwvYR1NbekphBDNo+KGoEzQ==", + "license": "MIT", + "peer": true, "dependencies": { - "@standard-schema/spec": "^1.0.0", - "zod": "^4.3.5" + "@standard-schema/spec": "^1.1.0", + "zod": "^4.3.6" }, "peerDependencies": { - "@better-auth/utils": "0.3.0", + "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", - "better-call": "1.1.8", + "@cloudflare/workers-types": ">=4", + "better-call": "1.3.2", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } } }, - "node_modules/@better-auth/telemetry": { - "version": "1.4.19", - "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.4.19.tgz", - "integrity": "sha512-ApGNS7olCTtDpKF8Ow3Z+jvFAirOj7c4RyFUpu8axklh3mH57ndpfUAUjhgA8UVoaaH/mnm/Tl884BlqiewLyw==", - "dependencies": { - "@better-auth/utils": "0.3.0", - "@better-fetch/fetch": "1.1.21" - }, + "node_modules/@better-auth/drizzle-adapter": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.5.4.tgz", + "integrity": "sha512-4M4nMAWrDd3TmpV6dONkJjybBVKRZghe5Oj0NNyDEoXubxastQdO7Sb5B54I1rTx5yoMgsqaB+kbJnu/9UgjQg==", + "license": "MIT", "peerDependencies": { - "@better-auth/core": "1.4.19" + "@better-auth/core": "1.5.4", + "@better-auth/utils": "^0.3.0", + "drizzle-orm": ">=0.41.0" } }, "node_modules/@better-auth/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.1.tgz", + "integrity": "sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg==", "license": "MIT" }, "node_modules/@better-fetch/fetch": { @@ -2814,6 +2822,19 @@ } } }, + "node_modules/auth/node_modules/@better-auth/drizzle-adapter": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.5.3.tgz", + "integrity": "sha512-dib9V1vpwDu+TKLC+L+8Q5bLNS0uE3JCT4pGotw52pnpiQF8msoMK4eEfri19f8DtNltpb2F2yzyIsTugBBYNQ==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "@better-auth/core": "1.5.3", + "@better-auth/utils": "^0.3.0", + "drizzle-orm": ">=0.41.0" + } + }, "node_modules/auth/node_modules/@better-auth/kysely-adapter": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.5.3.tgz", @@ -2848,12 +2869,6 @@ "@better-auth/core": "1.5.3" } }, - "node_modules/auth/node_modules/@better-auth/utils": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.1.tgz", - "integrity": "sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg==", - "license": "MIT" - }, "node_modules/auth/node_modules/better-auth": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.5.3.tgz", @@ -2968,26 +2983,6 @@ } } }, - "node_modules/auth/node_modules/better-call": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.3.2.tgz", - "integrity": "sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw==", - "license": "MIT", - "dependencies": { - "@better-auth/utils": "^0.3.1", - "@better-fetch/fetch": "^1.1.21", - "rou3": "^0.7.12", - "set-cookie-parser": "^3.0.1" - }, - "peerDependencies": { - "zod": "^4.0.0" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, "node_modules/auth/node_modules/drizzle-orm": { "version": "0.41.0", "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.41.0.tgz", @@ -3109,12 +3104,6 @@ } } }, - "node_modules/auth/node_modules/set-cookie-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz", - "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==", - "license": "MIT" - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -3256,7 +3245,42 @@ "better-auth": "^1.4.19" } }, - "node_modules/better-call": { + "node_modules/better-auth/node_modules/@better-auth/core": { + "version": "1.4.19", + "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.19.tgz", + "integrity": "sha512-uADLHG1jc5BnEJi7f6ijUN5DmPPRSj++7m/G19z3UqA3MVCo4Y4t1MMa4IIxLCqGDFv22drdfxescgW+HnIowA==", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "zod": "^4.3.5" + }, + "peerDependencies": { + "@better-auth/utils": "0.3.0", + "@better-fetch/fetch": "1.1.21", + "better-call": "1.1.8", + "jose": "^6.1.0", + "kysely": "^0.28.5", + "nanostores": "^1.0.1" + } + }, + "node_modules/better-auth/node_modules/@better-auth/telemetry": { + "version": "1.4.19", + "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.4.19.tgz", + "integrity": "sha512-ApGNS7olCTtDpKF8Ow3Z+jvFAirOj7c4RyFUpu8axklh3mH57ndpfUAUjhgA8UVoaaH/mnm/Tl884BlqiewLyw==", + "dependencies": { + "@better-auth/utils": "0.3.0", + "@better-fetch/fetch": "1.1.21" + }, + "peerDependencies": { + "@better-auth/core": "1.4.19" + } + }, + "node_modules/better-auth/node_modules/@better-auth/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", + "license": "MIT" + }, + "node_modules/better-auth/node_modules/better-call": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.1.8.tgz", "integrity": "sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw==", @@ -3276,6 +3300,32 @@ } } }, + "node_modules/better-auth/node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/better-call": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.3.2.tgz", + "integrity": "sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw==", + "license": "MIT", + "dependencies": { + "@better-auth/utils": "^0.3.1", + "@better-fetch/fetch": "^1.1.21", + "rou3": "^0.7.12", + "set-cookie-parser": "^3.0.1" + }, + "peerDependencies": { + "zod": "^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/better-sqlite3": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.6.2.tgz", @@ -5244,9 +5294,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz", + "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==", "license": "MIT" }, "node_modules/sharp": { diff --git a/package.json b/package.json index f14b054..8f910df 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,10 @@ "build": "next build", "start": "next start", "db:push": "drizzle-kit push", - "auth:push": "auth migrate" + "auth:push": "auth generate" }, "dependencies": { + "@better-auth/drizzle-adapter": "^1.5.4", "@libsql/client": "^0.17.0", "@tailwindcss/postcss": "^4.2.1", "auth": "^1.5.3", diff --git a/src/app/actions/get-dataset-entries.ts b/src/app/actions/get-dataset-entries.ts index 4991843..3179424 100644 --- a/src/app/actions/get-dataset-entries.ts +++ b/src/app/actions/get-dataset-entries.ts @@ -11,7 +11,6 @@ interface FilterParams { modelName?: string; dialect?: string; iteration?: number; - utteranceId?: string; } export async function getDatasetEntries( @@ -40,10 +39,6 @@ export async function getDatasetEntries( conditions.push(eq(dataset_entry.iteration, filters.iteration)); } - if (filters?.utteranceId) { - conditions.push(eq(dataset_entry.utteranceId, filters.utteranceId)); - } - const whereClause = and(...conditions); const entries = await db diff --git a/src/app/actions/get-filter-options.ts b/src/app/actions/get-filter-options.ts index fcb0ac0..7a4a64e 100644 --- a/src/app/actions/get-filter-options.ts +++ b/src/app/actions/get-filter-options.ts @@ -15,13 +15,11 @@ export async function getFilterOptions(datasetId: number) { const modelNames = [...new Set(entries.map(e => e.modelName))].sort(); const dialects = [...new Set(entries.map(e => e.dialect))].sort(); const iterations = [...new Set(entries.map(e => e.iteration))].sort((a, b) => a - b); - const utteranceIds = [...new Set(entries.map(e => e.utteranceId).filter(Boolean))].sort(); return { speakerIds, modelNames, dialects, iterations, - utteranceIds, }; } diff --git a/src/app/actions/upload-utterances.ts b/src/app/actions/upload-utterances.ts deleted file mode 100644 index 6f1693b..0000000 --- a/src/app/actions/upload-utterances.ts +++ /dev/null @@ -1,119 +0,0 @@ -'use server'; - -import db from '@/lib/db'; -import { dataset_utterance } from '@/lib/model/utterance'; -import { eq, and } from 'drizzle-orm'; -import { revalidatePath } from 'next/cache'; - -export async function uploadDatasetUtterances( - datasetId: number, - formData: FormData -) { - const file = formData.get('file') as File; - - if (!file) { - throw new Error('No file provided'); - } - - if (!file.name.endsWith('.csv')) { - throw new Error('File must be a CSV file'); - } - - try { - const csvContent = await file.text(); - const lines = csvContent.split('\n').filter((line) => line.trim()); - - if (lines.length < 2) { - throw new Error('CSV is empty or invalid'); - } - - // Parse CSV header - const headers = lines[0].split(',').map((h) => h.trim()); - - if (!headers.includes('id') || !headers.includes('text')) { - throw new Error('CSV must have "id" and "text" columns'); - } - - // Get indices of id and text columns - const idIndex = headers.indexOf('id'); - const textIndex = headers.indexOf('text'); - - // Parse utterances - const utterances: typeof dataset_utterance.$inferInsert[] = []; - - for (let i = 1; i < lines.length; i++) { - // Handle CSV parsing with quotes - const line = lines[i]; - const parts: string[] = []; - let current = ''; - let inQuotes = false; - - for (let j = 0; j < line.length; j++) { - const char = line[j]; - const nextChar = line[j + 1]; - - if (char === '"') { - if (inQuotes && nextChar === '"') { - current += '"'; - j++; // Skip next quote - } else { - inQuotes = !inQuotes; - } - } else if (char === ',' && !inQuotes) { - parts.push(current.trim()); - current = ''; - } else { - current += char; - } - } - parts.push(current.trim()); - - if (parts.length > Math.max(idIndex, textIndex)) { - const id = parts[idIndex]?.trim(); - const text = parts[textIndex]?.trim(); - - if (id && text) { - utterances.push({ - datasetId, - id, - text, - }); - } - } - } - - if (utterances.length === 0) { - throw new Error('No valid utterances found in CSV'); - } - - // Check for existing utterances to avoid duplicates - const existingUtterances = await db - .select({ id: dataset_utterance.id }) - .from(dataset_utterance) - .where(eq(dataset_utterance.datasetId, datasetId)); - - const existingIds = new Set(existingUtterances.map((u) => u.id)); - - // Filter out duplicates - const newUtterances = utterances.filter((u) => !existingIds.has(u.id)); - - if (newUtterances.length === 0) { - throw new Error('All utterances already exist in the dataset'); - } - - // Insert new utterances into database - await db.insert(dataset_utterance).values(newUtterances); - - revalidatePath(`/admin/datasets/${datasetId}`); - - return { - success: true, - utterancesCreated: newUtterances.length, - }; - } catch (error) { - console.error('Error uploading utterances:', error); - throw new Error( - error instanceof Error ? error.message : 'Failed to upload utterances' - ); - } -} diff --git a/src/app/actions/upload.ts b/src/app/actions/upload.ts index 586964f..e7caa2f 100644 --- a/src/app/actions/upload.ts +++ b/src/app/actions/upload.ts @@ -2,7 +2,6 @@ import db from '@/lib/db'; import { dataset_entry } from '@/lib/model/dataset_entry'; -import { dataset_utterance } from '@/lib/model/utterance'; import { revalidatePath } from 'next/cache'; import { eq } from 'drizzle-orm'; import { writeFile, mkdir, readFile, rm, readdir } from 'fs/promises'; @@ -14,7 +13,6 @@ interface DatasetEntryInput { id: string; audio_file: string; duration_ms: string; - utt_id: string; speaker: string; model: string; dialect: string; @@ -104,7 +102,6 @@ export async function uploadDatasetEntries( speakerId: row.speaker, modelName: row.model, fileName: relativePath, - utteranceId: row.utt_id || undefined, dialect: row.dialect, iteration: parseInt(row.iteration, 10), }); diff --git a/src/app/admin/datasets/[id]/entries/[entryId]/page.tsx b/src/app/admin/datasets/[id]/entries/[entryId]/page.tsx index 0cf30a2..01e7131 100644 --- a/src/app/admin/datasets/[id]/entries/[entryId]/page.tsx +++ b/src/app/admin/datasets/[id]/entries/[entryId]/page.tsx @@ -1,7 +1,6 @@ import Link from 'next/link'; import db from '@/lib/db'; import { dataset_entry } from '@/lib/model/dataset_entry'; -import { dataset_utterance } from '@/lib/model/utterance'; import { eq } from 'drizzle-orm'; import AudioPlayer from '@/components/AudioPlayer'; @@ -42,17 +41,6 @@ export default async function DatasetEntryPage({ params }: DatasetEntryPageProps const entry = entries[0]; - // Fetch utterance if utteranceId is present - let utterance = null; - if (entry.utteranceId) { - const utterances = await db - .select() - .from(dataset_utterance) - .where(eq(dataset_utterance.id, entry.utteranceId)); - - utterance = utterances.length > 0 ? utterances[0] : null; - } - return (
@@ -107,13 +95,6 @@ export default async function DatasetEntryPage({ params }: DatasetEntryPageProps
- {utterance && ( -
-

Utterance {entry.utteranceId}

-

{utterance.text}

-
- )} -

Created

diff --git a/src/app/admin/datasets/[id]/page.tsx b/src/app/admin/datasets/[id]/page.tsx index a1efd2c..7ea8918 100644 --- a/src/app/admin/datasets/[id]/page.tsx +++ b/src/app/admin/datasets/[id]/page.tsx @@ -5,7 +5,6 @@ import { eq } from 'drizzle-orm'; import EditableDatasetHeader from '@/components/EditableDatasetHeader'; import DatasetEntriesList from '@/components/DatasetEntriesList'; import UploadDatasetEntriesModal from '@/components/UploadDatasetEntriesModal'; -import UploadUtterancesModal from '@/components/UploadUtterancesModal'; import RemoveAllEntriesButton from '@/components/RemoveAllEntriesButton'; interface DatasetPageProps { @@ -57,7 +56,6 @@ export default async function DatasetPage({ params }: DatasetPageProps) {

-
diff --git a/src/components/DatasetEntriesList.tsx b/src/components/DatasetEntriesList.tsx index af4ea15..0c8a723 100644 --- a/src/components/DatasetEntriesList.tsx +++ b/src/components/DatasetEntriesList.tsx @@ -17,7 +17,6 @@ interface DatasetEntry { speakerId: string; modelName: string; fileName: string; - utteranceId: string | null; dialect: string; iteration: number; createdAt: Date; @@ -29,7 +28,6 @@ interface FilterOptions { modelNames: string[]; dialects: string[]; iterations: number[]; - utteranceIds: string[]; } export default function DatasetEntriesList({ @@ -47,7 +45,6 @@ export default function DatasetEntriesList({ modelName: '', dialect: '', iteration: '', - utteranceId: '', }); // Filter options @@ -56,7 +53,6 @@ export default function DatasetEntriesList({ modelNames: [], dialects: [], iterations: [], - utteranceIds: [], }); // Load filter options on mount @@ -85,7 +81,6 @@ export default function DatasetEntriesList({ modelName: filters.modelName || undefined, dialect: filters.dialect || undefined, iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined, - utteranceId: filters.utteranceId || undefined, }; const result = await getDatasetEntries(datasetId, pageNum, filterParams); @@ -112,7 +107,6 @@ export default function DatasetEntriesList({ modelName: filters.modelName || undefined, dialect: filters.dialect || undefined, iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined, - utteranceId: filters.utteranceId || undefined, }; const result = await getDatasetEntries(datasetId, page + 1, filterParams); @@ -140,7 +134,6 @@ export default function DatasetEntriesList({ modelName: '', dialect: '', iteration: '', - utteranceId: '', }); } @@ -229,23 +222,6 @@ export default function DatasetEntriesList({ ))}
-
- - -
@@ -338,23 +314,6 @@ export default function DatasetEntriesList({ ))} -
- - -
@@ -373,7 +332,6 @@ export default function DatasetEntriesList({ Speaker ID Model Name Dialect - Utterance ID File Name Iteration @@ -395,7 +353,6 @@ export default function DatasetEntriesList({ {entry.speakerId} {entry.modelName} {entry.dialect} - {entry.utteranceId || '-'} {entry.fileName} {entry.iteration} diff --git a/src/components/UploadUtterancesModal.tsx b/src/components/UploadUtterancesModal.tsx deleted file mode 100644 index 45b07f8..0000000 --- a/src/components/UploadUtterancesModal.tsx +++ /dev/null @@ -1,215 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { uploadDatasetUtterances } from '@/app/actions/upload-utterances'; -import Modal from '@/components/Modal'; - -interface UploadUtterancesModalProps { - datasetId: number; -} - -export default function UploadUtterancesModal({ - datasetId, -}: UploadUtterancesModalProps) { - const [isOpen, setIsOpen] = useState(false); - const [file, setFile] = useState(null); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(null); - const [success, setSuccess] = useState(false); - const [utterancesCreated, setUtterancesCreated] = useState(0); - const [status, setStatus] = useState(''); - const [isDragging, setIsDragging] = useState(false); - - function handleFileChange(e: React.ChangeEvent) { - const selectedFile = e.target.files?.[0]; - if (selectedFile) { - setFile(selectedFile); - setError(null); - } - } - - function handleDragOver(e: React.DragEvent) { - e.preventDefault(); - e.stopPropagation(); - setIsDragging(true); - } - - function handleDragLeave(e: React.DragEvent) { - e.preventDefault(); - e.stopPropagation(); - setIsDragging(false); - } - - function handleDrop(e: React.DragEvent) { - e.preventDefault(); - e.stopPropagation(); - setIsDragging(false); - - const droppedFiles = e.dataTransfer.files; - if (droppedFiles.length > 0) { - const droppedFile = droppedFiles[0]; - if (droppedFile.name.endsWith('.csv')) { - setFile(droppedFile); - setError(null); - } else { - setError('Please upload a CSV file'); - } - } - } - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setError(null); - setSuccess(false); - - if (!file) { - setError('Please select a CSV file'); - return; - } - - setLoading(true); - setStatus('Preparing upload...'); - - try { - const formData = new FormData(); - formData.append('file', file); - - const result = await uploadDatasetUtterances(datasetId, formData); - - setSuccess(true); - setUtterancesCreated(result.utterancesCreated); - setStatus(`Successfully created ${result.utterancesCreated} utterances!`); - setFile(null); - - setTimeout(() => { - setSuccess(false); - setIsOpen(false); - setStatus(''); - window.location.reload(); - }, 2500); - } catch (err) { - const errorMsg = - err instanceof Error ? err.message : 'Failed to upload utterances'; - setError(errorMsg); - setStatus(''); - } finally { - setLoading(false); - } - } - - function handleClose() { - if (!loading) { - setIsOpen(false); - setFile(null); - setError(null); - setSuccess(false); - setStatus(''); - } - } - - return ( - <> - - - { - const form = document.getElementById( - 'uploadUtterancesForm' - ) as HTMLFormElement; - form?.dispatchEvent(new Event('submit', { bubbles: true })); - }, - variant: 'primary', - disabled: loading || !file, - }, - ]} - > -
-
- -
- - -
-
- -
-

CSV file should contain:

-
    -
  • - id column with - utterance IDs (e.g., utt_001) -
  • -
  • - text column with the - utterance text -
  • -
-
- - {error && ( -
- {error} -
- )} - - {success && ( -
- {status} -
- )} -
-
- - ); -} diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 2442aa6..b570e77 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,10 +1,13 @@ import { betterAuth } from "better-auth"; -import Database from "better-sqlite3"; import { localization } from "better-auth-localization"; +import { drizzleAdapter } from "@better-auth/drizzle-adapter"; +import db from "./db"; export const auth = betterAuth({ - database: new Database("./sqlite_users.db"), + database: drizzleAdapter(db, { + provider: "sqlite", + }), emailAndPassword: { enabled: true, }, diff --git a/src/lib/model/auth-schema.ts b/src/lib/model/auth-schema.ts new file mode 100644 index 0000000..66fc633 --- /dev/null +++ b/src/lib/model/auth-schema.ts @@ -0,0 +1,107 @@ +import { relations, sql } from "drizzle-orm"; +import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core"; + +export const user = sqliteTable("user", { + id: text("id").primaryKey(), + name: text("name").notNull(), + email: text("email").notNull().unique(), + emailVerified: integer("email_verified", { mode: "boolean" }) + .default(false) + .notNull(), + image: text("image"), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), +}); + +export const session = sqliteTable( + "session", + { + id: text("id").primaryKey(), + expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(), + token: text("token").notNull().unique(), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + ipAddress: text("ip_address"), + userAgent: text("user_agent"), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + }, + (table) => [index("session_userId_idx").on(table.userId)], +); + +export const account = sqliteTable( + "account", + { + id: text("id").primaryKey(), + accountId: text("account_id").notNull(), + providerId: text("provider_id").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + accessToken: text("access_token"), + refreshToken: text("refresh_token"), + idToken: text("id_token"), + accessTokenExpiresAt: integer("access_token_expires_at", { + mode: "timestamp_ms", + }), + refreshTokenExpiresAt: integer("refresh_token_expires_at", { + mode: "timestamp_ms", + }), + scope: text("scope"), + password: text("password"), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + }, + (table) => [index("account_userId_idx").on(table.userId)], +); + +export const verification = sqliteTable( + "verification", + { + id: text("id").primaryKey(), + identifier: text("identifier").notNull(), + value: text("value").notNull(), + expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + }, + (table) => [index("verification_identifier_idx").on(table.identifier)], +); + +export const userRelations = relations(user, ({ many }) => ({ + sessions: many(session), + accounts: many(account), +})); + +export const sessionRelations = relations(session, ({ one }) => ({ + user: one(user, { + fields: [session.userId], + references: [user.id], + }), +})); + +export const accountRelations = relations(account, ({ one }) => ({ + user: one(user, { + fields: [account.userId], + references: [user.id], + }), +})); diff --git a/src/lib/model/dataset_entry.ts b/src/lib/model/dataset_entry.ts index b092b44..902415a 100644 --- a/src/lib/model/dataset_entry.ts +++ b/src/lib/model/dataset_entry.ts @@ -1,9 +1,7 @@ import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core'; import { relations } from 'drizzle-orm'; import { dataset } from './dataset'; -import { dataset_utterance } from './utterance'; -// Define the dataset table schema export const dataset_entry = sqliteTable('dataset_entry', { id: integer('id').primaryKey({ autoIncrement: true }), externalId: text('external_id').notNull(), @@ -12,7 +10,6 @@ export const dataset_entry = sqliteTable('dataset_entry', { datasetId: integer('dataset_id') .notNull() .references(() => dataset.id), - utteranceId: text('utterance_id').references(() => dataset_utterance.id), fileName: text('file_name').notNull(), dialect: text('dialect').notNull(), iteration: integer('iteration').notNull(), @@ -28,10 +25,6 @@ export const dataset_entryRelations = relations(dataset_entry, ({ one }) => ({ dataset: one(dataset, { fields: [dataset_entry.datasetId], references: [dataset.id] - }), - utterance: one(dataset_utterance, { - fields: [dataset_entry.utteranceId], - references: [dataset_utterance.id] }) })); diff --git a/src/lib/model/index.ts b/src/lib/model/index.ts index 862f382..39cbe6a 100644 --- a/src/lib/model/index.ts +++ b/src/lib/model/index.ts @@ -1,3 +1,3 @@ export * from "./dataset"; export * from "./dataset_entry"; -export * from "./utterance"; \ No newline at end of file +export * from "./auth-schema"; \ No newline at end of file diff --git a/src/lib/model/utterance.ts b/src/lib/model/utterance.ts deleted file mode 100644 index cc8aed5..0000000 --- a/src/lib/model/utterance.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'; -import { relations } from 'drizzle-orm'; -import { dataset } from './dataset'; - -// Define the dataset_utterance table schema -export const dataset_utterance = sqliteTable('dataset_utterance', { - id: text('id').primaryKey(), - datasetId: integer('dataset_id') - .notNull() - .references(() => dataset.id), - text: text('text').notNull(), - createdAt: integer('created_at', { mode: 'timestamp' }) - .notNull() - .default(new Date()), - updatedAt: integer('updated_at', { mode: 'timestamp' }) - .notNull() - .default(new Date()), -}); - -export const dataset_utteranceRelations = relations(dataset_utterance, ({ one }) => ({ - dataset: one(dataset, { - fields: [dataset_utterance.datasetId], - references: [dataset.id], - }), -})); - -// Create types for dataset_utterance records based on the schema -export type DatasetUtterance = typeof dataset_utterance.$inferSelect; -export type NewDatasetUtterance = typeof dataset_utterance.$inferInsert;