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

@@ -11,6 +11,7 @@ interface FilterParams {
modelName?: string;
dialect?: string;
iteration?: number;
utteranceId?: string;
}
export async function getDatasetEntries(
@@ -39,6 +40,10 @@ export async function getDatasetEntries(
conditions.push(eq(dataset_entry.iteration, filters.iteration));
}
if (filters?.utteranceId) {
conditions.push(like(dataset_entry.utteranceId, `%${filters.utteranceId}%`));
}
const whereClause = and(...conditions);
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 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((id): id is string => Boolean(id)))].sort();
return {
speakerIds,
modelNames,
dialects,
iterations,
utteranceIds,
};
}

View File

@@ -131,6 +131,8 @@ export async function processDatasetEntries(
externalId: row.id,
speakerId: row.speaker,
modelName: row.model,
utteranceId: row.utt_id,
utteranceText: row.text,
fileName: relativePath,
dialect: row.dialect,
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>
</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">
<p className="text-sm text-gray-600 mb-1">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>
</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">
<p className="text-sm text-gray-600 mb-3">Audio Player</p>
<AudioPlayer datasetId={datasetIdNum} fileName={entry.fileName} externalId={entry.externalId} />

View File

@@ -16,6 +16,8 @@ interface DatasetEntry {
externalId: string;
speakerId: string;
modelName: string;
utteranceId: string | null;
utteranceText: string | null;
fileName: string;
dialect: string;
iteration: number;
@@ -28,6 +30,7 @@ interface FilterOptions {
modelNames: string[];
dialects: string[];
iterations: number[];
utteranceIds: string[];
}
export default function DatasetEntriesList({
@@ -45,6 +48,7 @@ export default function DatasetEntriesList({
modelName: '',
dialect: '',
iteration: '',
utteranceId: '',
});
// Filter options
@@ -53,6 +57,7 @@ export default function DatasetEntriesList({
modelNames: [],
dialects: [],
iterations: [],
utteranceIds: [],
});
// Load filter options on mount
@@ -81,6 +86,7 @@ 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);
@@ -107,6 +113,7 @@ 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);
@@ -134,6 +141,7 @@ export default function DatasetEntriesList({
modelName: '',
dialect: '',
iteration: '',
utteranceId: '',
});
}
@@ -153,7 +161,7 @@ export default function DatasetEntriesList({
Clear all
</button>
</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>
<label className="block text-sm font-medium text-gray-700 mb-1">
Speaker ID
@@ -222,6 +230,23 @@ export default function DatasetEntriesList({
))}
</select>
</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>
@@ -245,7 +270,7 @@ export default function DatasetEntriesList({
Clear all
</button>
</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>
<label className="block text-sm font-medium text-gray-700 mb-1">
Speaker ID
@@ -314,6 +339,23 @@ export default function DatasetEntriesList({
))}
</select>
</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>
@@ -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">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">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">File Name</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 className="py-3 px-4">{entry.speakerId}</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 truncate">{entry.fileName}</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(),
speakerId: text('speaker_id').notNull(),
modelName: text('model_name').notNull(),
utteranceId: text('utterance_id'),
utteranceText: text('utterance_text'),
datasetId: integer('dataset_id')
.notNull()
.references(() => dataset.id),