diff --git a/community/hooks.py b/community/hooks.py index 0c21b608..3ace5ad7 100644 --- a/community/hooks.py +++ b/community/hooks.py @@ -136,6 +136,7 @@ primary_rules = [ {"from_route": "/hackathons//", "to_route": "hackathons/project"}, {"from_route": "/dashboard", "to_route": ""}, {"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"}, + {"from_route": "/courses///home", "to_route": "batch/home"}, {"from_route": "/courses///learn", "to_route": "batch/learn"}, {"from_route": "/courses///learn/.", "to_route": "batch/learn"}, {"from_route": "/courses///schedule", "to_route": "batch/schedule"}, diff --git a/community/lms/doctype/exercise/test_exercise.py b/community/lms/doctype/exercise/test_exercise.py index 8ae68e96..c68f3212 100644 --- a/community/lms/doctype/exercise/test_exercise.py +++ b/community/lms/doctype/exercise/test_exercise.py @@ -14,7 +14,9 @@ class TestExercise(unittest.TestCase): course = frappe.get_doc({ "doctype": "LMS Course", "name": "test-course", - "title": "Test Course" + "title": "Test Course", + "short_introduction": "Test Course", + "description": "Test Course" }) course.insert() e = frappe.get_doc({ diff --git a/community/lms/doctype/lms_batch/lms_batch.json b/community/lms/doctype/lms_batch/lms_batch.json index 6eb5056e..1783be8f 100644 --- a/community/lms/doctype/lms_batch/lms_batch.json +++ b/community/lms/doctype/lms_batch/lms_batch.json @@ -6,11 +6,10 @@ "engine": "InnoDB", "field_order": [ "course", - "title", "start_date", "start_time", "column_break_3", - "code", + "title", "sessions_on", "end_time", "section_break_5", @@ -31,13 +30,6 @@ "label": "Course", "options": "LMS Course" }, - { - "fieldname": "code", - "fieldtype": "Data", - "label": "Code", - "read_only": 1, - "unique": 1 - }, { "fieldname": "title", "fieldtype": "Data", @@ -84,7 +76,8 @@ }, { "fieldname": "section_break_5", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "label": "Batch Description" }, { "fieldname": "column_break_9", @@ -92,7 +85,8 @@ }, { "fieldname": "section_break_7", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "label": "Batch Settings" }, { "fieldname": "start_date", @@ -126,7 +120,7 @@ "link_fieldname": "batch" } ], - "modified": "2021-05-06 05:46:38.469120", + "modified": "2021-05-26 16:43:57.399747", "modified_by": "Administrator", "module": "LMS", "name": "LMS Batch", diff --git a/community/lms/doctype/lms_batch/lms_batch.py b/community/lms/doctype/lms_batch/lms_batch.py index 6be6e6e6..185134ae 100644 --- a/community/lms/doctype/lms_batch/lms_batch.py +++ b/community/lms/doctype/lms_batch/lms_batch.py @@ -12,8 +12,6 @@ from community.query import find, find_all class LMSBatch(Document): def validate(self): self.validate_if_mentor() - if not self.code: - self.generate_code() def validate_if_mentor(self): course = frappe.get_doc("LMS Course", self.course) @@ -23,11 +21,6 @@ class LMSBatch(Document): def after_insert(self): create_membership(batch=self.name, member_type="Mentor") - def generate_code(self): - short_code = frappe.db.get_value("LMS Course", self.course, "short_code") - course_batches = frappe.get_all("LMS Batch",{"course":self.course}) - self.code = short_code + str(len(course_batches) + 1) - def get_mentors(self): memberships = frappe.get_all( "LMS Batch Membership", @@ -87,6 +80,11 @@ class LMSBatch(Document): membership = self.get_membership(user) return membership and membership.current_lesson + def get_learn_url(self, lesson_number): + if not lesson_number: + return + return f"/courses/{self.course}/{self.name}/learn/{lesson_number}" + @frappe.whitelist() def save_message(message, batch): doc = frappe.get_doc({ diff --git a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py index fe563a63..7d714d46 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py @@ -34,7 +34,7 @@ class LMSBatchMembership(Document): "member": self.member, "name": ["!=", self.name] }, - fields=["batch", "member_type"] + fields=["batch", "member_type", "name"] ) for membership in previous_membership: diff --git a/community/lms/doctype/lms_batch_membership/test_lms_batch_membership.py b/community/lms/doctype/lms_batch_membership/test_lms_batch_membership.py index c0385c17..0463e9a6 100644 --- a/community/lms/doctype/lms_batch_membership/test_lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/test_lms_batch_membership.py @@ -19,7 +19,9 @@ class TestLMSBatchMembership(unittest.TestCase): "doctype": "LMS Course", "name": "test-course", "title": "Test Course", - "short_code": "XX" + "short_code": "XX", + "short_introduction": "Test Course", + "description": "Test Course" }) course.insert() diff --git a/community/lms/doctype/lms_course/lms_course.json b/community/lms/doctype/lms_course/lms_course.json index 9ec683b6..41f4de73 100644 --- a/community/lms/doctype/lms_course/lms_course.json +++ b/community/lms/doctype/lms_course/lms_course.json @@ -28,7 +28,8 @@ { "fieldname": "description", "fieldtype": "Markdown Editor", - "label": "Description" + "label": "Description", + "reqd": 1 }, { "default": "0", @@ -57,7 +58,8 @@ { "fieldname": "short_introduction", "fieldtype": "Small Text", - "label": "Short Introduction" + "label": "Short Introduction", + "reqd": 1 } ], "index_web_pages_for_search": 1, @@ -84,7 +86,7 @@ "link_fieldname": "course" } ], - "modified": "2021-05-06 13:37:03.318829", + "modified": "2021-05-23 18:14:32.602647", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", diff --git a/community/lms/doctype/lms_course/test_lms_course.py b/community/lms/doctype/lms_course/test_lms_course.py index 69e78484..db17c8de 100644 --- a/community/lms/doctype/lms_course/test_lms_course.py +++ b/community/lms/doctype/lms_course/test_lms_course.py @@ -15,7 +15,9 @@ class TestLMSCourse(unittest.TestCase): def new_course(self, title): doc = frappe.get_doc({ "doctype": "LMS Course", - "title": title + "title": title, + "short_introduction": title, + "description": title }) doc.insert() return doc diff --git a/community/lms/doctype/lms_message/lms_message.py b/community/lms/doctype/lms_message/lms_message.py index f19d80ea..b190c210 100644 --- a/community/lms/doctype/lms_message/lms_message.py +++ b/community/lms/doctype/lms_message/lms_message.py @@ -18,7 +18,7 @@ class LMSMessage(Document): template = self.get_message_template() message = frappe._dict({ "author_name": self.author_name, - "message_time": frappe.utils.pretty_date(self.creation), + "message_time": frappe.utils.format_datetime(self.creation, "dd-mm-yyyy HH:mm"), "message": frappe.utils.md_to_html(self.message) }) @@ -32,26 +32,28 @@ class LMSMessage(Document): template = frappe.render_template(template, {{ "message": message }}) - $(".message-section").append(template); + $(".messages").append(template); + var message_element = document.getElementsByClassName("messages")[0] + message_element.scrollTo(0, message_element.scrollHeight); """.format(template, message, self.owner) frappe.publish_realtime(event="eval_js", message=js, after_commit=True) def get_message_template(self): return """ -
+
  • {{ message.author_name }}
    -
    + {{ message.message_time }} +
    -
    -
    +
    {{ message.message }}
    -
    +
  • """ def send_email(self): @@ -106,4 +108,3 @@ def send_daily_digest(): }, delayed = False ) - diff --git a/community/lms/widgets/BatchHeader.html b/community/lms/widgets/BatchHeader.html new file mode 100644 index 00000000..a6c99cdc --- /dev/null +++ b/community/lms/widgets/BatchHeader.html @@ -0,0 +1,4 @@ +
    +

    {{batch_name}}

    +
    {{member_count}} members
    +
    diff --git a/community/lms/widgets/BatchTabs.html b/community/lms/widgets/BatchTabs.html new file mode 100644 index 00000000..48378660 --- /dev/null +++ b/community/lms/widgets/BatchTabs.html @@ -0,0 +1,39 @@ +
    + Courses /{% if course.is_mentor(frappe.session.user) %} {{ course.title }} {% else %} {{ course.title }} {% endif %} +
    + + diff --git a/community/lms/widgets/ChapterTeaser.html b/community/lms/widgets/ChapterTeaser.html index c80d1a55..49f3af78 100644 --- a/community/lms/widgets/ChapterTeaser.html +++ b/community/lms/widgets/ChapterTeaser.html @@ -1,14 +1,14 @@
    -

    {{index}} {{ chapter.title }}

    +

    {{index}}. {{ chapter.title }}

    {{ chapter.description or "" }}
    {% for lesson in chapter.get_lessons() %} -
    - {{lesson.title}} -
    + {% endfor %}
    diff --git a/community/lms/widgets/CourseOutline.html b/community/lms/widgets/CourseOutline.html new file mode 100644 index 00000000..9dd26835 --- /dev/null +++ b/community/lms/widgets/CourseOutline.html @@ -0,0 +1,5 @@ +

    Course Outline

    + +{% for chapter in course.get_chapters() %} +{{ widgets.ChapterTeaser(index=loop.index, chapter=chapter, course=course, batch=batch, show_link=show_link)}} +{% endfor %} diff --git a/community/lms/widgets/InstructorSection.html b/community/lms/widgets/InstructorSection.html new file mode 100644 index 00000000..d7634b65 --- /dev/null +++ b/community/lms/widgets/InstructorSection.html @@ -0,0 +1,5 @@ +

    Instructor

    +
    +
    {{instructor.full_name}}
    +
    Created {{instructor.get_course_count()}} courses
    +
    diff --git a/community/public/css/style.css b/community/public/css/style.css index 65c9b48b..b97c3996 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -97,14 +97,6 @@ body { border-top: 1px solid #ddc; } -.batch .cta button { - background: var(--cta-color); - color: white; - border: none; - border-radius: 5px; - padding: 5px 10px; -} - .batch .right { float: right; } @@ -127,44 +119,13 @@ img.profile-photo { max-width: 100% } - -/* override style of base */ - .message { border: 1px dashed var(--text-color); padding: 20px; border-radius: 10px; } -.dashboard__profile { - width: 150px; - height: 155px; - border-radius: 50%; -} - -.dashboard__profileSmall { - width: 59px; - height: 57px; - border-radius: 50%; -} - -.dashboard__abbr { - font-size: 50px; - width: 155px; - height: 155px; - border-radius: 50%; -} - -.dashboard__abbrSmall { - font-size: 20px; - width: 59px; - height: 57px; - border-radius: 50%; -} - .msger-inputarea { - position: fixed; - bottom: 0; width: 100%; display: flex; padding: 10px; @@ -182,37 +143,6 @@ img.profile-photo { flex: 1; background: #ddd; } -.msger-send-btn { - margin-left: 10px; - background: var(--cta-color); - color: #fff; - font-weight: bold; - cursor: pointer; - transition: background 0.23s; -} - -.discussion { - border: 1px solid var(--text-color); - padding: 10px; - margin: 10px; - border-radius: 10px; - background: var(--received-message); - width: 50%; - display: flex; - flex-direction: column; -} - -.is-author { - float: right; - background: var(--send-message); -} - -.batch-header { - position: fixed; - top: 0; - background: var(--bg); - width: 100%; -} .message-section { margin-left: 3%; @@ -227,6 +157,57 @@ img.profile-photo { } .anchor_style { + color: inherit; +} + +a:hover { text-decoration: none; color: inherit; } + +.anchor_style:hover { + text-decoration: underline +} + +section { + padding: 5rem 0 5rem 0; +} + +.messages-container { + margin: 0 auto; + border: 1px solid black; +} + +.messages { + overflow: auto; + height: 450px; + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 8px; + list-style-type: none; +} + +.messages li { + background: #F7F5F5; + border-radius: 8px; + padding: 8px; + margin: 2px 8px 2px 0; + width: 40%; +} + +.messages li.ours { + align-self: flex-end; + margin: 2px 0 2px 8px; + background: var(--primary-color); + color: #fff +} + +.message-para { + font-size: 20px; +} + +.batch-header { + background: #eee; + border: 2px solid #ddd; +} diff --git a/community/public/css/style.less b/community/public/css/style.less index dc8f2d31..f95f643c 100644 --- a/community/public/css/style.less +++ b/community/public/css/style.less @@ -179,11 +179,8 @@ section.lightgray { .chapter-number { background: var(--text-color); color: white; - border-radius: 50%; height: 24px; min-width: 24px; - align-items: center; - padding: 5px 8px 2px 8px; margin-right: 5px; } @@ -288,9 +285,7 @@ section.lightgray { } .lesson-teaser { - font-weight: bold; - color: black; - padding-left: 20px; + line-height: 35px; } #hero h1 { diff --git a/community/public/images/wallpaper.png b/community/public/images/wallpaper.png new file mode 100644 index 00000000..95b06d7e Binary files /dev/null and b/community/public/images/wallpaper.png differ diff --git a/community/www/batch/about.html b/community/www/batch/about.html index 4edabaef..132bf8a0 100644 --- a/community/www/batch/about.html +++ b/community/www/batch/about.html @@ -1,7 +1,4 @@ {% extends "templates/base.html" %} -{% from "www/macros/sidebar.html" import Sidebar %} -{% from "www/macros/common_macro.html" import InstructorsSection, MentorsSection %} - {% block title %}About{% endblock %} {% block head_include %} @@ -11,48 +8,33 @@ {% endblock %} {% block content %} -{{ Sidebar(course, batch) }} -
    - {{ CourseBasicDetail(course)}} - {{ InstructorsSection(course.get_instructor()) }} - {{ BatchDetails(batch)}} + {{ widgets.BatchTabs(course=course, batch=batch) }} +
    + {{ CourseBasicDetail(course)}} +
    +
    + +
    +
    +
    {% endblock %} {% macro CourseBasicDetail(course) %}

    {{course.title}}

    - {{course.short_introduction}} + {{course.short_introduction}}
    {% if course.video_link %}
    - +
    {% endif %}

    About the Course

    {{frappe.utils.md_to_html(course.description)}}
    {% endmacro %} - -{% macro BatchDetails(batch) %} -

    About the Batch

    - -
    -
    -
    Session every {{batch.sessions_on}}
    -
    {{frappe.utils.format_time(batch.start_time, "short")}} - - {{frappe.utils.format_time(batch.end_time, "short")}}
    -
    Starting {{frappe.utils.format_date(batch.start_date, "medium")}}
    -
    mentors
    - - {% for m in batch.get_mentors() %} -
    - {{ widgets.Avatar(member=m, avatar_class="avatar-medium" ) }} - {{m.full_name}} -
    - {% endfor %} -
    -
    -{% endmacro %} diff --git a/community/www/batch/about.py b/community/www/batch/about.py index b847d8c8..48be81c9 100644 --- a/community/www/batch/about.py +++ b/community/www/batch/about.py @@ -3,5 +3,3 @@ from . import utils def get_context(context): utils.get_common_context(context) - - print("context", context) diff --git a/community/www/batch/discuss.html b/community/www/batch/discuss.html index 31cf1813..a31b0f92 100644 --- a/community/www/batch/discuss.html +++ b/community/www/batch/discuss.html @@ -1,6 +1,4 @@ {% extends "templates/base.html" %} -{% from "www/macros/sidebar.html" import Sidebar %} -{% from "www/macros/common_macro.html" import BatchHearder %} {% block title %}Discuss{% endblock %} {% block head_include %} @@ -11,16 +9,14 @@ {% endblock %} {% block content %} -{{ Sidebar(course, batch) }} -
    -
    - {{ BatchHearder(course.title, member_count) }} -
    -
    -
    +
    + {{ widgets.BatchTabs(course=course, batch=batch) }} +
    + {{ widgets.BatchHeader(batch_name=batch.title, member_count=member_count)}} +
      {{ Messages(messages) }} -
    + {{ TextArea() }}
    @@ -28,25 +24,25 @@ {% macro Messages(messages) %} {% for message in messages %} -
    +
  • {{ message.author_name }}
    -
    - {{ frappe.utils.pretty_date(message.creation) }} -
    + + {{ frappe.utils.format_datetime(message.creation, "dd-mm-yyyy HH:mm") }} +
    -
    +
    {{ message.message }}
    -
    +
  • {% endfor %} {% endmacro %} {% macro TextArea() %} -
    + - +
    {% endmacro %} diff --git a/community/www/batch/discuss.js b/community/www/batch/discuss.js index 74f435c1..4a3adc80 100644 --- a/community/www/batch/discuss.js +++ b/community/www/batch/discuss.js @@ -11,7 +11,9 @@ frappe.ready(() => { }) setTimeout(() => { - window.scrollTo(0, document.body.scrollHeight); + var message_element = document.getElementsByClassName("messages")[0] + message_element.scrollTo(0, message_element.scrollHeight); + document.getElementsByClassName("messages-container")[0].scrollIntoView({block: "center"}) }, 300); $(".msger-send-btn").click((e) => { diff --git a/community/www/batch/home.html b/community/www/batch/home.html new file mode 100644 index 00000000..3b98e3fb --- /dev/null +++ b/community/www/batch/home.html @@ -0,0 +1,46 @@ +{% extends "templates/base.html" %} +{% block title %}Batch{% endblock %} +{% block head_include %} + + + + +{% endblock %} + +{% block content %} +
    + {{ widgets.BatchTabs(course=course, batch=batch) }} +

    {{ batch.title }}

    +
    + {{ widgets.CourseOutline(course=course, batch=batch, show_link=True) }} +
    +
    +

    Batch Schedule

    + {{ BatchDetails(batch) }} +
    +

    Batch Details

    + {{ frappe.utils.md_to_html(batch.description) }} + + +
    +{% endblock %} + +{% macro BatchDetails(batch) %} +
    +
    +
    Session every {{batch.sessions_on}}
    +
    {{frappe.utils.format_time(batch.start_time, "short")}} - + {{frappe.utils.format_time(batch.end_time, "short")}} +
    +
    Starting {{frappe.utils.format_date(batch.start_date, "medium")}}
    +
    mentors
    + + {% for m in batch.get_mentors() %} +
    + {{ widgets.Avatar(member=m, avatar_class="avatar-medium" ) }} + {{m.full_name}} +
    + {% endfor %} +
    +
    +{% endmacro %} diff --git a/community/www/batch/home.py b/community/www/batch/home.py new file mode 100644 index 00000000..48be81c9 --- /dev/null +++ b/community/www/batch/home.py @@ -0,0 +1,5 @@ +import frappe +from . import utils + +def get_context(context): + utils.get_common_context(context) diff --git a/community/www/batch/learn.html b/community/www/batch/learn.html index 19699202..36136ddb 100644 --- a/community/www/batch/learn.html +++ b/community/www/batch/learn.html @@ -1,17 +1,17 @@ {% extends "templates/base.html" %} -{% from "www/macros/sidebar.html" import Sidebar %} {% from "www/macros/livecode.html" import LiveCodeEditorJS, LiveCodeEditor with context %} {% block title %}{{ lesson.title }}{% endblock %} {% block head_include %} - - - + + + + @@ -23,11 +23,10 @@ {% block content %} -{{ Sidebar(course, batch) }}
    + {{ widgets.BatchTabs(course=course, batch=batch) }}
    - {{ pagination(prev_url, next_url) }}

    {{ lesson.title }}

    @@ -37,52 +36,55 @@
    {% endfor %} - {{ pagination(prev_url, next_url) }} - + {{ pagination(prev_chap, prev_url, next_chap, next_url) }}
    {% endblock %} {% macro render_section(s) %} - {% if s.type == "text" %} - {{ render_section_text(s) }} - {% elif s.type == "example" or s.type == "code" %} - {{ LiveCodeEditor(s.name, +{% if s.type == "text" %} +{{ render_section_text(s) }} +{% elif s.type == "example" or s.type == "code" %} +{{ LiveCodeEditor(s.name, code=s.get_latest_code_for_user(), reset_code=s.contents, is_exercise=False) }} - {% elif s.type == "exercise" %} - {{ widgets.Exercise(exercise=s.get_exercise())}} - {% else %} -
    Unknown section type: {{s.type}}
    - {% endif %} +{% elif s.type == "exercise" %} +{{ widgets.Exercise(exercise=s.get_exercise())}} +{% else %} +
    Unknown section type: {{s.type}}
    +{% endif %} {% endmacro %} {% macro render_section_text(s) %} -
    -
    - {{ frappe.utils.md_to_html(s.contents) }} -
    +
    +
    + {{ frappe.utils.md_to_html(s.contents) }}
    +
    {% endmacro %} -{% macro pagination(prev_url, next_url) %} -
    - {% if prev_url %} - ← Prev - {% endif %} - {% if next_url %} - Next → - {% endif %} -
    -
    +{% macro pagination(prev_chap, prev_url, next_chap, next_url) %} +
    + {% if prev_url %} + + Prev: {{prev_chap}} + + {% endif %} + {% if next_url %} + + Next: {{next_chap}} + + {% endif %} +
    +
    {% endmacro %} {%- block script %} - {{ super() }} - {{ LiveCodeEditorJS() }} +{{ super() }} +{{ LiveCodeEditorJS() }}