Merge branch 'new-editor' of https://github.com/pateljannat/lms into new-design-system
This commit is contained in:
@@ -145,6 +145,10 @@ website_route_rules = [
|
|||||||
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
|
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
|
||||||
"to_route": "batch/learn",
|
"to_route": "batch/learn",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>/edit",
|
||||||
|
"to_route": "batch/edit",
|
||||||
|
},
|
||||||
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
|
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
|
||||||
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
|
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
|
||||||
{"from_route": "/classes/<classname>", "to_route": "classes/class"},
|
{"from_route": "/classes/<classname>", "to_route": "classes/class"},
|
||||||
|
|||||||
@@ -157,3 +157,22 @@ def authenticate():
|
|||||||
}
|
}
|
||||||
response = requests.request("POST", authenticate_url, headers=headers)
|
response = requests.request("POST", authenticate_url, headers=headers)
|
||||||
return response.json()["access_token"]
|
return response.json()["access_token"]
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def create_class(title, start_date, end_date, description=None, name=None):
|
||||||
|
if name:
|
||||||
|
class_details = frappe.get_doc("LMS Class", name)
|
||||||
|
else:
|
||||||
|
class_details = frappe.get_doc({"doctype": "LMS Class"})
|
||||||
|
|
||||||
|
class_details.update(
|
||||||
|
{
|
||||||
|
"title": title,
|
||||||
|
"start_date": start_date,
|
||||||
|
"end_date": end_date,
|
||||||
|
"description": description,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
class_details.save()
|
||||||
|
return class_details
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ def find_macros(text):
|
|||||||
if not text:
|
if not text:
|
||||||
return []
|
return []
|
||||||
macros = re.findall(MACRO_RE, text)
|
macros = re.findall(MACRO_RE, text)
|
||||||
|
print(macros)
|
||||||
# remove the quotes around the argument
|
# remove the quotes around the argument
|
||||||
return [(name, _remove_quotes(arg)) for name, arg in macros]
|
return [(name, _remove_quotes(arg)) for name, arg in macros]
|
||||||
|
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ def get_progress(course, lesson):
|
|||||||
|
|
||||||
|
|
||||||
def render_html(lesson):
|
def render_html(lesson):
|
||||||
|
print(lesson)
|
||||||
youtube = lesson.youtube
|
youtube = lesson.youtube
|
||||||
quiz_id = lesson.quiz_id
|
quiz_id = lesson.quiz_id
|
||||||
body = lesson.body
|
body = lesson.body
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
frappe.ready(function () {
|
|
||||||
// bind events here
|
|
||||||
});
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
{
|
|
||||||
"accept_payment": 0,
|
|
||||||
"allow_comments": 0,
|
|
||||||
"allow_delete": 0,
|
|
||||||
"allow_edit": 0,
|
|
||||||
"allow_incomplete": 0,
|
|
||||||
"allow_multiple": 0,
|
|
||||||
"allow_print": 0,
|
|
||||||
"amount": 0.0,
|
|
||||||
"amount_based_on_field": 0,
|
|
||||||
"apply_document_permissions": 0,
|
|
||||||
"button_label": "Save",
|
|
||||||
"creation": "2022-11-11 12:10:29.640675",
|
|
||||||
"custom_css": "",
|
|
||||||
"doc_type": "LMS Class",
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Web Form",
|
|
||||||
"idx": 0,
|
|
||||||
"is_standard": 1,
|
|
||||||
"list_columns": [],
|
|
||||||
"login_required": 0,
|
|
||||||
"max_attachment_size": 0,
|
|
||||||
"modified": "2022-11-21 10:56:01.627821",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "LMS",
|
|
||||||
"name": "class",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"payment_button_label": "Buy Now",
|
|
||||||
"published": 1,
|
|
||||||
"route": "class",
|
|
||||||
"show_attachments": 0,
|
|
||||||
"show_list": 0,
|
|
||||||
"show_sidebar": 0,
|
|
||||||
"success_title": "",
|
|
||||||
"success_url": "/classes",
|
|
||||||
"title": "Class",
|
|
||||||
"web_form_fields": [
|
|
||||||
{
|
|
||||||
"allow_read_on_all_link_options": 0,
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "Title",
|
|
||||||
"max_length": 0,
|
|
||||||
"max_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"show_in_filter": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_read_on_all_link_options": 0,
|
|
||||||
"fieldname": "start_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "Start Date",
|
|
||||||
"max_length": 0,
|
|
||||||
"max_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"show_in_filter": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_read_on_all_link_options": 0,
|
|
||||||
"fieldname": "end_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "End Date",
|
|
||||||
"max_length": 0,
|
|
||||||
"max_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"show_in_filter": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_read_on_all_link_options": 0,
|
|
||||||
"fieldname": "description",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "Description",
|
|
||||||
"max_length": 0,
|
|
||||||
"max_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"show_in_filter": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import frappe
|
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
|
||||||
# do your magic here
|
|
||||||
pass
|
|
||||||
@@ -51,4 +51,5 @@ lms.patches.v0_0.rename_exercise_doctype
|
|||||||
lms.patches.v0_0.add_question_type #09-04-2023
|
lms.patches.v0_0.add_question_type #09-04-2023
|
||||||
lms.patches.v0_0.add_evaluator_to_assignment #09-04-2023
|
lms.patches.v0_0.add_evaluator_to_assignment #09-04-2023
|
||||||
lms.patches.v0_0.convert_lesson_markdown_to_html #05-04-2023
|
lms.patches.v0_0.convert_lesson_markdown_to_html #05-04-2023
|
||||||
lms.patches.v0_0.convert_course_description_to_html
|
lms.patches.v0_0.convert_course_description_to_html
|
||||||
|
execute:frappe.delete_doc("Web Form", "class", ignore_missing=True, force=True)
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ def youtube_video_renderer(video_id):
|
|||||||
|
|
||||||
|
|
||||||
def video_renderer(src):
|
def video_renderer(src):
|
||||||
|
print(src)
|
||||||
return f"<video controls width='100%'><source src={src} type='video/mp4'></video>"
|
return f"<video controls width='100%'><source src={src} type='video/mp4'></video>"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2048,7 +2048,7 @@ select {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.common-page-style .tooltip-content {
|
.tooltip-content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ frappe.ready(() => {
|
|||||||
$(".chapter-dropzone").each((i, el) => {
|
$(".chapter-dropzone").each((i, el) => {
|
||||||
setSortable(el);
|
setSortable(el);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#create-class").click((e) => {
|
||||||
|
open_class_dialog(e);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const setSortable = (el) => {
|
const setSortable = (el) => {
|
||||||
@@ -385,3 +389,68 @@ const reorder_chapter = (e) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const open_class_dialog = (e) => {
|
||||||
|
this.class_dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("New Class"),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
fieldtype: "Data",
|
||||||
|
label: __("Title"),
|
||||||
|
fieldname: "title",
|
||||||
|
reqd: 1,
|
||||||
|
default: class_info && class_info.title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Date",
|
||||||
|
label: __("Start Date"),
|
||||||
|
fieldname: "start_date",
|
||||||
|
reqd: 1,
|
||||||
|
default: class_info && class_info.start_date,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Date",
|
||||||
|
label: __("End Date"),
|
||||||
|
fieldname: "end_date",
|
||||||
|
reqd: 1,
|
||||||
|
default: class_info && class_info.end_date,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Small Text",
|
||||||
|
label: __("Description"),
|
||||||
|
fieldname: "description",
|
||||||
|
default: class_info && class_info.description,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
primary_action_label: __("Save"),
|
||||||
|
primary_action: (values) => {
|
||||||
|
create_class(values);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.class_dialog.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
const create_class = (values) => {
|
||||||
|
frappe.call({
|
||||||
|
method: "lms.lms.doctype.lms_class.lms_class.create_class",
|
||||||
|
args: {
|
||||||
|
title: values.title,
|
||||||
|
start_date: values.start_date,
|
||||||
|
end_date: values.end_date,
|
||||||
|
description: values.description,
|
||||||
|
name: class_info && class_info.name,
|
||||||
|
},
|
||||||
|
callback: (r) => {
|
||||||
|
if (r.message) {
|
||||||
|
frappe.show_alert({
|
||||||
|
message: class_info
|
||||||
|
? __("Class Updated")
|
||||||
|
: __("Class Created"),
|
||||||
|
indicator: "green",
|
||||||
|
});
|
||||||
|
this.class_dialog.hide();
|
||||||
|
window.location.href = `/classes/${r.message.name}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
5
lms/public/js/editor.js
Normal file
5
lms/public/js/editor.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import EditorJS from "@editorjs/editorjs";
|
||||||
|
|
||||||
|
const editor = new EditorJS("body");
|
||||||
|
|
||||||
|
console.log(editor);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
import "./profile.js";
|
import "./profile.js";
|
||||||
import "./common_functions.js";
|
import "./common_functions.js";
|
||||||
|
import "./editor.js";
|
||||||
import "../../../../frappe/frappe/public/js/frappe/ui/chart.js";
|
import "../../../../frappe/frappe/public/js/frappe/ui/chart.js";
|
||||||
|
|||||||
25
lms/www/batch/edit.html
Normal file
25
lms/www/batch/edit.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% extends "lms/templates/lms_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% if lesson.title %}
|
||||||
|
{{ lesson.title }} - {{ course.title }}
|
||||||
|
{% else %}
|
||||||
|
{{ _("New Lesson") }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<div class="">
|
||||||
|
<div>
|
||||||
|
{{ _("Title") }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ _("Something short and concise.") }}
|
||||||
|
</div>
|
||||||
|
<input class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
10
lms/www/batch/edit.py
Normal file
10
lms/www/batch/edit.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import frappe
|
||||||
|
from lms.www.utils import get_current_lesson_details, get_common_context
|
||||||
|
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
get_common_context(context)
|
||||||
|
chapter_index = frappe.form_dict.get("chapter")
|
||||||
|
lesson_index = frappe.form_dict.get("lesson")
|
||||||
|
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||||
|
context.lesson = get_current_lesson_details(lesson_number, context)
|
||||||
@@ -593,7 +593,7 @@ const build_attachment_table = (file_doc) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const make_editor = () => {
|
const make_editor = () => {
|
||||||
this.code_field_group = new frappe.ui.FieldGroup({
|
/* this.code_field_group = new frappe.ui.FieldGroup({
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: "code_md",
|
fieldname: "code_md",
|
||||||
@@ -606,7 +606,7 @@ const make_editor = () => {
|
|||||||
this.code_field_group.make();
|
this.code_field_group.make();
|
||||||
$("#body .form-section:last").removeClass("empty-section");
|
$("#body .form-section:last").removeClass("empty-section");
|
||||||
$("#body .frappe-control").removeClass("hide-control");
|
$("#body .frappe-control").removeClass("hide-control");
|
||||||
$("#body .form-column").addClass("p-0");
|
$("#body .form-column").addClass("p-0"); */
|
||||||
};
|
};
|
||||||
|
|
||||||
const set_file_type = () => {
|
const set_file_type = () => {
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ from frappe import _
|
|||||||
from frappe.utils import cstr, flt
|
from frappe.utils import cstr, flt
|
||||||
|
|
||||||
from lms.lms.utils import get_lesson_url, has_course_moderator_role, is_instructor
|
from lms.lms.utils import get_lesson_url, has_course_moderator_role, is_instructor
|
||||||
from lms.www.utils import get_common_context, redirect_to_lesson
|
from lms.www.utils import (
|
||||||
|
get_common_context,
|
||||||
|
redirect_to_lesson,
|
||||||
|
get_current_lesson_details,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
@@ -62,20 +66,6 @@ def get_context(context):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_current_lesson_details(lesson_number, context):
|
|
||||||
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
|
||||||
|
|
||||||
if not len(details_list):
|
|
||||||
if frappe.form_dict.get("edit"):
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
redirect_to_lesson(context.course)
|
|
||||||
|
|
||||||
lesson_info = details_list[0]
|
|
||||||
lesson_info.body = lesson_info.body.replace('"', "'")
|
|
||||||
return lesson_info
|
|
||||||
|
|
||||||
|
|
||||||
def get_url(lesson_number, course):
|
def get_url(lesson_number, course):
|
||||||
return (
|
return (
|
||||||
get_lesson_url(course.name, lesson_number)
|
get_lesson_url(course.name, lesson_number)
|
||||||
|
|||||||
@@ -61,6 +61,11 @@
|
|||||||
<!-- Class Sections -->
|
<!-- Class Sections -->
|
||||||
{% macro ClassSections(class_info, class_courses, class_students, published_courses) %}
|
{% macro ClassSections(class_info, class_courses, class_students, published_courses) %}
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm pull-right" id="create-class">
|
||||||
|
{{ _("Edit") }}
|
||||||
|
</button>
|
||||||
|
|
||||||
<ul class="nav lms-nav" id="classes-tab">
|
<ul class="nav lms-nav" id="classes-tab">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" data-toggle="tab" href="#courses">
|
<a class="nav-link active" data-toggle="tab" href="#courses">
|
||||||
@@ -280,7 +285,6 @@
|
|||||||
|
|
||||||
{%- block script %}
|
{%- block script %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
{% if is_moderator %}
|
{% if is_moderator %}
|
||||||
<script>
|
<script>
|
||||||
frappe.boot.user = {
|
frappe.boot.user = {
|
||||||
@@ -294,6 +298,7 @@
|
|||||||
return name.toLowerCase().replace(/ /g, "-");
|
return name.toLowerCase().replace(/ /g, "-");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let class_info = {{ class_info | json }};
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="common-page-style lms-page-style">
|
<div class="common-page-style lms-page-style">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% if has_course_moderator_role() %}
|
{% if is_moderator %}
|
||||||
<a class="btn btn-secondary btn-sm pull-right" href="/class/new">
|
<button class="btn btn-secondary btn-sm pull-right" id="create-class">
|
||||||
{{ _("Create Class") }}
|
{{ _("Create Class") }}
|
||||||
</a>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="course-home-headings"> {{ _("All Classes") }} </div>
|
<div class="course-home-headings"> {{ _("All Classes") }} </div>
|
||||||
{% if classes %}
|
{% if classes %}
|
||||||
@@ -27,6 +27,15 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- block script %}
|
||||||
|
{{ super() }}
|
||||||
|
{{ include_script('controls.bundle.js') }}
|
||||||
|
{% if is_moderator %}
|
||||||
|
<script>
|
||||||
|
let class_info = null;
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% macro ClassCards(classes) %}
|
{% macro ClassCards(classes) %}
|
||||||
<div class="lms-card-parent">
|
<div class="lms-card-parent">
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
from lms.lms.utils import has_course_moderator_role
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
context.no_cache = 1
|
context.no_cache = 1
|
||||||
|
context.is_moderator = has_course_moderator_role()
|
||||||
context.classes = frappe.get_all(
|
context.classes = frappe.get_all(
|
||||||
"LMS Class",
|
"LMS Class",
|
||||||
{"end_date": [">=", getdate()]},
|
{"end_date": [">=", getdate()]},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
from lms.lms.utils import get_lesson_url, get_lessons, get_membership
|
from lms.lms.utils import get_lesson_url, get_lessons, get_membership
|
||||||
|
from frappe.utils import cstr
|
||||||
|
|
||||||
|
|
||||||
def get_common_context(context):
|
def get_common_context(context):
|
||||||
@@ -40,3 +41,17 @@ def redirect_to_lesson(course, index_="1.1"):
|
|||||||
get_lesson_url(course.name, index_) + course.query_parameter
|
get_lesson_url(course.name, index_) + course.query_parameter
|
||||||
)
|
)
|
||||||
raise frappe.Redirect
|
raise frappe.Redirect
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_lesson_details(lesson_number, context):
|
||||||
|
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
||||||
|
|
||||||
|
if not len(details_list):
|
||||||
|
if frappe.form_dict.get("edit"):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
redirect_to_lesson(context.course)
|
||||||
|
|
||||||
|
lesson_info = details_list[0]
|
||||||
|
lesson_info.body = lesson_info.body.replace('"', "'")
|
||||||
|
return lesson_info
|
||||||
|
|||||||
Reference in New Issue
Block a user