feat: create event for live class
This commit is contained in:
@@ -92,7 +92,7 @@ def update_course(class_name, course, value):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_live_class(class_name, title, duration, date, time, description=None):
|
def create_live_class(class_name, title, duration, date, time, description=None):
|
||||||
date = format_date(date, "yyyy-mm-dd")
|
date = format_date(date, "yyyy-mm-dd", True)
|
||||||
payload = {
|
payload = {
|
||||||
"topic": title,
|
"topic": title,
|
||||||
"start_time": format_datetime(f"{date} {time}", "yyyy-MM-ddTHH:mm:ssZ"),
|
"start_time": format_datetime(f"{date} {time}", "yyyy-MM-ddTHH:mm:ssZ"),
|
||||||
@@ -120,7 +120,7 @@ def create_live_class(class_name, title, duration, date, time, description=None)
|
|||||||
"host": frappe.session.user,
|
"host": frappe.session.user,
|
||||||
"date": date,
|
"date": date,
|
||||||
"time": time,
|
"time": time,
|
||||||
"class": class_name,
|
"class_name": class_name,
|
||||||
"password": data.get("password"),
|
"password": data.get("password"),
|
||||||
"description": description,
|
"description": description,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
"host",
|
"host",
|
||||||
"class",
|
"class_name",
|
||||||
"password",
|
"password",
|
||||||
"column_break_astv",
|
"column_break_astv",
|
||||||
"description",
|
"description",
|
||||||
@@ -57,12 +57,6 @@
|
|||||||
"label": "Timezone",
|
"label": "Timezone",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "class",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Class",
|
|
||||||
"options": "LMS Class"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "host",
|
"fieldname": "host",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -114,11 +108,17 @@
|
|||||||
"fieldtype": "Time",
|
"fieldtype": "Time",
|
||||||
"label": "Time",
|
"label": "Time",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "class_name",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Class",
|
||||||
|
"options": "LMS Class"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-03-02 23:00:33.006661",
|
"modified": "2023-03-06 16:59:28.565587",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Live Class",
|
"name": "LMS Live Class",
|
||||||
|
|||||||
@@ -1,9 +1,60 @@
|
|||||||
# Copyright (c) 2023, Frappe and contributors
|
# Copyright (c) 2023, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
class LMSLiveClass(Document):
|
class LMSLiveClass(Document):
|
||||||
pass
|
def after_insert(self):
|
||||||
|
"""calendar = frappe.db.get_value(
|
||||||
|
"Google Calendar", {"user": frappe.session.user, "enable": 1}, "name"
|
||||||
|
)
|
||||||
|
|
||||||
|
if calendar:
|
||||||
|
event = self.create_event()
|
||||||
|
self.add_event_participants(event, calendar)"""
|
||||||
|
|
||||||
|
def create_event(self):
|
||||||
|
event = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Event",
|
||||||
|
"subject": f"Live Class {self.title}",
|
||||||
|
"starts_on": f"{self.date} {self.time}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
event.save()
|
||||||
|
|
||||||
|
return event
|
||||||
|
|
||||||
|
def add_event_participants(self, event, calendar):
|
||||||
|
participants = frappe.get_all(
|
||||||
|
"Class Student", {"parent": self.class_name}, pluck="student"
|
||||||
|
)
|
||||||
|
|
||||||
|
participants.append(frappe.session.user)
|
||||||
|
print(participants)
|
||||||
|
for participant in participants:
|
||||||
|
print(participant)
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Event Participants",
|
||||||
|
"reference_doctype": "User",
|
||||||
|
"reference_docname": participant,
|
||||||
|
"email": participant,
|
||||||
|
"parent": event.name,
|
||||||
|
"parenttype": "Event",
|
||||||
|
"parentfield": "event_participants",
|
||||||
|
}
|
||||||
|
).save()
|
||||||
|
|
||||||
|
event.reload()
|
||||||
|
event.update(
|
||||||
|
{
|
||||||
|
"sync_with_google_calendar": 1,
|
||||||
|
"google_calendar": calendar,
|
||||||
|
"description": f"A Live Class has been scheduled on {frappe.utils.format_date(self.date, 'medium')} at { frappe.utils.format_time(self.time, 'hh:mm a')}. Click on this link to join. {self.join_url}. {self.description}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
event.save()
|
||||||
|
|||||||
@@ -1984,3 +1984,19 @@ select {
|
|||||||
.resize-none {
|
.resize-none {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lms-page-style {
|
||||||
|
background-color: var(--fg-color);
|
||||||
|
font-size: var(--text-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lms-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
padding: 1rem;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="common-page-style">
|
<div class="common-page-style lms-page-style">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ BreadCrumb(class_info) }}
|
{{ BreadCrumb(class_info) }}
|
||||||
<div class="common-card-style column-card">
|
<div class="">
|
||||||
{{ ClassDetails(class_info) }}
|
{{ ClassDetails(class_info) }}
|
||||||
{{ ClassSections(class_info, class_courses, class_students, published_courses) }}
|
{{ ClassSections(class_info, class_courses, class_students, published_courses) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -30,7 +30,11 @@
|
|||||||
<!-- Class Details -->
|
<!-- Class Details -->
|
||||||
{% macro ClassDetails(class_info) %}
|
{% macro ClassDetails(class_info) %}
|
||||||
<div class="class-details" data-class="{{ class_info.name }}">
|
<div class="class-details" data-class="{{ class_info.name }}">
|
||||||
<div class="medium pull-right">
|
|
||||||
|
<div class="course-home-headings">
|
||||||
|
{{ class_info.title }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
{% if class_info.start_date %}
|
{% if class_info.start_date %}
|
||||||
<span>
|
<span>
|
||||||
{{ frappe.utils.format_date(class_info.start_date, "medium") }} -
|
{{ frappe.utils.format_date(class_info.start_date, "medium") }} -
|
||||||
@@ -42,11 +46,8 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="course-home-headings">
|
|
||||||
{{ class_info.title }}
|
|
||||||
</div>
|
|
||||||
{% if class_info.description %}
|
{% if class_info.description %}
|
||||||
<div class="medium">
|
<div class="">
|
||||||
{{ class_info.description }}
|
{{ class_info.description }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -74,11 +75,13 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{% if is_moderator or is_student %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" data-toggle="tab" href="#live-class">
|
<a class="nav-link" data-toggle="tab" href="#live-class">
|
||||||
{{ _("Live Class") }}
|
{{ _("Live Class") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -93,9 +96,11 @@
|
|||||||
{{ StudentsSection(class_info, class_students) }}
|
{{ StudentsSection(class_info, class_students) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if is_moderator or is_student %}
|
||||||
<div class="tab-pane" id="live-class" role="tabpanel" aria-labelledby="live-class">
|
<div class="tab-pane" id="live-class" role="tabpanel" aria-labelledby="live-class">
|
||||||
{{ LiveClassSection(class_info, live_classes) }}
|
{{ LiveClassSection(class_info, live_classes) }}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -119,7 +124,7 @@
|
|||||||
|
|
||||||
|
|
||||||
{% macro StudentsSection(class_info, class_students) %}
|
{% macro StudentsSection(class_info, class_students) %}
|
||||||
<div class="medium">
|
<div class="">
|
||||||
{% if is_moderator %}
|
{% if is_moderator %}
|
||||||
{{ AddStudents() }}
|
{{ AddStudents() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -190,15 +195,15 @@
|
|||||||
|
|
||||||
{% macro LiveClassSection(class_info, live_classes) %}
|
{% macro LiveClassSection(class_info, live_classes) %}
|
||||||
<div>
|
<div>
|
||||||
{% if is_moderator %}
|
|
||||||
{{ CreateLiveClass(class_info) }}
|
{{ CreateLiveClass(class_info) }}
|
||||||
{% endif %}
|
|
||||||
{{ LiveClassList(class_info, live_classes) }}
|
{{ LiveClassList(class_info, live_classes) }}
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
{% macro CreateLiveClass(class_info) %}
|
{% macro CreateLiveClass(class_info) %}
|
||||||
|
|
||||||
|
{% if is_moderator %}
|
||||||
<button class="btn btn-secondary btn-sm" id="open-class-modal">
|
<button class="btn btn-secondary btn-sm" id="open-class-modal">
|
||||||
{{ _("Create a Live Class") }}
|
{{ _("Create a Live Class") }}
|
||||||
</button>
|
</button>
|
||||||
@@ -228,23 +233,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
{% macro LiveClassList(class_info, live_classes) %}
|
{% macro LiveClassList(class_info, live_classes) %}
|
||||||
<div class="cards-parent mt-5">
|
<div class="cards-parent mt-8">
|
||||||
{% for class in live_classes %}
|
{% for class in live_classes %}
|
||||||
<div class="common-card-style column-card">
|
<div class="lms-card">
|
||||||
<div class="course-card-title">
|
<div class="course-card-title mb-0">
|
||||||
{{ class.title }}
|
{{ class.title }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="small">
|
||||||
{{ class.description }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ frappe.utils.format_date(class.date, "medium") }} {{ _("at") }}
|
{{ frappe.utils.format_date(class.date, "medium") }} {{ _("at") }}
|
||||||
{{ frappe.utils.format_time(class.time, "hh:mm a") }}
|
{{ frappe.utils.format_time(class.time, "hh:mm a") }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="my-4">
|
||||||
|
{{ class.description }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if class.owner == frappe.session.user and class.date == frappe.utils.getdate() %}
|
||||||
|
<a class="btn btn-secondary btn-sm mt-auto" href="{{ class.start_url }}">
|
||||||
|
{{ _("Start Class") }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if is_student and class.date == frappe.utils.getdate() %}
|
||||||
|
<a class="btn btn-secondary btn-sm mt-auto" href="{{ class.join_url }}">
|
||||||
|
{{ _("Join Class") }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -83,10 +83,11 @@ const update_course = (e) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const create_live_class = (e) => {
|
const create_live_class = (e) => {
|
||||||
|
let class_name = $(".class-details").data("class");
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "lms.lms.doctype.lms_class.lms_class.create_live_class",
|
method: "lms.lms.doctype.lms_class.lms_class.create_live_class",
|
||||||
args: {
|
args: {
|
||||||
class_name: $(".class-details").data("class"),
|
class_name: class_name,
|
||||||
title: $("input[data-fieldname='meeting_title']").val(),
|
title: $("input[data-fieldname='meeting_title']").val(),
|
||||||
duration: $("input[data-fieldname='meeting_duration']").val(),
|
duration: $("input[data-fieldname='meeting_duration']").val(),
|
||||||
date: $("input[data-fieldname='meeting_date']").val(),
|
date: $("input[data-fieldname='meeting_date']").val(),
|
||||||
@@ -97,6 +98,16 @@ const create_live_class = (e) => {
|
|||||||
},
|
},
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
$("#live-class-modal").modal("hide");
|
$("#live-class-modal").modal("hide");
|
||||||
|
frappe.show_alert(
|
||||||
|
{
|
||||||
|
message: __("Live Class created successfully"),
|
||||||
|
indicator: "green",
|
||||||
|
},
|
||||||
|
3
|
||||||
|
);
|
||||||
|
setTimeout(function () {
|
||||||
|
window.location.href = `/classes/${class_name}#live-class`;
|
||||||
|
}, 1000);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from lms.lms.utils import has_course_moderator_role
|
from lms.lms.utils import has_course_moderator_role
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
from frappe.utils import getdate
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
@@ -28,14 +29,6 @@ def get_context(context):
|
|||||||
"Class Student", {"parent": class_name}, ["student", "student_name", "username"]
|
"Class Student", {"parent": class_name}, ["student", "student_name", "username"]
|
||||||
)
|
)
|
||||||
|
|
||||||
context.is_moderator = has_course_moderator_role()
|
|
||||||
|
|
||||||
context.live_classes = frappe.get_all(
|
|
||||||
"LMS Live Class",
|
|
||||||
{"class": class_name},
|
|
||||||
["title", "description", "time", "date", "start_url", "join_url"],
|
|
||||||
)
|
|
||||||
|
|
||||||
for student in class_students:
|
for student in class_students:
|
||||||
if student.student == frappe.session.user:
|
if student.student == frappe.session.user:
|
||||||
session_user.append(student)
|
session_user.append(student)
|
||||||
@@ -46,3 +39,15 @@ def get_context(context):
|
|||||||
context.class_students = session_user + remaining_students
|
context.class_students = session_user + remaining_students
|
||||||
else:
|
else:
|
||||||
context.class_students = class_students
|
context.class_students = class_students
|
||||||
|
|
||||||
|
context.is_moderator = has_course_moderator_role()
|
||||||
|
|
||||||
|
students = [student.student for student in class_students]
|
||||||
|
context.is_student = frappe.session.user in students
|
||||||
|
|
||||||
|
context.live_classes = frappe.get_all(
|
||||||
|
"LMS Live Class",
|
||||||
|
{"class_name": class_name, "date": [">=", getdate()]},
|
||||||
|
["title", "description", "time", "date", "start_url", "join_url", "owner"],
|
||||||
|
order_by="date",
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="common-page-style">
|
<div class="common-page-style lms-page-style">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% if has_course_moderator_role() %}
|
{% if has_course_moderator_role() %}
|
||||||
<a class="btn btn-default btn-sm pull-right" href="/class/new">
|
<a class="btn btn-secondary btn-sm pull-right" href="/class/new">
|
||||||
{{ _("Create Class") }}
|
{{ _("Create Class") }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
{% set course_count = frappe.db.count("Class Course", {"parent": class.name}) %}
|
{% set course_count = frappe.db.count("Class Course", {"parent": class.name}) %}
|
||||||
{% set student_count = frappe.db.count("Class Student", {"parent": class.name}) %}
|
{% set student_count = frappe.db.count("Class Student", {"parent": class.name}) %}
|
||||||
|
|
||||||
<div class="common-card-style column-card">
|
<div class="lms-card">
|
||||||
<div class="text-muted small">
|
<div class="text-muted small">
|
||||||
{% if course_count %}
|
{% if course_count %}
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
Reference in New Issue
Block a user