-
${note.title || note.noteId}
-
${badgeText}
+
+
+
+
+
+
${note.title || note.noteId}
+ ${badgeText}
+
+
+ ${isPermanentlyFailed ?
+ `Status: Permanently failed` :
+ `Attempts: ${note.attempts}`}
+
+ Last attempt: ${note.lastAttempt.substring(0, 19)}
+
+ Error: ${(note.error || 'Unknown error').substring(0, 100)}${(note.error && note.error.length > 100) ? '...' : ''}
+
+
+
+
+
-
-
-
-
Attempts: ${note.attempts}
-
Last attempt: ${note.lastAttempt}
-
Error: ${note.error}
`);
@@ -882,38 +910,67 @@ export default class AiSettingsWidget extends OptionsWidget {
$failedList.append($item);
}
- this.$widget.find('.embedding-failed-notes-list').empty().append($failedHeader, $failedList);
+ // Add the header and list to the DOM (no card structure)
+ this.$widget.find('.embedding-failed-notes-list').empty().append($header, $failedList);
// Add event handlers using local variables to avoid 'this' issues
const self = this;
- this.$widget.find('.retry-btn').on('click', async function() {
- const noteId = $(this).data('note-id');
- $(this).prop('disabled', true).text('Retrying...');
+ this.$widget.find('.retry-btn').on('click', async function(e) {
+ // Prevent default behavior
+ e.preventDefault();
+
+ const $button = $(this);
+ const noteId = $button.data('note-id');
+
+ // Show loading state
+ $button.prop('disabled', true)
+ .removeClass('btn-outline-secondary')
+ .addClass('btn-outline-secondary')
+ .html('
Retrying');
const success = await self.retryFailedEmbedding(noteId);
if (success) {
- toastService.showMessage("Note queued for retry");
+ toastService.showMessage(t("ai_llm.note_queued_for_retry"));
await self.refreshEmbeddingStats();
} else {
- toastService.showError("Failed to retry note");
- $(this).prop('disabled', false).text('Retry');
+ toastService.showError(t("ai_llm.failed_to_retry_note"));
+ $button.prop('disabled', false)
+ .html('
Retry');
}
});
- this.$widget.find('.retry-all-btn').on('click', async function() {
- $(this).prop('disabled', true).text('Retrying All...');
+ this.$widget.find('.retry-all-btn').on('click', async function(e) {
+ const $button = $(this);
+
+ // Show loading state
+ $button.prop('disabled', true)
+ .removeClass('btn-primary')
+ .addClass('btn-secondary')
+ .html('
Retrying All');
const success = await self.retryAllFailedEmbeddings();
if (success) {
- toastService.showMessage("All failed notes queued for retry");
+ toastService.showMessage(t("ai_llm.all_notes_queued_for_retry"));
await self.refreshEmbeddingStats();
+
+ // Return button to original state after successful refresh
+ if (!$button.is(':disabled')) { // Check if button still exists
+ $button.prop('disabled', false)
+ .removeClass('btn-secondary')
+ .addClass('btn-primary')
+ .html('Retry All');
+ }
} else {
- toastService.showError("Failed to retry notes");
- $(this).prop('disabled', false).text('Retry All Failed');
+ toastService.showError(t("ai_llm.failed_to_retry_all"));
+ $button.prop('disabled', false)
+ .removeClass('btn-secondary')
+ .addClass('btn-primary')
+ .html('Retry All');
}
});
}
}
+
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 3ba3ad2d4..7aa352a17 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1209,7 +1209,11 @@
"refresh_stats": "Refresh Stats",
"refreshing": "Refreshing...",
"stats_error": "Error fetching embedding statistics",
- "auto_refresh_notice": "Auto-refreshes every {{seconds}} seconds"
+ "auto_refresh_notice": "Auto-refreshes every {{seconds}} seconds",
+ "note_queued_for_retry": "Note queued for retry",
+ "failed_to_retry_note": "Failed to retry note",
+ "all_notes_queued_for_retry": "All failed notes queued for retry",
+ "failed_to_retry_all": "Failed to retry notes"
},
"zoom_factor": {
"title": "Zoom Factor (desktop build only)",
diff --git a/src/services/llm/embeddings/queue.ts b/src/services/llm/embeddings/queue.ts
index 102b52ff8..893dd6d0d 100644
--- a/src/services/llm/embeddings/queue.ts
+++ b/src/services/llm/embeddings/queue.ts
@@ -286,10 +286,10 @@ export async function processEmbeddingQueue() {
if (noteData.attempts + 1 >= 3) {
log.error(`Marked note ${noteData.noteId} as permanently failed after multiple embedding attempts`);
- // Set the failed flag and update the attempts
+ // Set the failed flag but keep the actual attempts count
await sql.execute(`
UPDATE embedding_queue
- SET attempts = 999, failed = 1
+ SET failed = 1
WHERE noteId = ?
`, [noteData.noteId]);
}
@@ -313,10 +313,10 @@ export async function processEmbeddingQueue() {
if (noteData.attempts + 1 >= 3) {
log.error(`Marked note ${noteData.noteId} as permanently failed after multiple embedding attempts`);
- // Set the failed flag and update the attempts
+ // Set the failed flag but keep the actual attempts count
await sql.execute(`
UPDATE embedding_queue
- SET attempts = 999, failed = 1
+ SET failed = 1
WHERE noteId = ?
`, [noteData.noteId]);
}