Merge pull request #654 from pateljannat/timetable-milestones
feat: timetable milestones
This commit is contained in:
@@ -52,6 +52,7 @@ const set_timetable = (frm) => {
|
|||||||
"start_time",
|
"start_time",
|
||||||
"end_time",
|
"end_time",
|
||||||
"duration",
|
"duration",
|
||||||
|
"milestone",
|
||||||
],
|
],
|
||||||
filters: {
|
filters: {
|
||||||
parent: frm.doc.timetable_template,
|
parent: frm.doc.timetable_template,
|
||||||
@@ -82,6 +83,7 @@ const add_timetable_rows = (frm, timetable) => {
|
|||||||
.format("HH:mm")
|
.format("HH:mm")
|
||||||
: null;
|
: null;
|
||||||
child.duration = row.duration;
|
child.duration = row.duration;
|
||||||
|
child.milestone = row.milestone;
|
||||||
});
|
});
|
||||||
frm.refresh_field("timetable");
|
frm.refresh_field("timetable");
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ from frappe.utils import (
|
|||||||
cint,
|
cint,
|
||||||
format_date,
|
format_date,
|
||||||
format_datetime,
|
format_datetime,
|
||||||
add_to_date,
|
|
||||||
getdate,
|
|
||||||
get_datetime,
|
|
||||||
)
|
)
|
||||||
from lms.lms.utils import get_lessons, get_lesson_index, get_lesson_url
|
from lms.lms.utils import get_lessons, get_lesson_index, get_lesson_url
|
||||||
from lms.www.utils import get_quiz_details, get_assignment_details
|
from lms.www.utils import get_quiz_details, get_assignment_details
|
||||||
@@ -325,7 +322,17 @@ def get_batch_timetable(batch):
|
|||||||
timetable = frappe.get_all(
|
timetable = frappe.get_all(
|
||||||
"LMS Batch Timetable",
|
"LMS Batch Timetable",
|
||||||
filters={"parent": batch},
|
filters={"parent": batch},
|
||||||
fields=["reference_doctype", "reference_docname", "date", "start_time", "end_time"],
|
fields=[
|
||||||
|
"reference_doctype",
|
||||||
|
"reference_docname",
|
||||||
|
"date",
|
||||||
|
"start_time",
|
||||||
|
"end_time",
|
||||||
|
"milestone",
|
||||||
|
"name",
|
||||||
|
"idx",
|
||||||
|
"parent",
|
||||||
|
],
|
||||||
order_by="date",
|
order_by="date",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -362,20 +369,26 @@ def get_timetable_details(timetable):
|
|||||||
assessment = frappe._dict({"assessment_name": entry.reference_docname})
|
assessment = frappe._dict({"assessment_name": entry.reference_docname})
|
||||||
|
|
||||||
if entry.reference_doctype == "Course Lesson":
|
if entry.reference_doctype == "Course Lesson":
|
||||||
entry.icon = "icon-list"
|
|
||||||
course = frappe.db.get_value(
|
course = frappe.db.get_value(
|
||||||
entry.reference_doctype, entry.reference_docname, "course"
|
entry.reference_doctype, entry.reference_docname, "course"
|
||||||
)
|
)
|
||||||
entry.url = get_lesson_url(course, get_lesson_index(entry.reference_docname))
|
entry.url = get_lesson_url(course, get_lesson_index(entry.reference_docname))
|
||||||
|
|
||||||
|
entry.completed = (
|
||||||
|
True
|
||||||
|
if frappe.db.exists(
|
||||||
|
"LMS Course Progress",
|
||||||
|
{"lesson": entry.reference_docname, "member": frappe.session.user},
|
||||||
|
)
|
||||||
|
else False
|
||||||
|
)
|
||||||
|
|
||||||
elif entry.reference_doctype == "LMS Quiz":
|
elif entry.reference_doctype == "LMS Quiz":
|
||||||
entry.icon = "icon-quiz"
|
|
||||||
entry.url = "/quizzes"
|
entry.url = "/quizzes"
|
||||||
details = get_quiz_details(assessment, frappe.session.user)
|
details = get_quiz_details(assessment, frappe.session.user)
|
||||||
entry.update(details)
|
entry.update(details)
|
||||||
|
|
||||||
elif entry.reference_doctype == "LMS Assignment":
|
elif entry.reference_doctype == "LMS Assignment":
|
||||||
entry.icon = "icon-quiz"
|
|
||||||
details = get_assignment_details(assessment, frappe.session.user)
|
details = get_assignment_details(assessment, frappe.session.user)
|
||||||
entry.update(details)
|
entry.update(details)
|
||||||
|
|
||||||
@@ -390,3 +403,40 @@ def send_email_to_students(batch, subject, reply_to, message):
|
|||||||
frappe.sendmail(
|
frappe.sendmail(
|
||||||
recipients=students, subject=subject, reply_to=reply_to, message=message
|
recipients=students, subject=subject, reply_to=reply_to, message=message
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def is_milestone_complete(idx, batch):
|
||||||
|
previous_rows = frappe.get_all(
|
||||||
|
"LMS Batch Timetable",
|
||||||
|
filters={"parent": batch, "idx": ["<", cint(idx)]},
|
||||||
|
fields=["reference_doctype", "reference_docname", "idx"],
|
||||||
|
order_by="idx",
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in previous_rows:
|
||||||
|
if row.reference_doctype == "Course Lesson":
|
||||||
|
if not frappe.db.exists(
|
||||||
|
"LMS Course Progress",
|
||||||
|
{"member": frappe.session.user, "lesson": row.reference_docname},
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if row.reference_doctype == "LMS Quiz":
|
||||||
|
passing_percentage = frappe.db.get_value(
|
||||||
|
row.reference_doctype, row.reference_docname, "passing_percentage"
|
||||||
|
)
|
||||||
|
if not frappe.db.exists(
|
||||||
|
"LMS Quiz Submission",
|
||||||
|
{"quiz": row.reference_docname, "member": frappe.session.user},
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if row.reference_doctype == "LMS Assignment":
|
||||||
|
if not frappe.db.exists(
|
||||||
|
"LMS Assignment Submission",
|
||||||
|
{"assignment": row.reference_docname, "member": frappe.session.user},
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
"column_break_merq",
|
"column_break_merq",
|
||||||
"start_time",
|
"start_time",
|
||||||
"end_time",
|
"end_time",
|
||||||
"duration"
|
"duration",
|
||||||
|
"milestone"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -69,12 +70,17 @@
|
|||||||
"fieldname": "day",
|
"fieldname": "day",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Day"
|
"label": "Day"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "milestone",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Milestone"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-03 17:40:31.530181",
|
"modified": "2023-10-20 11:58:01.782921",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Batch Timetable",
|
"name": "LMS Batch Timetable",
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ def quiz_summary(quiz, results):
|
|||||||
correct = result["is_correct"][0]
|
correct = result["is_correct"][0]
|
||||||
for point in result["is_correct"]:
|
for point in result["is_correct"]:
|
||||||
correct = correct and point
|
correct = correct and point
|
||||||
|
|
||||||
result["is_correct"] = correct
|
result["is_correct"] = correct
|
||||||
|
|
||||||
question_details = frappe.db.get_value(
|
question_details = frappe.db.get_value(
|
||||||
@@ -100,6 +99,8 @@ def quiz_summary(quiz, results):
|
|||||||
"score": score,
|
"score": score,
|
||||||
"score_out_of": score_out_of,
|
"score_out_of": score_out_of,
|
||||||
"member": frappe.session.user,
|
"member": frappe.session.user,
|
||||||
|
"percentage": percentage,
|
||||||
|
"passing_percentage": quiz_details.passing_percentage,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
submission.save(ignore_permissions=True)
|
submission.save(ignore_permissions=True)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"score_out_of",
|
"score_out_of",
|
||||||
"column_break_gkip",
|
"column_break_gkip",
|
||||||
"percentage",
|
"percentage",
|
||||||
|
"passing_percentage",
|
||||||
"section_break_6",
|
"section_break_6",
|
||||||
"result"
|
"result"
|
||||||
],
|
],
|
||||||
@@ -96,12 +97,20 @@
|
|||||||
"non_negative": 1,
|
"non_negative": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "passing_percentage",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Passing Percentage",
|
||||||
|
"non_negative": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-17 13:07:27.979974",
|
"modified": "2023-10-17 13:07:27.979975",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Submission",
|
"name": "LMS Quiz Submission",
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
class LMSQuizSubmission(Document):
|
class LMSQuizSubmission(Document):
|
||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
self.set_percentage()
|
if not self.percentage:
|
||||||
|
self.set_percentage()
|
||||||
|
|
||||||
def set_percentage(self):
|
def set_percentage(self):
|
||||||
if self.score and self.score_out_of:
|
if self.score and self.score_out_of:
|
||||||
|
|||||||
@@ -686,7 +686,9 @@ const get_calendar_options = (element, calendar_id) => {
|
|||||||
],
|
],
|
||||||
template: {
|
template: {
|
||||||
time: function (event) {
|
time: function (event) {
|
||||||
|
let hide = event.raw.completed ? "" : "hide";
|
||||||
return `<div class="calendar-event-time">
|
return `<div class="calendar-event-time">
|
||||||
|
<img class='icon icon-sm pull-right ${hide}' src="/assets/lms/icons/check.svg">
|
||||||
<div> ${frappe.datetime.get_time(event.start.d.d)} -
|
<div> ${frappe.datetime.get_time(event.start.d.d)} -
|
||||||
${frappe.datetime.get_time(event.end.d.d)} </div>
|
${frappe.datetime.get_time(event.end.d.d)} </div>
|
||||||
<div class="calendar-event-title"> ${event.title} </div>
|
<div class="calendar-event-title"> ${event.title} </div>
|
||||||
@@ -717,6 +719,11 @@ const create_events = (calendar, events, calendar_id) => {
|
|||||||
},
|
},
|
||||||
raw: {
|
raw: {
|
||||||
url: event.url,
|
url: event.url,
|
||||||
|
milestone: event.milestone,
|
||||||
|
name: event.name,
|
||||||
|
idx: event.idx,
|
||||||
|
parent: event.parent,
|
||||||
|
completed: event.completed,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -730,9 +737,28 @@ const add_links_to_events = (calendar) => {
|
|||||||
event_date = moment(event_date).format("YYYY-MM-DD");
|
event_date = moment(event_date).format("YYYY-MM-DD");
|
||||||
|
|
||||||
let current_date = moment().format("YYYY-MM-DD");
|
let current_date = moment().format("YYYY-MM-DD");
|
||||||
if (allow_future || moment(event_date).isSameOrBefore(current_date)) {
|
|
||||||
window.open(event.raw.url, "_blank");
|
if (!moment(event_date).isSameOrBefore(current_date) && !allow_future)
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
if (event.raw.milestone) {
|
||||||
|
frappe.call({
|
||||||
|
method: "lms.lms.doctype.lms_batch.lms_batch.is_milestone_complete",
|
||||||
|
args: {
|
||||||
|
idx: event.raw.idx,
|
||||||
|
batch: event.raw.parent,
|
||||||
|
},
|
||||||
|
callback: (data) => {
|
||||||
|
if (data.message) window.open(event.raw.url, "_blank");
|
||||||
|
else
|
||||||
|
frappe.show_alert({
|
||||||
|
message:
|
||||||
|
"Please complete all previous activities to proceed.",
|
||||||
|
indicator: "red",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else window.open(event.raw.url, "_blank");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -755,17 +781,13 @@ const set_calendar_range = (calendar, events) => {
|
|||||||
).format("DD MMMM YYYY")}`
|
).format("DD MMMM YYYY")}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (week_start.diff(moment(events[0].date), "days") <= 0) {
|
if (week_start.diff(moment(events[0].date), "days") <= 0)
|
||||||
$("#prev-week").hide();
|
$("#prev-week").hide();
|
||||||
} else {
|
else $("#prev-week").show();
|
||||||
$("#prev-week").show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (week_end.diff(moment(events.slice(-1)[0].date), "days") > 0) {
|
if (week_end.diff(moment(events.slice(-1)[0].date), "days") > 0)
|
||||||
$("#next-week").hide();
|
$("#next-week").hide();
|
||||||
} else {
|
else $("#next-week").show();
|
||||||
$("#next-week").show();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const get_background_color = (doctype) => {
|
const get_background_color = (doctype) => {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ def get_assignment_details(assessment, member):
|
|||||||
"assignment": assessment.assessment_name,
|
"assignment": assessment.assessment_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
assessment.completed = False
|
||||||
if existing_submission:
|
if existing_submission:
|
||||||
assessment.submission = frappe.db.get_value(
|
assessment.submission = frappe.db.get_value(
|
||||||
"LMS Assignment Submission",
|
"LMS Assignment Submission",
|
||||||
@@ -101,6 +101,7 @@ def get_assignment_details(assessment, member):
|
|||||||
["name", "status", "comments"],
|
["name", "status", "comments"],
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
|
assessment.completed = True
|
||||||
|
|
||||||
assessment.edit_url = f"/assignments/{assessment.assessment_name}"
|
assessment.edit_url = f"/assignments/{assessment.assessment_name}"
|
||||||
submission_name = existing_submission if existing_submission else "new-submission"
|
submission_name = existing_submission if existing_submission else "new-submission"
|
||||||
@@ -112,7 +113,10 @@ def get_assignment_details(assessment, member):
|
|||||||
|
|
||||||
|
|
||||||
def get_quiz_details(assessment, member):
|
def get_quiz_details(assessment, member):
|
||||||
assessment.title = frappe.db.get_value("LMS Quiz", assessment.assessment_name, "title")
|
assessment_details = frappe.db.get_value(
|
||||||
|
"LMS Quiz", assessment.assessment_name, ["title", "passing_percentage"], as_dict=1
|
||||||
|
)
|
||||||
|
assessment.title = assessment_details.title
|
||||||
|
|
||||||
existing_submission = frappe.get_all(
|
existing_submission = frappe.get_all(
|
||||||
"LMS Quiz Submission",
|
"LMS Quiz Submission",
|
||||||
@@ -120,13 +124,17 @@ def get_quiz_details(assessment, member):
|
|||||||
"member": member,
|
"member": member,
|
||||||
"quiz": assessment.assessment_name,
|
"quiz": assessment.assessment_name,
|
||||||
},
|
},
|
||||||
["name", "score"],
|
["name", "score", "percentage"],
|
||||||
order_by="creation desc",
|
order_by="percentage desc",
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(existing_submission):
|
if len(existing_submission):
|
||||||
assessment.submission = existing_submission[0]
|
assessment.submission = existing_submission[0]
|
||||||
|
|
||||||
|
assessment.completed = False
|
||||||
|
if assessment.submission:
|
||||||
|
assessment.completed = True
|
||||||
|
|
||||||
assessment.edit_url = f"/quizzes/{assessment.assessment_name}"
|
assessment.edit_url = f"/quizzes/{assessment.assessment_name}"
|
||||||
submission_name = (
|
submission_name = (
|
||||||
existing_submission[0].name if len(existing_submission) else "new-submission"
|
existing_submission[0].name if len(existing_submission) else "new-submission"
|
||||||
|
|||||||
Reference in New Issue
Block a user