feat: add utterance field to dataset entries and update related components for filtering and display

This commit is contained in:
averel10
2026-03-13 10:32:46 +01:00
parent 6432375a4f
commit 1aeb9a7c7d
11 changed files with 1150 additions and 2 deletions

View File

@@ -0,0 +1 @@
ALTER TABLE `dataset_entry` ADD `utterance` text;

View File

@@ -0,0 +1,3 @@
ALTER TABLE `dataset_entry` ADD `utterance_id` text;--> statement-breakpoint
ALTER TABLE `dataset_entry` ADD `utterance_text` text;--> statement-breakpoint
ALTER TABLE `dataset_entry` DROP COLUMN `utterance`;

View File

@@ -0,0 +1,528 @@
{
"version": "6",
"dialect": "sqlite",
"id": "a6a553fb-fa1a-48d1-9e34-cb2195d3ace1",
"prevId": "dade89a0-2dca-4d30-afd6-7b1c36089481",
"tables": {
"account": {
"name": "account",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"access_token_expires_at": {
"name": "access_token_expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"refresh_token_expires_at": {
"name": "refresh_token_expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"account_userId_idx": {
"name": "account_userId_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"account_user_id_user_id_fk": {
"name": "account_user_id_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session": {
"name": "session",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ip_address": {
"name": "ip_address",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"session_token_unique": {
"name": "session_token_unique",
"columns": [
"token"
],
"isUnique": true
},
"session_userId_idx": {
"name": "session_userId_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_user_id_user_id_fk": {
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"user": {
"name": "user",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email_verified": {
"name": "email_verified",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"admin": {
"name": "admin",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
}
},
"indexes": {
"user_email_unique": {
"name": "user_email_unique",
"columns": [
"email"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"verification": {
"name": "verification",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
}
},
"indexes": {
"verification_identifier_idx": {
"name": "verification_identifier_idx",
"columns": [
"identifier"
],
"isUnique": false
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"dataset_entry": {
"name": "dataset_entry",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"external_id": {
"name": "external_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"speaker_id": {
"name": "speaker_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"model_name": {
"name": "model_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"utterance": {
"name": "utterance",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"dataset_id": {
"name": "dataset_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"file_name": {
"name": "file_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"dialect": {
"name": "dialect",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"iteration": {
"name": "iteration",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
}
},
"indexes": {},
"foreignKeys": {
"dataset_entry_dataset_id_dataset_id_fk": {
"name": "dataset_entry_dataset_id_dataset_id_fk",
"tableFrom": "dataset_entry",
"tableTo": "dataset",
"columnsFrom": [
"dataset_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"dataset": {
"name": "dataset",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@@ -0,0 +1,535 @@
{
"version": "6",
"dialect": "sqlite",
"id": "d2a2f066-c79f-4de8-8581-3278254f02e1",
"prevId": "a6a553fb-fa1a-48d1-9e34-cb2195d3ace1",
"tables": {
"account": {
"name": "account",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"access_token_expires_at": {
"name": "access_token_expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"refresh_token_expires_at": {
"name": "refresh_token_expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"account_userId_idx": {
"name": "account_userId_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"account_user_id_user_id_fk": {
"name": "account_user_id_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"session": {
"name": "session",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ip_address": {
"name": "ip_address",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"session_token_unique": {
"name": "session_token_unique",
"columns": [
"token"
],
"isUnique": true
},
"session_userId_idx": {
"name": "session_userId_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"session_user_id_user_id_fk": {
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"user": {
"name": "user",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email_verified": {
"name": "email_verified",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"admin": {
"name": "admin",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
}
},
"indexes": {
"user_email_unique": {
"name": "user_email_unique",
"columns": [
"email"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"verification": {
"name": "verification",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
}
},
"indexes": {
"verification_identifier_idx": {
"name": "verification_identifier_idx",
"columns": [
"identifier"
],
"isUnique": false
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"dataset_entry": {
"name": "dataset_entry",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"external_id": {
"name": "external_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"speaker_id": {
"name": "speaker_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"model_name": {
"name": "model_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"utterance_id": {
"name": "utterance_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"utterance_text": {
"name": "utterance_text",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"dataset_id": {
"name": "dataset_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"file_name": {
"name": "file_name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"dialect": {
"name": "dialect",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"iteration": {
"name": "iteration",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
}
},
"indexes": {},
"foreignKeys": {
"dataset_entry_dataset_id_dataset_id_fk": {
"name": "dataset_entry_dataset_id_dataset_id_fk",
"tableFrom": "dataset_entry",
"tableTo": "dataset",
"columnsFrom": [
"dataset_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"dataset": {
"name": "dataset",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch())"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@@ -22,6 +22,20 @@
"when": 1773393053497, "when": 1773393053497,
"tag": "0002_foamy_quicksilver", "tag": "0002_foamy_quicksilver",
"breakpoints": true "breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1773393527437,
"tag": "0003_illegal_zuras",
"breakpoints": true
},
{
"idx": 4,
"version": "6",
"when": 1773394171171,
"tag": "0004_nervous_giant_girl",
"breakpoints": true
} }
] ]
} }

View File

@@ -11,6 +11,7 @@ interface FilterParams {
modelName?: string; modelName?: string;
dialect?: string; dialect?: string;
iteration?: number; iteration?: number;
utteranceId?: string;
} }
export async function getDatasetEntries( export async function getDatasetEntries(
@@ -39,6 +40,10 @@ export async function getDatasetEntries(
conditions.push(eq(dataset_entry.iteration, filters.iteration)); conditions.push(eq(dataset_entry.iteration, filters.iteration));
} }
if (filters?.utteranceId) {
conditions.push(like(dataset_entry.utteranceId, `%${filters.utteranceId}%`));
}
const whereClause = and(...conditions); const whereClause = and(...conditions);
const entries = await db const entries = await db

View File

@@ -15,11 +15,13 @@ export async function getFilterOptions(datasetId: number) {
const modelNames = [...new Set(entries.map(e => e.modelName))].sort(); const modelNames = [...new Set(entries.map(e => e.modelName))].sort();
const dialects = [...new Set(entries.map(e => e.dialect))].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 iterations = [...new Set(entries.map(e => e.iteration))].sort((a, b) => a - b);
const utteranceIds = [...new Set(entries.map(e => e.utteranceId).filter((id): id is string => Boolean(id)))].sort();
return { return {
speakerIds, speakerIds,
modelNames, modelNames,
dialects, dialects,
iterations, iterations,
utteranceIds,
}; };
} }

View File

@@ -131,6 +131,8 @@ export async function processDatasetEntries(
externalId: row.id, externalId: row.id,
speakerId: row.speaker, speakerId: row.speaker,
modelName: row.model, modelName: row.model,
utteranceId: row.utt_id,
utteranceText: row.text,
fileName: relativePath, fileName: relativePath,
dialect: row.dialect, dialect: row.dialect,
iteration: parseInt(row.iteration, 10), iteration: parseInt(row.iteration, 10),

View File

@@ -87,6 +87,11 @@ export default async function DatasetEntryPage({ params }: DatasetEntryPageProps
<p className="text-lg font-semibold">{entry.modelName}</p> <p className="text-lg font-semibold">{entry.modelName}</p>
</div> </div>
<div className="bg-white border border-gray-200 p-4 rounded-lg">
<p className="text-sm text-gray-600 mb-1">Utterance ID</p>
<p className="text-lg font-semibold">{entry.utteranceId || '-'}</p>
</div>
<div className="bg-white border border-gray-200 p-4 rounded-lg"> <div className="bg-white border border-gray-200 p-4 rounded-lg">
<p className="text-sm text-gray-600 mb-1">Dialect</p> <p className="text-sm text-gray-600 mb-1">Dialect</p>
<p className="text-lg font-semibold">{entry.dialect}</p> <p className="text-lg font-semibold">{entry.dialect}</p>
@@ -102,6 +107,11 @@ export default async function DatasetEntryPage({ params }: DatasetEntryPageProps
<p className="text-lg font-semibold break-all">{entry.fileName}</p> <p className="text-lg font-semibold break-all">{entry.fileName}</p>
</div> </div>
<div className="col-span-2 bg-white border border-gray-200 p-4 rounded-lg">
<p className="text-sm text-gray-600 mb-1">Utterance Text</p>
<p className="text-lg font-semibold break-words">{entry.utteranceText || '-'}</p>
</div>
<div className="col-span-2 bg-white border border-gray-200 p-4 rounded-lg"> <div className="col-span-2 bg-white border border-gray-200 p-4 rounded-lg">
<p className="text-sm text-gray-600 mb-3">Audio Player</p> <p className="text-sm text-gray-600 mb-3">Audio Player</p>
<AudioPlayer datasetId={datasetIdNum} fileName={entry.fileName} externalId={entry.externalId} /> <AudioPlayer datasetId={datasetIdNum} fileName={entry.fileName} externalId={entry.externalId} />

View File

@@ -16,6 +16,8 @@ interface DatasetEntry {
externalId: string; externalId: string;
speakerId: string; speakerId: string;
modelName: string; modelName: string;
utteranceId: string | null;
utteranceText: string | null;
fileName: string; fileName: string;
dialect: string; dialect: string;
iteration: number; iteration: number;
@@ -28,6 +30,7 @@ interface FilterOptions {
modelNames: string[]; modelNames: string[];
dialects: string[]; dialects: string[];
iterations: number[]; iterations: number[];
utteranceIds: string[];
} }
export default function DatasetEntriesList({ export default function DatasetEntriesList({
@@ -45,6 +48,7 @@ export default function DatasetEntriesList({
modelName: '', modelName: '',
dialect: '', dialect: '',
iteration: '', iteration: '',
utteranceId: '',
}); });
// Filter options // Filter options
@@ -53,6 +57,7 @@ export default function DatasetEntriesList({
modelNames: [], modelNames: [],
dialects: [], dialects: [],
iterations: [], iterations: [],
utteranceIds: [],
}); });
// Load filter options on mount // Load filter options on mount
@@ -81,6 +86,7 @@ export default function DatasetEntriesList({
modelName: filters.modelName || undefined, modelName: filters.modelName || undefined,
dialect: filters.dialect || undefined, dialect: filters.dialect || undefined,
iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined, iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined,
utteranceId: filters.utteranceId || undefined,
}; };
const result = await getDatasetEntries(datasetId, pageNum, filterParams); const result = await getDatasetEntries(datasetId, pageNum, filterParams);
@@ -107,6 +113,7 @@ export default function DatasetEntriesList({
modelName: filters.modelName || undefined, modelName: filters.modelName || undefined,
dialect: filters.dialect || undefined, dialect: filters.dialect || undefined,
iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined, iteration: filters.iteration ? parseInt(filters.iteration, 10) : undefined,
utteranceId: filters.utteranceId || undefined,
}; };
const result = await getDatasetEntries(datasetId, page + 1, filterParams); const result = await getDatasetEntries(datasetId, page + 1, filterParams);
@@ -134,6 +141,7 @@ export default function DatasetEntriesList({
modelName: '', modelName: '',
dialect: '', dialect: '',
iteration: '', iteration: '',
utteranceId: '',
}); });
} }
@@ -153,7 +161,7 @@ export default function DatasetEntriesList({
Clear all Clear all
</button> </button>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
Speaker ID Speaker ID
@@ -222,6 +230,23 @@ export default function DatasetEntriesList({
))} ))}
</select> </select>
</div> </div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Utterance ID
</label>
<select
value={filters.utteranceId}
onChange={(e) => handleFilterChange('utteranceId', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">All utterance IDs</option>
{filterOptions.utteranceIds.map((utt) => (
<option key={utt} value={utt}>
{utt}
</option>
))}
</select>
</div>
</div> </div>
</div> </div>
@@ -245,7 +270,7 @@ export default function DatasetEntriesList({
Clear all Clear all
</button> </button>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
Speaker ID Speaker ID
@@ -314,6 +339,23 @@ export default function DatasetEntriesList({
))} ))}
</select> </select>
</div> </div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Utterance ID
</label>
<select
value={filters.utteranceId}
onChange={(e) => handleFilterChange('utteranceId', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">All utterance IDs</option>
{filterOptions.utteranceIds.map((utt) => (
<option key={utt} value={utt}>
{utt}
</option>
))}
</select>
</div>
</div> </div>
</div> </div>
@@ -331,6 +373,8 @@ export default function DatasetEntriesList({
<th className="text-left py-3 px-4 font-semibold text-gray-700">External ID</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">External ID</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Speaker ID</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">Speaker ID</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Model Name</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">Model Name</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Utterance ID</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Utterance Text</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Dialect</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">Dialect</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">File Name</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">File Name</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Iteration</th> <th className="text-left py-3 px-4 font-semibold text-gray-700">Iteration</th>
@@ -352,6 +396,8 @@ export default function DatasetEntriesList({
</td> </td>
<td className="py-3 px-4">{entry.speakerId}</td> <td className="py-3 px-4">{entry.speakerId}</td>
<td className="py-3 px-4">{entry.modelName}</td> <td className="py-3 px-4">{entry.modelName}</td>
<td className="py-3 px-4 truncate">{entry.utteranceId || '-'}</td>
<td className="py-3 px-4 truncate">{entry.utteranceText || '-'}</td>
<td className="py-3 px-4">{entry.dialect}</td> <td className="py-3 px-4">{entry.dialect}</td>
<td className="py-3 px-4 truncate">{entry.fileName}</td> <td className="py-3 px-4 truncate">{entry.fileName}</td>
<td className="py-3 px-4">{entry.iteration}</td> <td className="py-3 px-4">{entry.iteration}</td>

View File

@@ -7,6 +7,8 @@ export const dataset_entry = sqliteTable('dataset_entry', {
externalId: text('external_id').notNull(), externalId: text('external_id').notNull(),
speakerId: text('speaker_id').notNull(), speakerId: text('speaker_id').notNull(),
modelName: text('model_name').notNull(), modelName: text('model_name').notNull(),
utteranceId: text('utterance_id'),
utteranceText: text('utterance_text'),
datasetId: integer('dataset_id') datasetId: integer('dataset_id')
.notNull() .notNull()
.references(() => dataset.id), .references(() => dataset.id),