feat(transcription): swap plain textarea for PersonMentionEditor and thread mentionedPersons through autosave
- TranscriptionBlockData now carries mentionedPersons (matches backend schema added in PR-A). - useBlockAutoSave.saveFn signature widens to (blockId, text, mentions); pendingMentions is tracked alongside pendingTexts and is preserved on failure so a retry resends the in-flight payload (B12). - TranscriptionBlock.svelte renders <PersonMentionEditor>, exposing the textarea node back through a captureTextarea callback so the existing quote-selection feature still works. - saveBlock in routes/documents/[id]/+page.svelte forwards mentions on PUT. - flushOnUnload sends mentions in the keepalive payload too. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,8 @@ const block1 = {
|
||||
sortOrder: 0,
|
||||
version: 0,
|
||||
source: 'MANUAL' as const,
|
||||
reviewed: false
|
||||
reviewed: false,
|
||||
mentionedPersons: []
|
||||
};
|
||||
const block2 = {
|
||||
id: 'b2',
|
||||
@@ -26,7 +27,8 @@ const block2 = {
|
||||
sortOrder: 1,
|
||||
version: 0,
|
||||
source: 'OCR' as const,
|
||||
reviewed: true
|
||||
reviewed: true,
|
||||
mentionedPersons: []
|
||||
};
|
||||
|
||||
function renderView(overrides: Record<string, unknown> = {}, service = createConfirmService()) {
|
||||
@@ -141,7 +143,28 @@ describe('TranscriptionEditView — auto-save debounce', () => {
|
||||
vi.advanceTimersByTime(1500);
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Neue Zeile');
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Neue Zeile', []);
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('passes the block mentionedPersons array as the 3rd save argument', async () => {
|
||||
vi.useFakeTimers();
|
||||
const onSaveBlock = vi.fn().mockResolvedValue(undefined);
|
||||
const blockWithMention = {
|
||||
...block1,
|
||||
mentionedPersons: [{ personId: 'p-aug', displayName: 'Auguste Raddatz' }]
|
||||
};
|
||||
renderView({ blocks: [blockWithMention], onSaveBlock });
|
||||
|
||||
const textarea = page.getByRole('textbox').first();
|
||||
await textarea.fill('Hallo @Auguste Raddatz');
|
||||
|
||||
vi.advanceTimersByTime(1500);
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Hallo @Auguste Raddatz', [
|
||||
{ personId: 'p-aug', displayName: 'Auguste Raddatz' }
|
||||
]);
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
@@ -165,7 +188,7 @@ describe('TranscriptionEditView — auto-save debounce', () => {
|
||||
|
||||
// Only one save with the final value
|
||||
expect(onSaveBlock).toHaveBeenCalledTimes(1);
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Second');
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Second', []);
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
@@ -220,7 +243,7 @@ describe('TranscriptionEditView — flush on blur', () => {
|
||||
el.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Blur text');
|
||||
expect(onSaveBlock).toHaveBeenCalledWith('b1', 'Blur text', []);
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user