refactor: assignments
This commit is contained in:
@@ -13,11 +13,16 @@
|
||||
"column_break_4",
|
||||
"title",
|
||||
"include_in_preview",
|
||||
"included_in_course",
|
||||
"index_label",
|
||||
"section_break_6",
|
||||
"youtube",
|
||||
"column_break_9",
|
||||
"quiz_id",
|
||||
"section_break_16",
|
||||
"question",
|
||||
"column_break_15",
|
||||
"file_type",
|
||||
"section_break_11",
|
||||
"body",
|
||||
"help_section",
|
||||
@@ -105,11 +110,41 @@
|
||||
"fieldname": "youtube",
|
||||
"fieldtype": "Data",
|
||||
"label": "YouTube Video URL"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "included_in_course",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Included in Course",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_16",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Assignment"
|
||||
},
|
||||
{
|
||||
"description": "Assignment will appear at the bottom of the lesson.",
|
||||
"fieldname": "question",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Question"
|
||||
},
|
||||
{
|
||||
"fieldname": "file_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "File Type",
|
||||
"mandatory_depends_on": "question",
|
||||
"options": "Image\nDocument\nPDF"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2022-09-02 11:30:15.450624",
|
||||
"modified": "2022-10-28 12:36:01.978640",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Course Lesson",
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"lesson",
|
||||
"user",
|
||||
"column_break_3",
|
||||
"assignment",
|
||||
"id"
|
||||
"lesson",
|
||||
"course",
|
||||
"column_break_3",
|
||||
"member",
|
||||
"member_name"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -21,32 +22,39 @@
|
||||
"label": "Lesson",
|
||||
"options": "Course Lesson"
|
||||
},
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "User",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "id",
|
||||
"fieldtype": "Data",
|
||||
"label": "ID"
|
||||
},
|
||||
{
|
||||
"fieldname": "assignment",
|
||||
"fieldtype": "Attach",
|
||||
"label": "Assignment"
|
||||
},
|
||||
{
|
||||
"fieldname": "member",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Member",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fetch_from": "member.full_name",
|
||||
"fieldname": "member_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Member Name"
|
||||
},
|
||||
{
|
||||
"fetch_from": "lesson.course",
|
||||
"fieldname": "course",
|
||||
"fieldtype": "Data",
|
||||
"label": "Course"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-12-22 11:17:08.390615",
|
||||
"modified": "2022-10-28 12:38:05.541906",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Lesson Assignment",
|
||||
@@ -66,5 +74,6 @@
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -5,16 +5,17 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.handler import upload_file
|
||||
|
||||
|
||||
class LessonAssignment(Document):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload_assignment(assignment, lesson, identifier):
|
||||
def upload_assignment(assignment, lesson):
|
||||
args = {
|
||||
"doctype": "Lesson Assignment",
|
||||
"lesson": lesson,
|
||||
"user": frappe.session.user,
|
||||
"id": identifier
|
||||
"member": frappe.session.user
|
||||
}
|
||||
if frappe.db.exists(args):
|
||||
del args["doctype"]
|
||||
@@ -24,18 +25,17 @@ def upload_assignment(assignment, lesson, identifier):
|
||||
lesson_work = frappe.get_doc(args)
|
||||
lesson_work.save(ignore_permissions=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_assignment(lesson):
|
||||
assignments = frappe.get_all("Lesson Assignment",
|
||||
{
|
||||
assignment = frappe.db.get_value("Lesson Assignment", {
|
||||
"lesson": lesson,
|
||||
"user": frappe.session.user
|
||||
},
|
||||
["lesson", "user", "id", "assignment"])
|
||||
if len(assignments):
|
||||
for assignment in assignments:
|
||||
assignment.file_name = frappe.db.get_value("File", {"file_url": assignment.assignment}, "file_name")
|
||||
return assignments
|
||||
"member": frappe.session.user
|
||||
}, ["lesson", "member", "assignment"],
|
||||
as_dict=True)
|
||||
print(assignment)
|
||||
assignment.file_name = frappe.db.get_value("File", {"file_url": assignment.assignment}, "file_name")
|
||||
return assignment
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ def save_chapter(course, title, chapter_description, idx, chapter):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def save_lesson(title, body, chapter, preview, idx, lesson, youtube=None, quiz_id=None):
|
||||
def save_lesson(title, body, chapter, preview, idx, lesson, youtube=None, quiz_id=None, question=None, file_type=None):
|
||||
if lesson:
|
||||
doc = frappe.get_doc("Course Lesson", lesson)
|
||||
else:
|
||||
@@ -284,7 +284,9 @@ def save_lesson(title, body, chapter, preview, idx, lesson, youtube=None, quiz_i
|
||||
"body": body,
|
||||
"include_in_preview": preview,
|
||||
"youtube": youtube,
|
||||
"quiz_id": quiz_id
|
||||
"quiz_id": quiz_id,
|
||||
"question": question,
|
||||
"file_type": file_type
|
||||
})
|
||||
doc.save(ignore_permissions=True)
|
||||
|
||||
|
||||
@@ -100,8 +100,10 @@ def get_lesson_details(chapter):
|
||||
order_by="idx")
|
||||
|
||||
for row in lesson_list:
|
||||
lesson_details = frappe.db.get_value("Course Lesson", row.lesson,
|
||||
["name", "title", "include_in_preview", "body", "creation", "youtube", "quiz_id"], as_dict=True)
|
||||
lesson_details = frappe.db.get_value("Course Lesson",
|
||||
row.lesson,
|
||||
["name", "title", "include_in_preview", "body", "creation", "youtube", "quiz_id", "question", "unique_id", "file_type"],
|
||||
as_dict=True)
|
||||
lesson_details.number = flt("{}.{}".format(chapter.idx, row.idx))
|
||||
lesson_details.icon = "icon-list"
|
||||
macros = find_macros(lesson_details.body)
|
||||
@@ -244,13 +246,22 @@ def get_progress(course, lesson):
|
||||
["status"])
|
||||
|
||||
|
||||
def render_html(body, youtube, quiz_id):
|
||||
def render_html(lesson):
|
||||
youtube = lesson.youtube
|
||||
quiz_id = lesson.quiz_id
|
||||
body = lesson.body
|
||||
|
||||
if youtube and "/" in youtube:
|
||||
youtube = youtube.split("/")[-1]
|
||||
|
||||
quiz_id = "{{ Quiz('" + quiz_id + "') }}" if quiz_id else ""
|
||||
youtube = "{{ YouTubeVideo('" + youtube + "') }}" if youtube else ""
|
||||
text = youtube + body + quiz_id
|
||||
|
||||
if lesson.question:
|
||||
assignment = "{{ Assignment('" + lesson.question + "-" + lesson.file_type + "') }}"
|
||||
text = text + assignment
|
||||
|
||||
return markdown_to_html(text)
|
||||
|
||||
|
||||
|
||||
@@ -151,9 +151,10 @@ def assignment_renderer(detail):
|
||||
"Image": ".png, .jpg, .jpeg",
|
||||
"Video": "video/*"
|
||||
}
|
||||
question = detail.split("-")[0]
|
||||
file_type = detail.split("-")[1]
|
||||
accept = supported_types[file_type] if file_type else ""
|
||||
return frappe.render_template("templates/assignment.html", {"id": detail.split("-")[0], "accept": accept})
|
||||
return frappe.render_template("templates/assignment.html", {"question": question, "accept": accept})
|
||||
|
||||
def show_custom_signup():
|
||||
if (frappe.db.get_single_value("LMS Settings", "terms_of_use")
|
||||
|
||||
@@ -1126,8 +1126,7 @@ pre {
|
||||
}
|
||||
|
||||
.preview-work {
|
||||
width: 50%;
|
||||
justify-content: space-between;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.job-card {
|
||||
@@ -1778,3 +1777,25 @@ li {
|
||||
.course-description-section {
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
input::file-selector-button {
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--text-md);
|
||||
padding: 0.25rem 1.25rem;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input::file-selector-button:hover {
|
||||
background-color: var(--gray-400);
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<div class="form-group">
|
||||
<div class="d-flex">
|
||||
<input class="btn btn-default btn-sm mr-3 attach-file" type="file" id="{{ id }}" accept="{{ accept }}" />
|
||||
<div class="button is-secondary submit-work">{{ _("Submit Work") }}</div>
|
||||
<div class="preview-work button is-default hide">
|
||||
<a target="_blank"></a>
|
||||
<div class="button is-secondary clear-work">{{ _("Change") }}</div>
|
||||
<div class="">
|
||||
<h3> {{ _("Assignment") }} </h3>
|
||||
<div class="my-3"> {{ _(question) }} </div>
|
||||
<input class="btn btn-default btn-sm border attach-file" type="file" accept="{{ accept }}" />
|
||||
<div class="btn btn-secondary ml-2 submit-work">{{ _("Submit") }}</div>
|
||||
<div class="preview-work small hide">
|
||||
<a target="_blank"></a>
|
||||
<div class="btn btn-secondary btn-sm ml-2 clear-work">{{ _("Change") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
{% if lesson.edit_mode %}
|
||||
{{ EditLesson(lesson) }}
|
||||
{% else %}
|
||||
{{ render_html(lesson.body, lesson.youtube, lesson.quiz_id) }}
|
||||
{{ render_html(lesson) }}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
@@ -171,11 +171,30 @@
|
||||
<!-- Edit Lesson -->
|
||||
{% macro EditLesson(lesson) %}
|
||||
|
||||
<div class="medium mt-2" contenteditable="true" data-placeholder="{{ _('YouTube Video ID') }}"
|
||||
id="youtube">{% if lesson.youtube %}{{ lesson.youtube }}{% endif %}</div>
|
||||
<div class="d-flex mt-2 medium">
|
||||
<div class="flex-grow-1" contenteditable="true" data-placeholder="{{ _('YouTube Video ID') }}"
|
||||
id="youtube">{% if lesson.youtube %}{{ lesson.youtube }}{% endif %}</div>
|
||||
|
||||
<div class="flex-grow-1 ml-2" contenteditable="true" data-placeholder="{{ _('Quiz ID') }}"
|
||||
id="quiz-id">{% if lesson.quiz_id %}{{ lesson.quiz_id }}{% endif %}</div>
|
||||
</div>
|
||||
|
||||
<div id="body" {% if lesson.body %} data-body="{{ lesson.body }}" {% endif %}></div>
|
||||
<div class="medium mb-4" contenteditable="true" data-placeholder="{{ _('Quiz ID') }}"
|
||||
id="quiz-id">{% if lesson.quiz_id %}{{ lesson.quiz_id }}{% endif %}</div>
|
||||
|
||||
<div class="d-flex medium mx-0 mb-4">
|
||||
<div class="flex-grow-1" contenteditable="true" data-placeholder="{{ _('Assignment Question') }}"
|
||||
id="assignment-question">{% if lesson.question %}{{ lesson.question }}{% endif %}</div>
|
||||
|
||||
<select class="btn btn-default ml-2" id="file-type" data-type="{{ lesson.file_type }}">
|
||||
<option selected> {{ _("File Type") }} </option>
|
||||
<option value="Image"> {{ _("Image") }} </option>
|
||||
<option value="Document"> {{ _("Document") }} </option>
|
||||
<option value="PDF"> {{ _("PDF") }} </option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="preview" for="preview">
|
||||
<input {% if lesson.include_in_preview %} checked {% endif %} type="checkbox" id="preview">
|
||||
|
||||
@@ -2,6 +2,8 @@ frappe.ready(() => {
|
||||
|
||||
this.marked_as_complete = false;
|
||||
this.quiz_submitted = false;
|
||||
this.file_type;
|
||||
let self = this;
|
||||
|
||||
localStorage.removeItem($("#quiz-title").data("name"));
|
||||
|
||||
@@ -9,6 +11,8 @@ frappe.ready(() => {
|
||||
|
||||
save_current_lesson();
|
||||
|
||||
set_file_type();
|
||||
|
||||
$(".option").click((e) => {
|
||||
enable_check(e);
|
||||
});
|
||||
@@ -77,7 +81,6 @@ frappe.ready(() => {
|
||||
});
|
||||
|
||||
if ($("#quiz-title").data("max-attempts")) {
|
||||
let self = this;
|
||||
window.addEventListener("beforeunload", (e) => {
|
||||
e.returnValue = "";
|
||||
if ($(".active-question").length && !self.quiz_submitted) {
|
||||
@@ -89,6 +92,12 @@ frappe.ready(() => {
|
||||
if ($("#body").length) {
|
||||
make_editor();
|
||||
}
|
||||
|
||||
$("#file-type").change((e) => {
|
||||
$("#file-type option:selected" ).each(function() {
|
||||
self.file_type = $(this).val();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -318,8 +327,7 @@ const upload_file = (file, target) => {
|
||||
|
||||
let form_data = new FormData();
|
||||
if (file.file_obj) {
|
||||
form_data.append('file', file.file_obj, `${frappe.session.user}-${file.name}`);
|
||||
form_data.append('folder', `${$(".title").attr("data-lesson")} ${$(".title").attr("data-course")}`)
|
||||
form_data.append('file', file.file_obj, file.name);
|
||||
}
|
||||
|
||||
xhr.send(form_data);
|
||||
@@ -333,7 +341,6 @@ const create_lesson_work = (file, target) => {
|
||||
args: {
|
||||
assignment: file.file_url,
|
||||
lesson: $(".title").attr("data-lesson"),
|
||||
identifier: target.siblings(".attach-file").attr("id")
|
||||
},
|
||||
callback: (data) => {
|
||||
target.siblings(".attach-file").addClass("hide");
|
||||
@@ -398,17 +405,15 @@ const fetch_assignments = () => {
|
||||
"lesson": $(".title").attr("data-lesson")
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message && data.message.length) {
|
||||
const assignments = data.message;
|
||||
for (let i in assignments) {
|
||||
let target = $(`#${assignments[i]["id"]}`);
|
||||
if (data.message) {
|
||||
const assignment = data.message;
|
||||
let target = $(".attach-file");
|
||||
target.addClass("hide");
|
||||
target.siblings(".submit-work").addClass("hide");
|
||||
target.siblings(".preview-work").removeClass("hide");
|
||||
target.siblings(".preview-work").find("a").attr("href", assignments[i]["assignment"]).text(assignments[i]["file_name"]);
|
||||
target.siblings(".preview-work").find("a").attr("href", assignment.assignment).text(assignment.file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -449,6 +454,7 @@ const calculate_and_display_time = (percent_time) => {
|
||||
|
||||
const save_lesson = (e) => {
|
||||
let lesson = $("#title").data("lesson");
|
||||
let self = this;
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.save_lesson",
|
||||
args: {
|
||||
@@ -459,7 +465,9 @@ const save_lesson = (e) => {
|
||||
"chapter": $("#title").data("chapter"),
|
||||
"preview": $("#preview").prop("checked") ? 1 : 0,
|
||||
"idx": $("#title").data("index"),
|
||||
"lesson": lesson ? lesson : ""
|
||||
"lesson": lesson ? lesson : "",
|
||||
"question": $("#assignment-question").text(),
|
||||
"file_type": self.file_type
|
||||
},
|
||||
callback: (data) => {;
|
||||
frappe.show_alert({
|
||||
@@ -531,3 +539,15 @@ const make_editor = () => {
|
||||
$("#body .frappe-control").removeClass("hide-control");
|
||||
$("#body .form-column").addClass("p-0");
|
||||
};
|
||||
|
||||
|
||||
const set_file_type = () => {
|
||||
let file_type = $("#file-type").data("type");
|
||||
if (file_type) {
|
||||
$("#file-type option").each((i, elem) => {
|
||||
if ($(elem).val() == file_type) {
|
||||
$(elem).attr("selected", true);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user