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 controller = new AbortController();
|
||||||
const timeout = setTimeout(() => controller.abort(), 30000);
|
const timeout = setTimeout(() => controller.abort(), 120000);
|
||||||
|
|
||||||
const temperatureByMode = {
|
const temperatureByMode = {
|
||||||
explain: 0.4,
|
explain: 0.4,
|
||||||
@@ -2878,7 +2878,7 @@ export default class VocabService {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
const err = new Error(
|
const err = new Error(
|
||||||
error?.name === 'AbortError'
|
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.'
|
: 'Der Sprachassistent konnte nicht erreicht werden.'
|
||||||
);
|
);
|
||||||
err.status = 502;
|
err.status = 502;
|
||||||
|
|||||||
@@ -715,6 +715,9 @@
|
|||||||
"languageAssistantInputPlaceholder": "Ask a leksiyon question o write imong own sentence para sa tamaion.",
|
"languageAssistantInputPlaceholder": "Ask a leksiyon question o write imong own sentence para sa tamaion.",
|
||||||
"languageAssistantSend": "Padal-a ang aron katabang",
|
"languageAssistantSend": "Padal-a ang aron katabang",
|
||||||
"languageAssistantSending": "Getting answer ...",
|
"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.",
|
"languageAssistantError": "Ang pinulongan katabang could not answer right now.",
|
||||||
"languageAssistantPresetExplainStart": "Palihog explain ang main patterns ug grammar sa ang leksiyon",
|
"languageAssistantPresetExplainStart": "Palihog explain ang main patterns ug grammar sa ang leksiyon",
|
||||||
"languageAssistantPatternHint": "Focus especially sa kini nga pattern",
|
"languageAssistantPatternHint": "Focus especially sa kini nga pattern",
|
||||||
|
|||||||
@@ -697,6 +697,9 @@
|
|||||||
"languageAssistantInputPlaceholder": "Stelle eine Frage zur Lektion oder schreibe einen eigenen Satz zum Korrigieren.",
|
"languageAssistantInputPlaceholder": "Stelle eine Frage zur Lektion oder schreibe einen eigenen Satz zum Korrigieren.",
|
||||||
"languageAssistantSend": "An Sprachassistent senden",
|
"languageAssistantSend": "An Sprachassistent senden",
|
||||||
"languageAssistantSending": "Antwort wird geholt ...",
|
"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.",
|
"languageAssistantError": "Der Sprachassistent konnte gerade nicht antworten.",
|
||||||
"languageAssistantPresetExplainStart": "Erkläre mir bitte die wichtigsten Muster und die Grammatik in der Lektion",
|
"languageAssistantPresetExplainStart": "Erkläre mir bitte die wichtigsten Muster und die Grammatik in der Lektion",
|
||||||
"languageAssistantPatternHint": "Nutze dabei besonders dieses Muster",
|
"languageAssistantPatternHint": "Nutze dabei besonders dieses Muster",
|
||||||
|
|||||||
@@ -697,6 +697,9 @@
|
|||||||
"languageAssistantInputPlaceholder": "Ask a lesson question or write your own sentence for correction.",
|
"languageAssistantInputPlaceholder": "Ask a lesson question or write your own sentence for correction.",
|
||||||
"languageAssistantSend": "Send to assistant",
|
"languageAssistantSend": "Send to assistant",
|
||||||
"languageAssistantSending": "Getting answer ...",
|
"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.",
|
"languageAssistantError": "The language assistant could not answer right now.",
|
||||||
"languageAssistantPresetExplainStart": "Please explain the main patterns and grammar in the lesson",
|
"languageAssistantPresetExplainStart": "Please explain the main patterns and grammar in the lesson",
|
||||||
"languageAssistantPatternHint": "Focus especially on this pattern",
|
"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.",
|
"languageAssistantInputPlaceholder": "Haz una pregunta sobre la lección o escribe tu propia frase para corregirla.",
|
||||||
"languageAssistantSend": "Enviar al asistente",
|
"languageAssistantSend": "Enviar al asistente",
|
||||||
"languageAssistantSending": "Obteniendo respuesta ...",
|
"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.",
|
"languageAssistantError": "El asistente no pudo responder ahora mismo.",
|
||||||
"languageAssistantPresetExplainStart": "Explícame por favor los patrones y la gramática principales de la lección",
|
"languageAssistantPresetExplainStart": "Explícame por favor los patrones y la gramática principales de la lección",
|
||||||
"languageAssistantPatternHint": "Concéntrate especialmente en este patró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.",
|
"languageAssistantInputPlaceholder": "Posez une question sur la leçon ou écrivez votre propre phrase à corriger.",
|
||||||
"languageAssistantSend": "Envoyer à l'assistant vocal",
|
"languageAssistantSend": "Envoyer à l'assistant vocal",
|
||||||
"languageAssistantSending": "La réponse sera récupérée...",
|
"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.",
|
"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.",
|
"languageAssistantPresetExplainStart": "Veuillez m'expliquer les modèles et la grammaire les plus importants de la leçon.",
|
||||||
"languageAssistantPatternHint": "Utilisez ce modèle en particulier",
|
"languageAssistantPatternHint": "Utilisez ce modèle en particulier",
|
||||||
|
|||||||
@@ -469,6 +469,15 @@
|
|||||||
</article>
|
</article>
|
||||||
</div>
|
</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">
|
<label class="language-assistant-panel__input">
|
||||||
<span>{{ $t('socialnetwork.vocab.courses.languageAssistantInputLabel') }}</span>
|
<span>{{ $t('socialnetwork.vocab.courses.languageAssistantInputLabel') }}</span>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -1094,6 +1103,9 @@ export default {
|
|||||||
assistantInput: '',
|
assistantInput: '',
|
||||||
assistantError: '',
|
assistantError: '',
|
||||||
assistantMode: 'practice',
|
assistantMode: 'practice',
|
||||||
|
assistantWaitStartedAt: null,
|
||||||
|
assistantWaitElapsedSeconds: 0,
|
||||||
|
assistantWaitTimer: null,
|
||||||
isAssistantFocused: false,
|
isAssistantFocused: false,
|
||||||
nextLessonId: null,
|
nextLessonId: null,
|
||||||
showCompletionDialog: false,
|
showCompletionDialog: false,
|
||||||
@@ -2760,6 +2772,7 @@ export default {
|
|||||||
|
|
||||||
this.assistantError = '';
|
this.assistantError = '';
|
||||||
this.assistantSubmitting = true;
|
this.assistantSubmitting = true;
|
||||||
|
this.startAssistantWaitTimer();
|
||||||
this.assistantMessages.push({ role: 'user', content: message });
|
this.assistantMessages.push({ role: 'user', content: message });
|
||||||
if (!customMessage) {
|
if (!customMessage) {
|
||||||
this.assistantInput = '';
|
this.assistantInput = '';
|
||||||
@@ -2780,8 +2793,29 @@ export default {
|
|||||||
this.assistantError = e.response?.data?.error || e.message || this.$t('socialnetwork.vocab.courses.languageAssistantError');
|
this.assistantError = e.response?.data?.error || e.message || this.$t('socialnetwork.vocab.courses.languageAssistantError');
|
||||||
} finally {
|
} finally {
|
||||||
this.assistantSubmitting = false;
|
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) {
|
initializeExercises(exercises) {
|
||||||
// Initialisiere Antwort-Arrays für Gap Fill Übungen
|
// Initialisiere Antwort-Arrays für Gap Fill Übungen
|
||||||
exercises.forEach(exercise => {
|
exercises.forEach(exercise => {
|
||||||
@@ -4055,6 +4089,7 @@ export default {
|
|||||||
window.clearTimeout(this.lessonStateSaveTimer);
|
window.clearTimeout(this.lessonStateSaveTimer);
|
||||||
this.lessonStateSaveTimer = null;
|
this.lessonStateSaveTimer = null;
|
||||||
}
|
}
|
||||||
|
this.stopAssistantWaitTimer();
|
||||||
// Stoppe alle aktiven Recognition-Instanzen
|
// Stoppe alle aktiven Recognition-Instanzen
|
||||||
Object.keys(this.activeRecognition).forEach(exerciseId => {
|
Object.keys(this.activeRecognition).forEach(exerciseId => {
|
||||||
this.stopRecognition(exerciseId);
|
this.stopRecognition(exerciseId);
|
||||||
@@ -4149,6 +4184,42 @@ export default {
|
|||||||
background: rgba(58, 117, 196, 0.08);
|
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 {
|
.language-assistant-panel__input {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|||||||
Reference in New Issue
Block a user