feat(VocabService, localization, VocabLessonView): extend assistant wait feedback and timeout duration
All checks were successful
Deploy to production / deploy (push) Successful in 2m2s
All checks were successful
Deploy to production / deploy (push) Successful in 2m2s
- Increased the timeout duration for the language assistant from 30 seconds to 120 seconds to accommodate longer processing times. - Added new localization strings across multiple languages (Cebuano, German, English, Spanish, French) to provide user feedback during the assistant's wait period, enhancing clarity and user experience. - Implemented a visual waiting indicator in VocabLessonView to inform users that the assistant is still processing their request, improving overall interaction quality.
This commit is contained in:
@@ -2844,7 +2844,7 @@ export default class VocabService {
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 30000);
|
||||
const timeout = setTimeout(() => controller.abort(), 120000);
|
||||
|
||||
const temperatureByMode = {
|
||||
explain: 0.4,
|
||||
@@ -2878,7 +2878,7 @@ export default class VocabService {
|
||||
} catch (error) {
|
||||
const err = new Error(
|
||||
error?.name === 'AbortError'
|
||||
? 'Der Sprachassistent hat zu lange für eine Antwort gebraucht.'
|
||||
? 'Der Sprachassistent hat länger als zwei Minuten für eine Antwort gebraucht.'
|
||||
: 'Der Sprachassistent konnte nicht erreicht werden.'
|
||||
);
|
||||
err.status = 502;
|
||||
|
||||
@@ -715,6 +715,9 @@
|
||||
"languageAssistantInputPlaceholder": "Ask a leksiyon question o write imong own sentence para sa tamaion.",
|
||||
"languageAssistantSend": "Padal-a ang aron katabang",
|
||||
"languageAssistantSending": "Getting answer ...",
|
||||
"languageAssistantWaitingTitle": "Ang pinulongan katabang is still working.",
|
||||
"languageAssistantWaitingBody": "Local models sama sa Ollama can take a few seconds, especially kung loading pa ang model.",
|
||||
"languageAssistantWaitingElapsed": "Waiting time: {seconds} s",
|
||||
"languageAssistantError": "Ang pinulongan katabang could not answer right now.",
|
||||
"languageAssistantPresetExplainStart": "Palihog explain ang main patterns ug grammar sa ang leksiyon",
|
||||
"languageAssistantPatternHint": "Focus especially sa kini nga pattern",
|
||||
|
||||
@@ -697,6 +697,9 @@
|
||||
"languageAssistantInputPlaceholder": "Stelle eine Frage zur Lektion oder schreibe einen eigenen Satz zum Korrigieren.",
|
||||
"languageAssistantSend": "An Sprachassistent senden",
|
||||
"languageAssistantSending": "Antwort wird geholt ...",
|
||||
"languageAssistantWaitingTitle": "Der Sprachassistent arbeitet noch.",
|
||||
"languageAssistantWaitingBody": "Lokale Modelle wie Ollama brauchen manchmal einige Sekunden, besonders wenn das Modell erst geladen wird.",
|
||||
"languageAssistantWaitingElapsed": "Wartezeit: {seconds} s",
|
||||
"languageAssistantError": "Der Sprachassistent konnte gerade nicht antworten.",
|
||||
"languageAssistantPresetExplainStart": "Erkläre mir bitte die wichtigsten Muster und die Grammatik in der Lektion",
|
||||
"languageAssistantPatternHint": "Nutze dabei besonders dieses Muster",
|
||||
|
||||
@@ -697,6 +697,9 @@
|
||||
"languageAssistantInputPlaceholder": "Ask a lesson question or write your own sentence for correction.",
|
||||
"languageAssistantSend": "Send to assistant",
|
||||
"languageAssistantSending": "Getting answer ...",
|
||||
"languageAssistantWaitingTitle": "The language assistant is still working.",
|
||||
"languageAssistantWaitingBody": "Local models like Ollama can take a few seconds, especially while the model is loading.",
|
||||
"languageAssistantWaitingElapsed": "Waiting time: {seconds}s",
|
||||
"languageAssistantError": "The language assistant could not answer right now.",
|
||||
"languageAssistantPresetExplainStart": "Please explain the main patterns and grammar in the lesson",
|
||||
"languageAssistantPatternHint": "Focus especially on this pattern",
|
||||
|
||||
@@ -681,6 +681,9 @@
|
||||
"languageAssistantInputPlaceholder": "Haz una pregunta sobre la lección o escribe tu propia frase para corregirla.",
|
||||
"languageAssistantSend": "Enviar al asistente",
|
||||
"languageAssistantSending": "Obteniendo respuesta ...",
|
||||
"languageAssistantWaitingTitle": "El asistente sigue trabajando.",
|
||||
"languageAssistantWaitingBody": "Los modelos locales como Ollama pueden tardar unos segundos, especialmente mientras se carga el modelo.",
|
||||
"languageAssistantWaitingElapsed": "Tiempo de espera: {seconds} s",
|
||||
"languageAssistantError": "El asistente no pudo responder ahora mismo.",
|
||||
"languageAssistantPresetExplainStart": "Explícame por favor los patrones y la gramática principales de la lección",
|
||||
"languageAssistantPatternHint": "Concéntrate especialmente en este patrón",
|
||||
|
||||
@@ -681,6 +681,9 @@
|
||||
"languageAssistantInputPlaceholder": "Posez une question sur la leçon ou écrivez votre propre phrase à corriger.",
|
||||
"languageAssistantSend": "Envoyer à l'assistant vocal",
|
||||
"languageAssistantSending": "La réponse sera récupérée...",
|
||||
"languageAssistantWaitingTitle": "L'assistant vocal travaille encore.",
|
||||
"languageAssistantWaitingBody": "Les modèles locaux comme Ollama peuvent prendre quelques secondes, surtout lorsque le modèle est en cours de chargement.",
|
||||
"languageAssistantWaitingElapsed": "Temps d'attente : {seconds} s",
|
||||
"languageAssistantError": "L'assistant vocal ne pouvait pas répondre pour le moment.",
|
||||
"languageAssistantPresetExplainStart": "Veuillez m'expliquer les modèles et la grammaire les plus importants de la leçon.",
|
||||
"languageAssistantPatternHint": "Utilisez ce modèle en particulier",
|
||||
|
||||
@@ -469,6 +469,15 @@
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div v-if="assistantSubmitting" class="language-assistant-waiting" role="status" aria-live="polite">
|
||||
<span class="language-assistant-waiting__spinner" aria-hidden="true"></span>
|
||||
<div>
|
||||
<strong>{{ $t('socialnetwork.vocab.courses.languageAssistantWaitingTitle') }}</strong>
|
||||
<p>{{ $t('socialnetwork.vocab.courses.languageAssistantWaitingBody') }}</p>
|
||||
<small>{{ $t('socialnetwork.vocab.courses.languageAssistantWaitingElapsed', { seconds: assistantWaitElapsedSeconds }) }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="language-assistant-panel__input">
|
||||
<span>{{ $t('socialnetwork.vocab.courses.languageAssistantInputLabel') }}</span>
|
||||
<textarea
|
||||
@@ -1094,6 +1103,9 @@ export default {
|
||||
assistantInput: '',
|
||||
assistantError: '',
|
||||
assistantMode: 'practice',
|
||||
assistantWaitStartedAt: null,
|
||||
assistantWaitElapsedSeconds: 0,
|
||||
assistantWaitTimer: null,
|
||||
isAssistantFocused: false,
|
||||
nextLessonId: null,
|
||||
showCompletionDialog: false,
|
||||
@@ -2760,6 +2772,7 @@ export default {
|
||||
|
||||
this.assistantError = '';
|
||||
this.assistantSubmitting = true;
|
||||
this.startAssistantWaitTimer();
|
||||
this.assistantMessages.push({ role: 'user', content: message });
|
||||
if (!customMessage) {
|
||||
this.assistantInput = '';
|
||||
@@ -2780,8 +2793,29 @@ export default {
|
||||
this.assistantError = e.response?.data?.error || e.message || this.$t('socialnetwork.vocab.courses.languageAssistantError');
|
||||
} finally {
|
||||
this.assistantSubmitting = false;
|
||||
this.stopAssistantWaitTimer();
|
||||
}
|
||||
},
|
||||
startAssistantWaitTimer() {
|
||||
this.stopAssistantWaitTimer();
|
||||
this.assistantWaitStartedAt = Date.now();
|
||||
this.assistantWaitElapsedSeconds = 0;
|
||||
this.assistantWaitTimer = window.setInterval(() => {
|
||||
if (!this.assistantWaitStartedAt) {
|
||||
this.assistantWaitElapsedSeconds = 0;
|
||||
return;
|
||||
}
|
||||
this.assistantWaitElapsedSeconds = Math.max(0, Math.floor((Date.now() - this.assistantWaitStartedAt) / 1000));
|
||||
}, 1000);
|
||||
},
|
||||
stopAssistantWaitTimer() {
|
||||
if (this.assistantWaitTimer) {
|
||||
window.clearInterval(this.assistantWaitTimer);
|
||||
this.assistantWaitTimer = null;
|
||||
}
|
||||
this.assistantWaitStartedAt = null;
|
||||
this.assistantWaitElapsedSeconds = 0;
|
||||
},
|
||||
initializeExercises(exercises) {
|
||||
// Initialisiere Antwort-Arrays für Gap Fill Übungen
|
||||
exercises.forEach(exercise => {
|
||||
@@ -4055,6 +4089,7 @@ export default {
|
||||
window.clearTimeout(this.lessonStateSaveTimer);
|
||||
this.lessonStateSaveTimer = null;
|
||||
}
|
||||
this.stopAssistantWaitTimer();
|
||||
// Stoppe alle aktiven Recognition-Instanzen
|
||||
Object.keys(this.activeRecognition).forEach(exerciseId => {
|
||||
this.stopRecognition(exerciseId);
|
||||
@@ -4149,6 +4184,42 @@ export default {
|
||||
background: rgba(58, 117, 196, 0.08);
|
||||
}
|
||||
|
||||
.language-assistant-waiting {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid rgba(248, 162, 43, 0.35);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(248, 162, 43, 0.1);
|
||||
}
|
||||
|
||||
.language-assistant-waiting__spinner {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-top: 2px;
|
||||
border: 3px solid rgba(248, 162, 43, 0.28);
|
||||
border-top-color: var(--color-primary-orange);
|
||||
border-radius: 50%;
|
||||
animation: assistant-spin 0.9s linear infinite;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.language-assistant-waiting p {
|
||||
margin: 4px 0;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.language-assistant-waiting small {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
@keyframes assistant-spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.language-assistant-panel__input {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
|
||||
Reference in New Issue
Block a user