chore: removed obsolete doctype LMS Topic
It has been replaced by Chapter and Lesson. Moved the section_parser from lms_topic directory to the lms.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from ..lms_topic.section_parser import SectionParser
|
from ...section_parser import SectionParser
|
||||||
|
|
||||||
class Lesson(Document):
|
class Lesson(Document):
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
|
|||||||
@@ -35,17 +35,6 @@ class LMSCourse(Document):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Course#{self.name}>"
|
return f"<Course#{self.name}>"
|
||||||
|
|
||||||
def get_topic(self, slug):
|
|
||||||
"""Returns the topic with given slug in this course as a Document.
|
|
||||||
"""
|
|
||||||
result = frappe.get_all(
|
|
||||||
"LMS Topic",
|
|
||||||
filters={"course": self.name, "slug": slug})
|
|
||||||
|
|
||||||
if result:
|
|
||||||
row = result[0]
|
|
||||||
return frappe.get_doc('LMS Topic', row['name'])
|
|
||||||
|
|
||||||
def has_mentor(self, email):
|
def has_mentor(self, email):
|
||||||
"""Checks if this course has a mentor with given email.
|
"""Checks if this course has a mentor with given email.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('LMS Topic', {
|
|
||||||
// refresh: function(frm) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"allow_guest_to_view": 1,
|
|
||||||
"creation": "2021-03-02 07:20:41.686573",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"course",
|
|
||||||
"title",
|
|
||||||
"slug",
|
|
||||||
"preview",
|
|
||||||
"description",
|
|
||||||
"order",
|
|
||||||
"sections"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "description",
|
|
||||||
"fieldtype": "Markdown Editor",
|
|
||||||
"label": "Description"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "course",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Course",
|
|
||||||
"options": "LMS Course",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "order",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"label": "Order"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "preview",
|
|
||||||
"fieldtype": "Markdown Editor",
|
|
||||||
"label": "Preview"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "sections",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "Sections",
|
|
||||||
"options": "LMS Section"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "The slug of the topic. Autogenerated from the title if not specified.",
|
|
||||||
"fieldname": "slug",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Slug"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2021-04-06 14:12:48.514062",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "LMS",
|
|
||||||
"name": "LMS Topic",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "System Manager",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"search_fields": "title",
|
|
||||||
"sort_field": "creation",
|
|
||||||
"sort_order": "ASC",
|
|
||||||
"title_field": "title",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 1,
|
|
||||||
"track_views": 1
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2021, FOSS United and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
from .section_parser import SectionParser
|
|
||||||
from ...utils import slugify
|
|
||||||
|
|
||||||
class LMSTopic(Document):
|
|
||||||
def before_save(self):
|
|
||||||
course = self.get_course()
|
|
||||||
if not self.slug:
|
|
||||||
self.slug = self.generate_slug(title=self.title)
|
|
||||||
|
|
||||||
sections = SectionParser().parse(self.description or "")
|
|
||||||
self.sections = [self.make_lms_section(i, s) for i, s in enumerate(sections)]
|
|
||||||
|
|
||||||
def get_course(self):
|
|
||||||
return frappe.get_doc("LMS Course", self.course)
|
|
||||||
|
|
||||||
def generate_slug(self, title):
|
|
||||||
result = frappe.get_all(
|
|
||||||
'LMS Topic',
|
|
||||||
filters={'course': self.course},
|
|
||||||
fields=['slug'])
|
|
||||||
slugs = set([row['slug'] for row in result])
|
|
||||||
return slugify(title, used_slugs=slugs)
|
|
||||||
|
|
||||||
def get_sections(self):
|
|
||||||
return sorted(self.sections, key=lambda s: s.index)
|
|
||||||
|
|
||||||
def make_lms_section(self, index, section):
|
|
||||||
s = frappe.new_doc('LMS Section', parent_doc=self, parentfield='sections')
|
|
||||||
s.type = section.type
|
|
||||||
s.label = section.label
|
|
||||||
s.contents = section.contents
|
|
||||||
s.index = index
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2021, FOSS United and Contributors
|
|
||||||
# See license.txt
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
class TestLMSTopic(unittest.TestCase):
|
|
||||||
pass
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
{% extends "templates/base.html" %}
|
|
||||||
{% from "www/macros/livecode.html" import LiveCodeEditor with context %}
|
|
||||||
{% block title %}{{topic.title}} ({{course.title}}){% endblock %}
|
|
||||||
{% block head_include %}
|
|
||||||
<meta name="description" content="Topic {{topic.title}} of the course {{course.title}}" />
|
|
||||||
<meta name="keywords" content="course {{course.title}} {{topic.title}}" />
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{ livecode_url }}/static/codemirror/lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="/assets/css/lms.css">
|
|
||||||
|
|
||||||
<script src="{{ livecode_url }}/static/codemirror/lib/codemirror.js"></script>
|
|
||||||
<script src="{{ livecode_url }}/static/codemirror/mode/python/python.js"></script>
|
|
||||||
<script src="{{ livecode_url }}/static/codemirror/keymap/sublime.js"></script>
|
|
||||||
|
|
||||||
<script src="{{ livecode_url }}/static/codemirror/addon/edit/matchbrackets.js"></script>
|
|
||||||
<script src="{{ livecode_url }}/static/codemirror/addon/comment/comment.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section class="top-section" style="padding: 1rem 0rem;">
|
|
||||||
<div class='container pb-5'>
|
|
||||||
<nav aria-label="breadcrumb">
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
<li class="breadcrumb-item" aria-current="page"><a href="/courses">Courses</a></li>
|
|
||||||
<li class="breadcrumb-item" aria-current="page"><a href="/courses/{{course.slug}}">{{course.title}}</a></li>
|
|
||||||
</ol>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<h1>{{ topic.title }}</h1>
|
|
||||||
|
|
||||||
{% for s in topic.get_sections() %}
|
|
||||||
<div class="section section-{{ s.type }}">
|
|
||||||
{{ render_section(s) }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% macro render_section(s) %}
|
|
||||||
{% if s.type == "text" %}
|
|
||||||
{{ render_section_text(s) }}
|
|
||||||
{% elif s.type == "example" or s.type == "code" %}
|
|
||||||
{{ LiveCodeEditor(s.name, s.get_latest_code_for_user()) }}
|
|
||||||
{% else %}
|
|
||||||
<div>Unknown section type: {{s.type}}</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_section_text(s) %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-9">
|
|
||||||
{{ frappe.utils.md_to_html(s.contents) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{%- block script %}
|
|
||||||
{{ super() }}
|
|
||||||
<script type="text/javascript" src="{{ livecode_url }}/static/livecode.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
var editorLookup = {};
|
|
||||||
|
|
||||||
$(".canvas-editor").each((i, e) => {
|
|
||||||
var data = $(e).data();
|
|
||||||
var editor = new LiveCodeEditor(e, {
|
|
||||||
runtime: "python-canvas",
|
|
||||||
base_url: "{{ livecode_url }}",
|
|
||||||
codemirror: true,
|
|
||||||
userdata: data,
|
|
||||||
autosave: function(editor, code) {
|
|
||||||
// can't autosave when user is Guest
|
|
||||||
if (frappe.session.user == "Guest") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var data = editor.options.userdata;
|
|
||||||
var code = editor.codemirror.doc.getValue();
|
|
||||||
// console.log("autosaving...")
|
|
||||||
frappe.call("community.lms.api.autosave_section", {
|
|
||||||
section: data.section,
|
|
||||||
code: code
|
|
||||||
}).then((r) => {
|
|
||||||
// TODO: verify
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
editorLookup[data.section] = editor;
|
|
||||||
})
|
|
||||||
|
|
||||||
$(".canvas-editor .reset").each((i, e) => {
|
|
||||||
$(e).on("click", function(event) {
|
|
||||||
var data = $(this).parents(".canvas-editor").data();
|
|
||||||
var section = data.section;
|
|
||||||
frappe.call("community.lms.api.get_section", {
|
|
||||||
name: section
|
|
||||||
}).then(r => {
|
|
||||||
var editor = editorLookup[data.section];
|
|
||||||
editor.codemirror.doc.setValue(r.message.contents);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{%- endblock %}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import frappe
|
|
||||||
|
|
||||||
def get_context(context):
|
|
||||||
context.no_cache = 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
course_slug = frappe.form_dict['course']
|
|
||||||
topic_slug = frappe.form_dict['topic']
|
|
||||||
except KeyError:
|
|
||||||
context.template = 'www/404.html'
|
|
||||||
return
|
|
||||||
|
|
||||||
course = get_course(course_slug)
|
|
||||||
topic = course and course.get_topic(topic_slug)
|
|
||||||
|
|
||||||
if not topic:
|
|
||||||
context.template = 'www/404.html'
|
|
||||||
return
|
|
||||||
|
|
||||||
context.course = course
|
|
||||||
context.topic = topic
|
|
||||||
context.livecode_url = get_livecode_url()
|
|
||||||
|
|
||||||
def notfound(context):
|
|
||||||
context.template = 'www/404.html'
|
|
||||||
|
|
||||||
def get_livecode_url():
|
|
||||||
doc = frappe.get_doc("LMS Settings")
|
|
||||||
return doc.livecode_url
|
|
||||||
|
|
||||||
def get_course(slug):
|
|
||||||
course = frappe.db.get_value('LMS Course', {"slug": slug}, ["name"], as_dict=1)
|
|
||||||
return course and frappe.get_doc('LMS Course', course['name'])
|
|
||||||
Reference in New Issue
Block a user