diff --git a/frontend/src/components/Quiz.vue b/frontend/src/components/Quiz.vue
index b925cb7f..165e666f 100644
--- a/frontend/src/components/Quiz.vue
+++ b/frontend/src/components/Quiz.vue
@@ -207,7 +207,7 @@
@@ -282,7 +290,7 @@ import {
FormControl,
} from 'frappe-ui'
import { ref, watch, reactive, inject, computed } from 'vue'
-import { createToast } from '@/utils/'
+import { createToast, showToast } from '@/utils/'
import { CheckCircle, XCircle, MinusCircle } from 'lucide-vue-next'
import { timeAgo } from '@/utils'
import { useRouter } from 'vue-router'
@@ -536,7 +544,7 @@ const addToLocalStorage = () => {
localStorage.setItem(quiz.data.title, JSON.stringify(quizData))
}
-const nextQuetion = () => {
+const nextQuestion = () => {
if (!quiz.data.show_answers && questionDetails.data?.type != 'Open Ended') {
checkAnswer()
} else {
@@ -574,6 +582,16 @@ const createSubmission = () => {
if (quiz.data && quiz.data.max_attempts) attempts.reload()
if (quiz.data.duration) clearInterval(timerInterval)
},
+ onError(err) {
+ const errorTitle = err?.message || ''
+ if (errorTitle.includes('MaximumAttemptsExceededError')) {
+ const errorMessage = err.messages?.[0] || err
+ showToast(__('Error'), __(errorMessage), 'x')
+ setTimeout(() => {
+ window.location.reload()
+ }, 3000)
+ }
+ },
}
)
}
diff --git a/frontend/src/pages/QuizForm.vue b/frontend/src/pages/QuizForm.vue
index b8f66df6..c143d2aa 100644
--- a/frontend/src/pages/QuizForm.vue
+++ b/frontend/src/pages/QuizForm.vue
@@ -55,7 +55,7 @@
{
const { userResource } = usersStore()
- const { isLoggedIn } = sessionStore()
+ let { isLoggedIn } = sessionStore()
const { allowGuestAccess } = useSettings()
try {
diff --git a/frontend/src/utils/quiz.js b/frontend/src/utils/quiz.js
index e391bc30..4781ba70 100644
--- a/frontend/src/utils/quiz.js
+++ b/frontend/src/utils/quiz.js
@@ -4,6 +4,7 @@ import { createApp, h } from 'vue'
import { usersStore } from '../stores/user'
import translationPlugin from '../translation'
import { CircleHelp } from 'lucide-vue-next'
+import router from '@/router'
export class Quiz {
constructor({ data, api, readOnly }) {
@@ -46,6 +47,7 @@ export class Quiz {
quiz: quiz,
})
app.use(translationPlugin)
+ app.use(router)
const { userResource } = usersStore()
app.provide('$user', userResource)
app.mount(this.wrapper)
diff --git a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py
index 0618eb2b..b643ea54 100644
--- a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py
+++ b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py
@@ -10,12 +10,29 @@ from frappe.desk.doctype.notification_log.notification_log import make_notificat
class LMSQuizSubmission(Document):
def validate(self):
+ self.validate_if_max_attempts_exceeded()
self.validate_marks()
self.set_percentage()
def on_update(self):
self.notify_member()
+ def validate_if_max_attempts_exceeded(self):
+ max_attempts = frappe.db.get_value("LMS Quiz", self.quiz, ["max_attempts"])
+ if max_attempts == 0:
+ return
+
+ current_user_submission_count = frappe.db.count(
+ self.doctype, filters={"quiz": self.quiz, "member": frappe.session.user}
+ )
+ if current_user_submission_count >= max_attempts:
+ frappe.throw(
+ _("You have exceeded the maximum number of attempts ({0}) for this quiz").format(
+ max_attempts
+ ),
+ MaximumAttemptsExceededError,
+ )
+
def validate_marks(self):
self.score = 0
for row in self.result:
@@ -52,3 +69,7 @@ class LMSQuizSubmission(Document):
)
make_notification_logs(notification, [self.member])
+
+
+class MaximumAttemptsExceededError(frappe.DuplicateEntryError):
+ pass
diff --git a/lms/locale/ar.po b/lms/locale/ar.po
index 2c4cc89c..8170ae3a 100644
--- a/lms/locale/ar.po
+++ b/lms/locale/ar.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/bs.po b/lms/locale/bs.po
index edbdc727..8e1b48f5 100644
--- a/lms/locale/bs.po
+++ b/lms/locale/bs.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/de.po b/lms/locale/de.po
index 91c9842f..30bf52a9 100644
--- a/lms/locale/de.po
+++ b/lms/locale/de.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "Max. Versuche"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/eo.po b/lms/locale/eo.po
index ed735b93..b7f51f3a 100644
--- a/lms/locale/eo.po
+++ b/lms/locale/eo.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "crwdns150150:0crwdne150150:0"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr "crwdns150152:0crwdne150152:0"
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/es.po b/lms/locale/es.po
index 47c52864..990f9ca9 100644
--- a/lms/locale/es.po
+++ b/lms/locale/es.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "Intentos máximos"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr "Intentos máximos"
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/fa.po b/lms/locale/fa.po
index 47a823bf..a53d970d 100644
--- a/lms/locale/fa.po
+++ b/lms/locale/fa.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/fr.po b/lms/locale/fr.po
index 5261d43a..fb35ea76 100644
--- a/lms/locale/fr.po
+++ b/lms/locale/fr.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/hu.po b/lms/locale/hu.po
index d3438f3d..95ac9a35 100644
--- a/lms/locale/hu.po
+++ b/lms/locale/hu.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/main.pot b/lms/locale/main.pot
index 675185dc..4eccc5d0 100644
--- a/lms/locale/main.pot
+++ b/lms/locale/main.pot
@@ -3042,7 +3042,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/pl.po b/lms/locale/pl.po
index c82d6ab1..765a1678 100644
--- a/lms/locale/pl.po
+++ b/lms/locale/pl.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/ru.po b/lms/locale/ru.po
index 41d0d1f5..915fcb8a 100644
--- a/lms/locale/ru.po
+++ b/lms/locale/ru.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "Максимум попыток"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/sv.po b/lms/locale/sv.po
index 630da1f1..102d136a 100644
--- a/lms/locale/sv.po
+++ b/lms/locale/sv.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "Maximalt antal försök"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr "Maximalt antal försök"
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/tr.po b/lms/locale/tr.po
index ccad300a..7a2d33b1 100644
--- a/lms/locale/tr.po
+++ b/lms/locale/tr.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr "Maksimum Deneme"
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'
diff --git a/lms/locale/zh.po b/lms/locale/zh.po
index 766432a0..23d4f542 100644
--- a/lms/locale/zh.po
+++ b/lms/locale/zh.po
@@ -3031,7 +3031,7 @@ msgid "Max Attempts"
msgstr ""
#: frontend/src/pages/QuizForm.vue:58
-msgid "Maximun Attempts"
+msgid "Maximum Attempts"
msgstr ""
#. Label of the medium (Select) field in DocType 'LMS Batch'