feat: my class tab

This commit is contained in:
Jannat Patel
2023-06-01 22:44:32 +05:30
parent fe80ef9b85
commit 85903d5385
9 changed files with 183 additions and 62 deletions

View File

@@ -24,26 +24,39 @@ class LMSAssignmentSubmission(Document):
@frappe.whitelist() @frappe.whitelist()
def upload_assignment(assignment_attachment, assignment, lesson=None): def upload_assignment(
assignment_attachment,
assignment,
lesson=None,
status="Not Graded",
comments=None,
submission=None,
):
if frappe.session.user == "Guest": if frappe.session.user == "Guest":
return return
args = { if submission:
"doctype": "LMS Assignment Submission", doc = frappe.get_doc("LMS Assignment Submission", submission)
"member": frappe.session.user,
"assignment": assignment,
}
if frappe.db.exists(args):
del args["doctype"]
frappe.db.set_value(
"LMS Assignment Submission", args, "assignment_attachment", assignment_attachment
)
return frappe.db.get_value("LMS Assignment Submission", args, "name")
else: else:
args.update({"assignment_attachment": assignment_attachment}) doc = frappe.get_doc(
doc = frappe.get_doc(args) {
doc.save(ignore_permissions=True) "doctype": "LMS Assignment Submission",
return doc.name "assignment": assignment,
"lesson": lesson,
"member": frappe.session.user,
}
)
print(doc.assignment)
print(comments)
doc.update(
{
"assignment_attachment": assignment_attachment,
"status": status,
"comments": comments,
}
)
doc.save(ignore_permissions=True)
return doc.name
@frappe.whitelist() @frappe.whitelist()

View File

@@ -1916,6 +1916,10 @@ li {
justify-content: flex-end !important; justify-content: flex-end !important;
} }
.modal-footer .btn-primary {
margin-left: 0.5rem
}
.modal-header .modal-title { .modal-header .modal-title {
color: var(--gray-900); color: var(--gray-900);
line-height: 1.5rem; line-height: 1.5rem;

View File

@@ -16,25 +16,32 @@
<header class="sticky mb-5"> <header class="sticky mb-5">
<div class="container form-width"> <div class="container form-width">
<div class="edit-header"> <div class="edit-header">
<div class="vertically-center"> <div>
<div class="page-title"> <div class="vertically-center">
{{ assignment.title }} <div class="page-title">
{{ assignment.title }}
</div>
{% if submission.status %}
{% set color = "green" if submission.status == "Pass" else "red" if submission.status == "Fail" else "orange" %}
<div class="indicator-pill {{ color }} ml-2">
{{ submission.status }}
</div>
{% endif %}
</div> </div>
{% if submission.status %} <div class="vertically-center small">
{% set color = "green" if submission.status == "Pass" else "red" if submission.status == "Fail" else "orange" %} <a class="dark-links" href="/classes">
<div class="indicator-pill {{ color }} ml-2"> {{ _("All Classes") }}
{{ submission.status }} </a>
</div> </div>
{% endif %}
</div> </div>
{% if submission.status == "Not Graded" %}
<div class="align-self-center"> <div class="align-self-center">
<button class="btn btn-primary btn-sm btn-save-assignment" {% if assignment.name %} data-assignment="{{ assignment.name }}" {% endif %}> <button class="btn btn-primary btn-sm btn-save-assignment" {% if assignment.name %} data-assignment="{{ assignment.name }}" {% endif %}
{% if submission.name %} data-submission="{{ submission.name }}" {% endif %}>
{{ _("Save") }} {{ _("Save") }}
</button> </button>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
</header> </header>
@@ -42,17 +49,19 @@
{% macro SubmissionForm(assignment) %} {% macro SubmissionForm(assignment) %}
<article class="field-parent"> <article class="field-parent">
{% if submission.name and is_moderator %}
<div class="field-group"> <div class="field-group">
<div class="field-label"> <div class="field-label">
{{ _("Student") }} {{ _("Student Name") }}
</div> </div>
{{ submission.member_name }} {{ submission.member_name }}
</div> </div>
{% endif %}
<div class="field-group"> <div class="field-group">
<!-- <div class="field-label"> <div class="field-label">
{{ _("Question")}} {{ _("Question")}}
</div> --> </div>
{{ assignment.question }} {{ assignment.question }}
</div> </div>
@@ -64,18 +73,61 @@
{{ _("Upload assignment as {0}").format(assignment.type) }} {{ _("Upload assignment as {0}").format(assignment.type) }}
</div> </div>
<div class="file-source-preview">
{% if submission.status == "Not Graded" and submission.member == frappe.session.user %} <div class="btn btn-default btn-sm btn-upload mt-2 {% if submission.assignment_attachment %} hide {% endif %}" data-type="{{ assignment.type }}">
<span class="btn btn-default btn-sm btn-close"> {{ _("Browse").format(assignment.type) }}
{{ _("Clear") }} </div>
<div class="field-input flex justify-between align-center {% if not submission.assignment_attachment %} hide {% endif %}" id="assignment-preview">
<a class="clickable" {% if submission.assignment_attachment %} href="{{ submission.assignment_attachment }}" {% endif %}>
{% if submission.assignment_attachment %} {{ submission.assignment_attachment }} {% endif %}
</a>
<span class="btn btn-default btn-sm btn-close {% if not submission %} hide {% endif %}">
{{ _("Clear") }}
</span> </span>
{% endif %}
<div class="btn-upload clickable {% if submission.assignment_attachment %} hide {% endif %}" data-type="{{ assignment.type }}">
{{ _("Browse").format(assignment.type) }}
</div>
<iframe class="image-preview {% if not submission.assignment_attachment %} hide {% endif %}" {% if submission.assignment_attachment %} src="{{ submission.assignment_attachment }}" {% endif %}></iframe>
</div> </div>
</div> </div>
{% if is_moderator %}
<div class="field-group">
<div class="field-label">
{{ _("Status") }}
</div>
<div class="field-input flex align-center">
<select class="form-control" id="status">
{% set statuses = ["Not Graded", "Pass", "Fail"] %}
{% for status in statuses %}
<option value="{{ status }}" {% if submission.status == status %} selected {% endif %}>
{{ status }}
</option>
{% endfor %}
</select>
<div class="select-icon">
<svg class="icon icon-sm">
<use class="" href="#icon-select"></use>
</svg>
</div>
</div>
</div>
<div class="field-group">
<div class="field-label">
{{ _("Comments by Mentor") }}
</div>
<textarea id="comments" type="text" class="field-input" height="300px"
>{% if submission.comments %}{{ submission.comments }}{% endif %}</textarea>
</div>
{% endif %}
{% if submission and submission.member == frappe.session.user and submission.comments %}
<div class="field-group">
<div class="field-label">
{{ _("Comments by Mentor") }}
</div>
<div>
{{ submission.comments }}
</div>
</div>
{% endif %}
</article> </article>
{% endmacro %} {% endmacro %}

View File

@@ -15,10 +15,15 @@ frappe.ready(() => {
const upload_file = (e) => { const upload_file = (e) => {
let type = $(e.currentTarget).data("type"); let type = $(e.currentTarget).data("type");
let mapper = { let mapper = {
Image: "image/*", Image: ["image/*"],
Document: Document: [
".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".doc",
PDF: ".pdf", ".docx",
".xml",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
],
PDF: [".pdf"],
}; };
new frappe.ui.FileUploader({ new frappe.ui.FileUploader({
@@ -26,20 +31,23 @@ const upload_file = (e) => {
folder: "Home/Attachments", folder: "Home/Attachments",
make_attachments_public: true, make_attachments_public: true,
restrictions: { restrictions: {
allowed_file_types: [mapper[type]], allowed_file_types: mapper[type],
}, },
on_success: (file_doc) => { on_success: (file_doc) => {
$(e.currentTarget).addClass("hide"); $(e.currentTarget).addClass("hide");
$(".file-source-preview .btn-close").removeClass("hide"); $("#assignment-preview").removeClass("hide");
$(".file-source-preview iframe") $("#assignment-preview .btn-close").removeClass("hide");
.attr("src", file_doc.file_url) $("#assignment-preview a").attr(
.removeClass("hide"); "href",
encodeURI(file_doc.file_url)
);
$("#assignment-preview a").text(file_doc.file_url);
}, },
}); });
}; };
const save_assignment = (e) => { const save_assignment = (e) => {
let file = $(".image-preview").attr("src"); let file = $("#assignment-preview a").attr("href");
if (!file) { if (!file) {
frappe.throw({ frappe.throw({
title: __("No File"), title: __("No File"),
@@ -51,7 +59,10 @@ const save_assignment = (e) => {
method: "lms.lms.doctype.lms_assignment_submission.lms_assignment_submission.upload_assignment", method: "lms.lms.doctype.lms_assignment_submission.lms_assignment_submission.upload_assignment",
args: { args: {
assignment: $(e.currentTarget).data("assignment"), assignment: $(e.currentTarget).data("assignment"),
submission: $(e.currentTarget).data("submission") || "",
assignment_attachment: file, assignment_attachment: file,
status: $("#status").val(),
comments: $("#comments").val(),
}, },
callback: (data) => { callback: (data) => {
frappe.show_alert({ frappe.show_alert({
@@ -68,7 +79,8 @@ const save_assignment = (e) => {
}; };
const clear_preview = (e) => { const clear_preview = (e) => {
$(".file-source-preview .btn-upload").removeClass("hide"); $(".btn-upload").removeClass("hide");
$(".file-source-preview iframe").attr("src", "").addClass("hide"); $("#assignment-preview").addClass("hide");
$(".file-source-preview .btn-close").addClass("hide"); $("#assignment-preview a").attr("href", "");
$("#assignment-preview .btn-close").addClass("hide");
}; };

View File

@@ -25,5 +25,5 @@ def get_context(context):
if not context.is_moderator and frappe.session.user != context.submission.member: if not context.is_moderator and frappe.session.user != context.submission.member:
raise frappe.PermissionError(_("You don't have permission to access this page.")) raise frappe.PermissionError(_("You don't have permission to access this page."))
if not context.assignment or not context.submission: if not context.assignment or not context.submission:
raise frappe.PermissionError(_("Invalid Submission URL")) raise frappe.PermissionError(_("Invalid Submission URL"))

View File

@@ -263,7 +263,7 @@
{{ _("To create a new assignment for this class, click on the create assignment button. Once you have created the new assignment you can come back to the class and add the assignment from here.") }} {{ _("To create a new assignment for this class, click on the create assignment button. Once you have created the new assignment you can come back to the class and add the assignment from here.") }}
</p> </p>
<div> <div>
<a class="btn btn-default btn-sm" href="/assignments/new-assignment" target="_blank"> <a class="btn btn-default btn-sm" href="/assignments/new-assignment">
{{ _("Create Assignment") }} {{ _("Create Assignment") }}
</a> </a>
</div> </div>
@@ -322,7 +322,7 @@
{% if assessments | length %} {% if assessments | length %}
<div> <div>
<div class="list-row level level-left small"> <div class="list-row level level-left small">
<div class="w-50"> <div class="w-25">
{{ _("Title") }} {{ _("Title") }}
</div> </div>
<div class=""> <div class="">
@@ -331,7 +331,7 @@
</div> </div>
{% for assessment in assessments %} {% for assessment in assessments %}
<div class="list-row level level-left"> <div class="list-row level level-left">
<div class="w-50"> <div class="w-25">
<a class="clickable" href="{{ assessment.edit_url }}"> <a class="clickable" href="{{ assessment.edit_url }}">
{{ assessment.title }} {{ assessment.title }}
</a> </a>

View File

@@ -8,7 +8,7 @@
<div class="container"> <div class="container">
{{ Header() }} {{ Header() }}
{% if past_classes | length or upcoming_classes | length %} {% if past_classes | length or upcoming_classes | length %}
{{ ClassTabs(past_classes, upcoming_classes) }} {{ ClassTabs(past_classes, upcoming_classes, my_classes) }}
{% else %} {% else %}
{{ EmptyState() }} {{ EmptyState() }}
{% endif %} {% endif %}
@@ -27,7 +27,7 @@
</header> </header>
{% endmacro %} {% endmacro %}
{% macro ClassTabs(past_classes, upcoming_classes) %} {% macro ClassTabs(past_classes, upcoming_classes, my_classes) %}
<article> <article>
<ul class="nav lms-nav" id="courses-tab"> <ul class="nav lms-nav" id="courses-tab">
@@ -40,6 +40,7 @@
</a> </a>
</li> </li>
{% if is_moderator %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#past"> <a class="nav-link" data-toggle="tab" href="#past">
{{ _("Past Classes") }} {{ _("Past Classes") }}
@@ -48,6 +49,18 @@
</span> </span>
</a> </a>
</li> </li>
{% endif %}
{% if frappe.session.user != "Guest" %}
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#my-class">
{{ _("My Classes") }}
<span class="course-list-count">
{{ my_classes | length }}
</span>
</a>
</li>
{% endif %}
</ul> </ul>
@@ -58,9 +71,17 @@
{{ ClassCards(upcoming_classes) }} {{ ClassCards(upcoming_classes) }}
</div> </div>
{% if is_moderator %}
<div class="tab-pane" id="past" role="tabpanel" aria-labelledby="past"> <div class="tab-pane" id="past" role="tabpanel" aria-labelledby="past">
{{ ClassCards(past_classes) }} {{ ClassCards(past_classes) }}
</div> </div>
{% endif %}
{% if frappe.session.user != "Guest" %}
<div class="tab-pane" id="my-class" role="tabpanel" aria-labelledby="my-classes">
{{ ClassCards(my_classes) }}
</div>
{% endif %}
</div> </div>
</article> </article>

View File

@@ -20,5 +20,24 @@ def get_context(context):
upcoming_classes.append(class_) upcoming_classes.append(class_)
context.past_classes = sorted(past_classes, key=lambda d: d.start_date) context.past_classes = sorted(past_classes, key=lambda d: d.start_date)
context.upcoming_classes = sorted(upcoming_classes, key=lambda d: d.start_date) context.upcoming_classes = sorted(upcoming_classes, key=lambda d: d.start_date)
if frappe.session.user != "Guest":
my_classes_info = []
my_classes = frappe.get_all(
"Class Student", {"student": frappe.session.user}, pluck="parent"
)
for class_ in my_classes:
my_classes_info.append(
frappe.db.get_value(
"LMS Class",
class_,
["name", "title", "start_date", "end_date", "paid_class", "seat_count"],
as_dict=True,
)
)
context.my_classes = my_classes_info
print(context.my_classes)

View File

@@ -8,7 +8,7 @@
<div class="common-page-style"> <div class="common-page-style">
{{ Header() }} {{ Header() }}
<div class="container form-width"> <div class="container form-width">
{{ Progress() }} {{ Progress(class_info, student) }}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
@@ -50,7 +50,7 @@
<div> <div>
{% for assessment in assessments %} {% for assessment in assessments %}
<div class="list-row level"> <div class="list-row level">
<a {% if assessment.submission %} class="clickable" href="{{ assessment.url }}" {% endif %}> <a {% if is_moderator and assessment.submission or frappe.session.user == student.name %} class="clickable" href="{{ assessment.url }}" {% endif %}>
{{ assessment.title }} {{ assessment.title }}
</a> </a>