diff --git a/.github/helper/install_dependencies.sh b/.github/helper/install_dependencies.sh
index e4c45b4b..574144b8 100644
--- a/.github/helper/install_dependencies.sh
+++ b/.github/helper/install_dependencies.sh
@@ -4,7 +4,8 @@ set -e
echo "Setting Up System Dependencies..."
sudo apt update
-sudo apt install libcups2-dev redis-server mariadb-client-10.6 mariadb-client-core-10.6
+sudo apt remove mysql-server mysql-client
+sudo apt install libcups2-dev redis-server mariadb-client-10.6
install_wkhtmltopdf() {
wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
diff --git a/cypress/e2e/course_creation.cy.js b/cypress/e2e/course_creation.cy.js
index 3aaf6155..48f3c5dd 100644
--- a/cypress/e2e/course_creation.cy.js
+++ b/cypress/e2e/course_creation.cy.js
@@ -86,26 +86,50 @@ describe("Course Creation", () => {
// Add Discussion
cy.get(".reply").click();
cy.wait(500);
- cy.get(".topic-title").type("Question Title");
- cy.get(".comment-field").type(
- "Question Content. This is a very long question. It contains more than once sentence. Its meant to be this long as this is a UI test."
- );
- cy.get(".submit-discussion").click();
+ cy.get(".discussion-modal").should("be.visible");
- // View Discussion
- cy.wait(1000);
- cy.get(".discussion-topic-title:first").contains("Question Title");
- cy.get(".sidebar-parent:first").click();
- cy.get(".reply-text").contains(
- "Question Content. This is a very long question. It contains more than once sentence. Its meant to be this long as this is a UI test."
+ // Enter title
+ cy.get(".modal .topic-title")
+ .type("Discussion from tests")
+ .should("have.value", "Discussion from tests");
+
+ // Enter comment
+ cy.get(".modal .discussions-comment").type(
+ "This is a discussion from the cypress ui tests."
);
- cy.get(".comment-field:visible").type(
- "This is a reply to the previous comment. Its not that long."
+
+ // Submit
+ cy.get(".modal .submit-discussion").click();
+ cy.wait(2000);
+
+ // Check if discussion is added to page and content is visible
+ cy.get(".sidebar-parent:first .discussion-topic-title").should(
+ "have.text",
+ "Discussion from tests"
);
- cy.get(".submit-discussion:visible").click();
- cy.wait(1000);
- cy.get(".reply-text:last p").contains(
- "This is a reply to the previous comment. Its not that long."
+ cy.get(".sidebar-parent:first .discussion-topic-title").click();
+ cy.get(".discussion-on-page:visible").should("have.class", "show");
+ cy.get(
+ ".discussion-on-page:visible .reply-card .reply-text .ql-editor p"
+ ).should(
+ "have.text",
+ "This is a discussion from the cypress ui tests."
);
+
+ cy.get(".discussion-form:visible .discussions-comment").type(
+ "This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page."
+ );
+
+ cy.get(".discussion-form:visible .submit-discussion").click();
+ cy.wait(3000);
+ cy.get(".discussion-on-page:visible").should("have.class", "show");
+ cy.get(".discussion-on-page:visible")
+ .children(".reply-card")
+ .eq(1)
+ .find(".reply-text")
+ .should(
+ "have.text",
+ "This is a discussion from the cypress ui tests. This comment was entered through the commentbox on the page.\n"
+ );
});
});
diff --git a/lms/lms/utils.py b/lms/lms/utils.py
index 7bed5c92..f7ecaa72 100644
--- a/lms/lms/utils.py
+++ b/lms/lms/utils.py
@@ -57,21 +57,28 @@ def generate_slug(title, doctype):
return slugify(title, used_slugs=slugs)
-def get_membership(course, member, batch=None):
+def get_membership(course, member=None, batch=None):
+ if not member:
+ member = frappe.session.user
+
filters = {"member": member, "course": course}
if batch:
filters["batch"] = batch
- membership = frappe.db.get_value(
- "LMS Batch Membership",
- filters,
- ["name", "batch", "current_lesson", "member_type", "progress"],
- as_dict=True,
- )
+ is_member = frappe.db.exists("LMS Batch Membership", filters)
+ if is_member:
+ membership = frappe.db.get_value(
+ "LMS Batch Membership",
+ filters,
+ ["name", "batch", "current_lesson", "member_type", "progress"],
+ as_dict=True,
+ )
- if membership and membership.batch:
- membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
- return membership
+ if membership and membership.batch:
+ membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
+ return membership
+
+ return False
def get_chapters(course):
@@ -534,7 +541,7 @@ def has_course_moderator_role(member=None):
def has_course_evaluator_role(member=None):
return frappe.db.get_value(
"Has Role",
- {"parent": member or frappe.session.user, "role": "Evaluator"},
+ {"parent": member or frappe.session.user, "role": "Class Evaluator"},
"name",
)
@@ -710,7 +717,7 @@ def get_chart_data(chart_name, timespan, timegrain, from_date, to_date):
}
-@frappe.whitelist(allow_guest=True)
+@frappe.whitelist()
def get_course_completion_data():
all_membership = frappe.db.count("LMS Batch Membership")
completed = frappe.db.count("LMS Batch Membership", {"progress": ["like", "%100%"]})
@@ -795,3 +802,21 @@ def get_evaluator(course, class_name=None):
evaluator = frappe.db.get_value("LMS Course", course, "evaluator")
return evaluator
+
+
+def get_upcoming_evals(student, courses):
+ upcoming_evals = frappe.get_all(
+ "LMS Certificate Request",
+ {
+ "member": student,
+ "course": ["in", courses],
+ "date": [">=", frappe.utils.nowdate()],
+ },
+ ["date", "start_time", "course", "evaluator", "google_meet_link"],
+ order_by="date",
+ )
+
+ for evals in upcoming_evals:
+ evals.course_title = frappe.db.get_value("LMS Course", evals.course, "title")
+ evals.evaluator_name = frappe.db.get_value("User", evals.evaluator, "full_name")
+ return upcoming_evals
diff --git a/lms/public/css/style.css b/lms/public/css/style.css
index e3a4e0be..803fd9e0 100644
--- a/lms/public/css/style.css
+++ b/lms/public/css/style.css
@@ -43,7 +43,7 @@ body {
margin-top: 2rem;
}
-.frappe-control .ql-editor:not(.read-mode) {
+.field-group .frappe-control .ql-editor:not(.read-mode) {
background-color: #FFFFFF;
}
@@ -321,11 +321,12 @@ input[type=checkbox] {
}
.common-card-style {
- display: flex;
- background: #FFFFFF;
- border-radius: var(--border-radius-md);
- position: relative;
- border: 1px solid var(--gray-300)
+ display: flex;
+ background: #FFFFFF;
+ border-radius: var(--border-radius-md);
+ position: relative;
+ border: 1px solid var(--gray-300);
+ box-shadow: var(--shadow-inset);
}
.course-card {
@@ -817,7 +818,7 @@ input[type=checkbox] {
}
.lesson-pagination {
- margin: 2rem 0;
+ margin: 2rem 0 5rem;
}
.lesson-video {
@@ -1648,10 +1649,6 @@ li {
color: var(--gray-600);
}
-.discussions-parent .empty-state {
- background-color: var(--gray-200);
-}
-
.job-cards-parent {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
@@ -2208,4 +2205,77 @@ select {
display: flex;
font-size: var(--text-sm);
padding: 0.5rem 0.5rem 0 0.5rem;
+}
+
+.lms-page-style .discussions-section-title {
+ font-size: var(--text-lg);
+}
+
+.class-dashboard .progress {
+ width: 150px;
+ height: 150px;
+ background: none;
+ position: relative;
+}
+
+.class-dashboard .progress::after {
+ content: "";
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ border: 6px solid #eee;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.class-dashboard .progress>span {
+ width: 50%;
+ height: 100%;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ z-index: 1;
+}
+
+.class-dashboard .progress .progress-left {
+ left: 0;
+}
+
+.class-dashboard .progress .progress-bar {
+ width: 100%;
+ height: 100%;
+ background: none;
+ border-width: 6px;
+ border-style: solid;
+ position: absolute;
+ top: 0;
+}
+
+.class-dashboard .progress .progress-left .progress-bar {
+ left: 100%;
+ border-top-right-radius: 80px;
+ border-bottom-right-radius: 80px;
+ border-left: 0;
+ -webkit-transform-origin: center left;
+ transform-origin: center left;
+}
+
+.class-dashboard .progress .progress-right {
+ right: 0;
+}
+
+.class-dashboard .progress .progress-right .progress-bar {
+ left: -100%;
+ border-top-left-radius: 80px;
+ border-bottom-left-radius: 80px;
+ border-right: 0;
+ -webkit-transform-origin: center right;
+ transform-origin: center right;
+}
+
+.class-dashboard .progress .progress-value {
+ position: absolute;
+ top: 0;
+ left: 0;
}
\ No newline at end of file
diff --git a/lms/public/js/website.bundle.js b/lms/public/js/website.bundle.js
index f24ab539..1e86a794 100644
--- a/lms/public/js/website.bundle.js
+++ b/lms/public/js/website.bundle.js
@@ -1,4 +1,5 @@
import "./profile.js";
import "./common_functions.js";
import "../../../../frappe/frappe/public/js/frappe/ui/chart.js";
+import "../../../../frappe/frappe/public/js/frappe/ui/keyboard.js";
import "../../../../frappe/frappe/public/js/frappe/event_emitter.js";
diff --git a/lms/templates/assessments.html b/lms/templates/assessments.html
new file mode 100644
index 00000000..e5f1f0b0
--- /dev/null
+++ b/lms/templates/assessments.html
@@ -0,0 +1,60 @@
+
+
+ {{ _("Assessments") }}
+
+ {% if assessments | length %}
+
+
+
+
+
+ {{ _("Assessment") }}
+
+
+ {{ _("Type") }}
+
+
+ {{ _("Status/Score") }}
+
+
+
+
+ {% for assessment in assessments %}
+ {% set has_access = is_moderator and assessment.submission or frappe.session.user == student.name %}
+
+
+
+ {{ assessment.title }}
+
+
+ {{ (assessment.assessment_type).split("LMS ")[1] }}
+
+
+
+ {% if assessment.submission %}
+ {% if assessment.assessment_type == "LMS Assignment" %}
+ {% set status = assessment.submission.status %}
+ {% set color = "green" if status == "Pass" else "red" if status == "Fail" else "orange" %}
+
+ {{ status }}
+
+ {% else %}
+
+ {{ assessment.submission.score }}
+
+ {% endif %}
+ {% else %}
+
+ {{ _("Not Attempted") }}
+
+ {% endif %}
+
+
+
+
+ {% endfor %}
+
+ {% else %}
+
{{ _("No Assessments") }}
+ {% endif %}
+
\ No newline at end of file
diff --git a/lms/templates/upcoming_evals.html b/lms/templates/upcoming_evals.html
new file mode 100644
index 00000000..87dc783f
--- /dev/null
+++ b/lms/templates/upcoming_evals.html
@@ -0,0 +1,45 @@
+
+
+ {{ _("Upcoming Evaluations") }}
+
+ {% if upcoming_evals | length %}
+
+ {% for eval in upcoming_evals %}
+
+
+
+ {{ eval.course_title }}
+
+ {% if eval.google_meet_link %}
+
+ {{ _("Join") }}
+
+ {% endif %}
+
+
+
+
+
+
+
+ {{ frappe.utils.format_date(eval.date, "medium") }} -
+
+
+ {{ frappe.utils.format_time(eval.start_time, "hh:mm a") }}
+
+
+
+
+ {{ _("Evaluator") }}:
+
+
+ {{ eval.evaluator_name }}
+
+
+
+ {% endfor %}
+
+ {% else %}
+
{{ _("No Upcoming Evaluations") }}
+ {% endif %}
+
\ No newline at end of file
diff --git a/lms/www/batch/learn.html b/lms/www/batch/learn.html
index 71d4ef9c..ee7fd13d 100644
--- a/lms/www/batch/learn.html
+++ b/lms/www/batch/learn.html
@@ -139,7 +139,9 @@
{% endif %}
- {{ frappe.utils.format_date(lesson.creation, "medium") }}
+
+ {{ frappe.utils.format_date(lesson.creation, "medium") }}
+
@@ -258,13 +260,15 @@
{% set redirect_to = "/courses/" + course.name %}
{% set empty_state_title = _("Have a doubt?") %}
{% set empty_state_subtitle = _("Post it here, our mentors will help you out.") %}
- {% include "frappe/templates/discussions/discussions_section.html" %}
+
+ {% include "frappe/templates/discussions/discussions_section.html" %}
+
{% endmacro %}
-
{%- block script %}
{{ super() }}
+ {{ include_script('controls.bundle.js') }}
+ {% else %}
+
{% endif %}
{{ include_script('controls.bundle.js') }}
diff --git a/lms/www/classes/class.js b/lms/www/classes/class.js
index a8a45a9e..7b43379e 100644
--- a/lms/www/classes/class.js
+++ b/lms/www/classes/class.js
@@ -42,6 +42,14 @@ frappe.ready(() => {
$(".btn-close").click((e) => {
window.location.reload();
});
+
+ $(".btn-schedule-eval").click((e) => {
+ open_evaluation_form(e);
+ });
+
+ $(document).on("click", ".slot", (e) => {
+ mark_active_slot(e);
+ });
});
const create_live_class = (e) => {
@@ -544,3 +552,121 @@ const remove_assessment = (e) => {
});
});
};
+
+const open_evaluation_form = (e) => {
+ this.eval_form = new frappe.ui.Dialog({
+ title: __("Schedule Evaluation"),
+ fields: [
+ {
+ fieldtype: "Link",
+ fieldname: "course",
+ label: __("Course"),
+ options: "LMS Course",
+ reqd: 1,
+ filters: {
+ name: ["in", courses],
+ },
+ filter_description: " ",
+ },
+ {
+ fieldtype: "Date",
+ fieldname: "date",
+ label: __("Date"),
+ reqd: 1,
+ min_date: new Date(
+ frappe.datetime.add_days(frappe.datetime.get_today(), 1)
+ ),
+ change: () => {
+ get_slots();
+ },
+ },
+ {
+ fieldtype: "HTML",
+ fieldname: "slots",
+ label: __("Slots"),
+ },
+ ],
+ primary_action: (values) => {
+ submit_evaluation_form(values);
+ },
+ });
+ this.eval_form.show();
+ setTimeout(() => {
+ $(".modal-body").css("min-height", "300px");
+ }, 1000);
+};
+
+const get_slots = () => {
+ frappe.call({
+ method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
+ args: {
+ course: this.eval_form.get_value("course"),
+ date: this.eval_form.get_value("date"),
+ class_name: $(".class-details").data("class"),
+ },
+ callback: (r) => {
+ if (r.message) {
+ display_slots(r.message);
+ }
+ },
+ });
+};
+
+const display_slots = (slots) => {
+ let slot_html = "";
+ let day = moment(this.eval_form.get_value("date")).format("dddd");
+
+ slots.forEach((slot) => {
+ if (slot.day == day) {
+ slot_html += `
+ ${moment(slot.start_time, "hh:mm").format("hh:mm a")} -
+ ${moment(slot.end_time, "hh:mm").format("hh:mm a")}
+
`;
+ }
+ });
+
+ if (!slot_html) {
+ slot_html = `
+ No slots available for this date.
+
`;
+ }
+
+ $("[data-fieldname='slots']").html(slot_html);
+};
+
+const mark_active_slot = (e) => {
+ $(".slot").removeClass("btn-outline-primary");
+ $(e.currentTarget).addClass("btn-outline-primary");
+ this.current_slot = $(e.currentTarget);
+};
+
+const submit_evaluation_form = (values) => {
+ if (!this.current_slot) {
+ frappe.throw(__("Please select a slot"));
+ }
+
+ frappe.call({
+ method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_certificate_request",
+ args: {
+ course: values.course,
+ date: values.date,
+ start_time: this.current_slot.data("start"),
+ end_time: this.current_slot.data("end"),
+ day: this.current_slot.data("day"),
+ class_name: $(".class-details").data("class"),
+ },
+ callback: (r) => {
+ this.eval_form.hide();
+ frappe.show_alert({
+ message: __("Evaluation scheduled successfully"),
+ indicator: "green",
+ });
+ setTimeout(() => {
+ window.location.reload();
+ }, 1000);
+ },
+ });
+};
diff --git a/lms/www/classes/class.py b/lms/www/classes/class.py
index fe48432f..b57aa904 100644
--- a/lms/www/classes/class.py
+++ b/lms/www/classes/class.py
@@ -1,16 +1,17 @@
from frappe import _
import frappe
-from frappe.utils import getdate
+from frappe.utils import getdate, cint
from lms.www.utils import get_assessments
from lms.lms.utils import (
has_course_moderator_role,
has_course_evaluator_role,
- get_course_progress,
+ get_upcoming_evals,
has_submitted_assessment,
has_graded_assessment,
get_lesson_index,
get_lesson_url,
get_lesson_icon,
+ get_membership,
)
@@ -39,10 +40,13 @@ def get_context(context):
as_dict=True,
)
+ context.reference_doctype = "LMS Class"
+ context.reference_name = class_name
+
class_courses = frappe.get_all(
"Class Course",
{"parent": class_name},
- ["name", "course"],
+ ["name", "course", "title"],
order_by="creation desc",
)
@@ -54,6 +58,7 @@ def get_context(context):
)
context.class_courses = get_class_course_details(class_courses)
+ context.course_list = [course.course for course in context.class_courses]
context.all_courses = frappe.get_all(
"LMS Course", fields=["name", "title"], limit_page_length=0
)
@@ -74,6 +79,9 @@ def get_context(context):
order_by="date",
)
+ context.current_student = (
+ get_current_student_details(class_courses, class_name) if context.is_student else None
+ )
context.all_assignments = get_all_assignments(class_name)
context.all_quizzes = get_all_quizzes(class_name)
context.flow = get_scheduled_flow(class_name)
@@ -140,36 +148,47 @@ def get_class_student_details(class_students, class_courses, assessments):
)
)
student.update(frappe.db.get_value("User", student.student, "last_active", as_dict=1))
-
- courses_completed = 0
- for course in class_courses:
- if get_course_progress(course.course, student.student) == 100:
- courses_completed += 1
- student["courses_completed"] = courses_completed
-
- assessments_completed = 0
- assessments_graded = 0
- for assessment in assessments:
- submission = has_submitted_assessment(
- assessment.assessment_name, assessment.assessment_type, student.student
- )
- if submission:
- assessments_completed += 1
-
- if (
- assessment.assessment_type == "LMS Assignment"
- and has_graded_assessment(submission)
- ):
- assessments_graded += 1
- elif assessment.assessment_type == "LMS Quiz":
- assessments_graded += 1
-
- student["assessments_completed"] = assessments_completed
- student["assessments_graded"] = assessments_graded
+ get_progress_info(student, class_courses)
+ get_assessment_info(student, assessments)
return sort_students(class_students)
+def get_progress_info(student, class_courses):
+ courses_completed = 0
+ student["courses"] = frappe._dict()
+ for course in class_courses:
+ membership = get_membership(course.course, student.student)
+ if membership and membership.progress == 100:
+ courses_completed += 1
+
+ student["courses_completed"] = courses_completed
+ return student
+
+
+def get_assessment_info(student, assessments):
+ assessments_completed = 0
+ assessments_graded = 0
+ for assessment in assessments:
+ submission = has_submitted_assessment(
+ assessment.assessment_name, assessment.assessment_type, student.student
+ )
+ if submission:
+ assessments_completed += 1
+
+ if (
+ assessment.assessment_type == "LMS Assignment" and has_graded_assessment(submission)
+ ):
+ assessments_graded += 1
+ elif assessment.assessment_type == "LMS Quiz":
+ assessments_graded += 1
+
+ student["assessments_completed"] = assessments_completed
+ student["assessments_graded"] = assessments_graded
+
+ return student
+
+
def sort_students(class_students):
session_user = []
remaining_students = []
@@ -226,3 +245,25 @@ def get_scheduled_flow(class_name):
chapter_exists[0]["lessons"].append(lesson)
return chapters
+
+
+def get_current_student_details(class_courses, class_name):
+ student_details = frappe._dict()
+ student_details.courses = frappe._dict()
+ course_list = [course.course for course in class_courses]
+
+ get_course_progress(class_courses, student_details)
+ student_details.name = frappe.session.user
+ student_details.assessments = get_assessments(class_name, frappe.session.user)
+ student_details.upcoming_evals = get_upcoming_evals(frappe.session.user, course_list)
+
+ return student_details
+
+
+def get_course_progress(class_courses, student_details):
+ for course in class_courses:
+ membership = get_membership(course.course, frappe.session.user)
+ if membership:
+ student_details.courses[course.course] = membership.progress
+ else:
+ student_details.courses[course.course] = 0
diff --git a/lms/www/classes/progress.html b/lms/www/classes/progress.html
index 2639eda7..1c191be0 100644
--- a/lms/www/classes/progress.html
+++ b/lms/www/classes/progress.html
@@ -64,112 +64,13 @@
{% macro UpcomingEvals(upcoming_evals) %}
-
- {{ _("Upcoming Evaluations") }}
-
- {% if upcoming_evals | length %}
-
- {% for eval in upcoming_evals %}
-
-
-
- {{ eval.course_title }}
-
- {% if eval.google_meet_link %}
-
- {{ _("Join") }}
-
- {% endif %}
-
-
-
-
-
-
-
- {{ frappe.utils.format_date(eval.date, "medium") }} -
-
-
- {{ frappe.utils.format_time(eval.start_time, "hh:mm a") }}
-
-
-
-
- {{ _("Evaluator") }}:
-
-
- {{ eval.evaluator_name }}
-
-
-
- {% endfor %}
-
- {% else %}
-
{{ _("No Upcoming Evaluations") }}
- {% endif %}
+ {% include "lms/templates/upcoming_evals.html" %}
{% endmacro %}
{% macro Assessments(class_info, student) %}
-
- {{ _("Assessments") }}
-
- {% if assessments | length %}
-
-
-
-
-
- {{ _("Assessment") }}
-
-
- {{ _("Type") }}
-
-
- {{ _("Status/Score") }}
-
-
-
-
- {% for assessment in assessments %}
- {% set has_access = is_moderator and assessment.submission or frappe.session.user == student.name %}
-
-
-
- {{ assessment.title }}
-
-
- {{ (assessment.assessment_type).split("LMS ")[1] }}
-
-
-
- {% if assessment.submission %}
- {% if assessment.assessment_type == "LMS Assignment" %}
- {% set status = assessment.submission.status %}
- {% set color = "green" if status == "Pass" else "red" if status == "Fail" else "orange" %}
-
- {{ status }}
-
- {% else %}
-
- {{ assessment.submission.score }}
-
- {% endif %}
- {% else %}
-
- {{ _("Not Attempted") }}
-
- {% endif %}
-
-
-
-
- {% endfor %}
-
- {% else %}
-
{{ _("No Assessments") }}
- {% endif %}
+ {% include "lms/templates/assessments.html" %}
{% endmacro %}
diff --git a/lms/www/classes/progress.js b/lms/www/classes/progress.js
index d8c2b6e4..6c136c9a 100644
--- a/lms/www/classes/progress.js
+++ b/lms/www/classes/progress.js
@@ -2,130 +2,4 @@ frappe.ready(() => {
$(".clickable-row").click((e) => {
window.location.href = $(e.currentTarget).data("href");
});
-
- $(".btn-schedule-eval").click((e) => {
- open_evaluation_form(e);
- });
-
- $(document).on("click", ".slot", (e) => {
- mark_active_slot(e);
- });
});
-
-const open_evaluation_form = (e) => {
- this.eval_form = new frappe.ui.Dialog({
- title: __("Schedule Evaluation"),
- fields: [
- {
- fieldtype: "Link",
- fieldname: "course",
- label: __("Course"),
- options: "LMS Course",
- reqd: 1,
- filters: {
- name: ["in", courses],
- },
- filter_description: " ",
- },
- {
- fieldtype: "Date",
- fieldname: "date",
- label: __("Date"),
- reqd: 1,
- min_date: new Date(
- frappe.datetime.add_days(frappe.datetime.get_today(), 1)
- ),
- change: () => {
- get_slots();
- },
- },
- {
- fieldtype: "HTML",
- fieldname: "slots",
- label: __("Slots"),
- },
- ],
- primary_action: (values) => {
- submit_evaluation_form(values);
- },
- });
- this.eval_form.show();
- setTimeout(() => {
- $(".modal-body").css("min-height", "300px");
- }, 1000);
-};
-
-const get_slots = () => {
- frappe.call({
- method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
- args: {
- course: this.eval_form.get_value("course"),
- date: this.eval_form.get_value("date"),
- class_name: class_name,
- },
- callback: (r) => {
- if (r.message) {
- display_slots(r.message);
- }
- },
- });
-};
-
-const display_slots = (slots) => {
- let slot_html = "";
- let day = moment(this.eval_form.get_value("date")).format("dddd");
-
- slots.forEach((slot) => {
- if (slot.day == day) {
- slot_html += `
- ${moment(slot.start_time, "hh:mm").format("hh:mm a")} -
- ${moment(slot.end_time, "hh:mm").format("hh:mm a")}
-
`;
- }
- });
-
- if (!slot_html) {
- slot_html = `
- No slots available for this date.
-
`;
- }
-
- $("[data-fieldname='slots']").html(slot_html);
-};
-
-const mark_active_slot = (e) => {
- $(".slot").removeClass("btn-outline-primary");
- $(e.currentTarget).addClass("btn-outline-primary");
- this.current_slot = $(e.currentTarget);
-};
-
-const submit_evaluation_form = (values) => {
- if (!this.current_slot) {
- frappe.throw(__("Please select a slot"));
- }
-
- frappe.call({
- method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_certificate_request",
- args: {
- course: values.course,
- date: values.date,
- start_time: this.current_slot.data("start"),
- end_time: this.current_slot.data("end"),
- day: this.current_slot.data("day"),
- class_name: class_name,
- },
- callback: (r) => {
- this.eval_form.hide();
- frappe.show_alert({
- message: __("Evaluation scheduled successfully"),
- indicator: "green",
- });
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- },
- });
-};
diff --git a/lms/www/classes/progress.py b/lms/www/classes/progress.py
index d273162c..90b41282 100644
--- a/lms/www/classes/progress.py
+++ b/lms/www/classes/progress.py
@@ -1,5 +1,9 @@
import frappe
-from lms.lms.utils import has_course_moderator_role, has_course_evaluator_role
+from lms.lms.utils import (
+ has_course_moderator_role,
+ has_course_evaluator_role,
+ get_upcoming_evals,
+)
from frappe import _
from lms.www.utils import get_assessments
@@ -34,20 +38,4 @@ def get_context(context):
)
context.assessments = get_assessments(class_name, context.student.name)
-
- upcoming_evals = frappe.get_all(
- "LMS Certificate Request",
- {
- "member": context.student.name,
- "course": ["in", context.courses],
- "date": [">=", frappe.utils.nowdate()],
- },
- ["date", "start_time", "course", "evaluator", "google_meet_link"],
- order_by="date",
- )
-
- for evals in upcoming_evals:
- evals.course_title = frappe.db.get_value("LMS Course", evals.course, "title")
- evals.evaluator_name = frappe.db.get_value("User", evals.evaluator, "full_name")
-
- context.upcoming_evals = upcoming_evals
+ context.upcoming_evals = get_upcoming_evals(context.student.name, context.courses)