fix: conflicts

This commit is contained in:
pateljannat
2021-09-21 12:38:43 +05:30
23 changed files with 116 additions and 35 deletions

View File

@@ -1,5 +1,6 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{####} {title}",
"creation": "2021-05-03 05:49:08.383057",
"doctype": "DocType",
@@ -38,7 +39,7 @@
"fieldname": "lessons",
"fieldtype": "Table",
"label": "Lessons",
"options": "Lessons"
"options": "Lesson Reference"
},
{
"fieldname": "column_break_3",
@@ -57,10 +58,11 @@
"link_fieldname": "chapter"
}
],
"modified": "2021-08-31 10:43:45.866864",
"modified": "2021-09-20 10:58:47.241660",
"modified_by": "Administrator",
"module": "LMS",
"name": "Chapter",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{

View File

@@ -23,7 +23,7 @@
"modified": "2021-07-27 16:25:02.903245",
"modified_by": "Administrator",
"module": "LMS",
"name": "Chapters",
"name": "Chapter Reference",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",

View File

@@ -4,5 +4,5 @@
# import frappe
from frappe.model.document import Document
class Lessons(Document):
class ChapterReference(Document):
pass

View File

@@ -1,5 +1,6 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{####} {title}",
"creation": "2021-05-03 06:21:12.995987",
"doctype": "DocType",
@@ -70,10 +71,11 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-31 10:44:14.168257",
"modified": "2021-09-20 10:52:29.116536",
"modified_by": "Administrator",
"module": "LMS",
"name": "Lesson",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{

View File

@@ -23,7 +23,7 @@
"modified": "2021-08-31 10:44:42.048232",
"modified_by": "Administrator",
"module": "LMS",
"name": "Lessons",
"name": "Lesson Reference",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",

View File

@@ -4,5 +4,5 @@
# import frappe
from frappe.model.document import Document
class Chapters(Document):
class LessonReference(Document):
pass

View File

@@ -100,7 +100,7 @@
"fieldname": "chapters",
"fieldtype": "Table",
"label": "Chapters",
"options": "Chapters"
"options": "Chapter Reference"
},
{
"fieldname": "instructor",
@@ -160,9 +160,14 @@
"group": "Mentors",
"link_doctype": "LMS Course Mentor Mapping",
"link_fieldname": "course"
},
{
"group": "Interests",
"link_doctype": "LMS Course Interest",
"link_fieldname": "course"
}
],
"modified": "2021-08-25 11:04:57.211898",
"modified": "2021-09-20 12:00:18.325579",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Course",

View File

@@ -176,7 +176,7 @@ class LMSCourse(Document):
def get_lesson_details(self, chapter):
lessons = []
lesson_list = frappe.get_all("Lessons", {"parent": chapter.name},
lesson_list = frappe.get_all("Lesson Reference", {"parent": chapter.name},
["lesson", "idx"], order_by="idx")
for row in lesson_list:
lesson_details = frappe.get_doc("Lesson", row.lesson)
@@ -213,7 +213,7 @@ class LMSCourse(Document):
def get_lesson_index(self, lesson_name):
"""Returns the {chapter_index}.{lesson_index} for the lesson.
"""
lesson = frappe.db.get_value("Lessons", {"lesson": lesson_name}, ["idx", "parent"], as_dict=True)
lesson = frappe.db.get_value("Lesson Reference", {"lesson": lesson_name}, ["idx", "parent"], as_dict=True)
if not lesson:
return None

View File

@@ -1,5 +1,6 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "field:title",
"creation": "2021-06-07 10:50:17.893625",
"doctype": "DocType",
@@ -33,10 +34,11 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-07-23 19:06:12.551633",
"modified": "2021-09-20 10:44:15.930892",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{

View File

@@ -21,7 +21,7 @@
<div class="lesson-info {% if membership.current_lesson == lesson.name %} active-lesson {% endif %}">
{% if membership or lesson.include_in_preview or is_instructor %}
{% if membership or lesson.include_in_preview %}
<a class="lesson-links" href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}">
{{ lesson.title }}
@@ -33,6 +33,15 @@
</a>
{% elif is_instructor and not lesson.include_in_preview %}
<a class="lesson-links"
title="This lesson is not available for preview but as an instructor you can access it."
href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}">
{{ lesson.title }}
<img class="ml-2" src="/assets/community/icons/lock.svg">
</a>
{% else %}
<div class="no-preview" title="This lesson is not available for preview">
<div class="lesson-links">

View File

@@ -1,16 +1,15 @@
{% if not course.upcoming %}
<div class="reviews-parent">
{% set reviews = course.get_reviews() %}
{% if reviews | length or course.is_eligible_to_review(membership) %}
<div class="mb-5">
<span class="course-home-headings">Reviews</span>
{% if course.is_eligible_to_review(membership) %}
{% if course.is_eligible_to_review(membership) and reviews | length %}
<span class="review-link button is-secondary pull-right">
Write a review
</span>
{% endif %}
</div>
{% endif %}
{% if reviews | length %}
<div class="reviews-section">
{% for review in reviews %}
@@ -36,9 +35,20 @@
</div>
{% endfor %}
</div>
{% else %}
<div class="common-card-style thread-card">
<span class="text-center"> No Reviews <img src="/assets/community/icons/slash.svg"></span>
<div class="w-25 text-center" style="margin: 0 auto;">
<span class="font-weight-bold"> No Reviews </span>
<div class="small">
There are no reviews for this course.
</div>
{% if course.is_eligible_to_review(membership) %}
<span class="review-link button is-secondary ml-auto mr-auto mt-3">
Write a review
</span>
{% endif %}
</div>
</div>
{% endif %}
</div>
@@ -48,7 +58,7 @@
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="course-home-headings modal-headings">Review</div>
<div class="font-weight-bold">Write a Review</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>

View File

@@ -18,6 +18,8 @@ class CustomUser(User):
else:
underscore_condition = ''
regex = re.compile('[@!#$%^&*()<>?/\|}{~:-]')
if self.is_new():
if not self.username:
self.username = self.get_username_from_first_name()
@@ -25,7 +27,7 @@ class CustomUser(User):
if self.username.find(" "):
self.username.replace(" ", "")
if not re.match("^[A-Za-z0-9_]*$", self.username) or underscore_condition:
if regex.search(self.username) or underscore_condition:
self.username = self.remove_illegal_characters()
if len(self.username) < 4:
@@ -38,8 +40,8 @@ class CustomUser(User):
if not self.username:
frappe.throw(_("Username already exists."))
if not re.match("^[A-Za-z0-9_]*$", self.username):
frappe.throw(_("Username can only contain alphabets, numbers and unedrscore."))
if regex.search(self.username):
frappe.throw(_("Username can only contain alphabets, numbers and underscore."))
if underscore_condition:
frappe.throw(_("First and Last character of username cannot be Underscore(_)."))

View File

@@ -31,7 +31,7 @@ def get_profile_url_prefix():
hooks = frappe.get_hooks("profile_url_prefix") or ["/users/"]
return hooks[-1]
RE_USERNAME = re.compile("[a-zA-Z0-9_]{4,}")
RE_INVALID_USERNAME = re.compile("[@!#$%^&*()<>?/\\|}{~:-]")
class ProfileRedirectPage(BaseRenderer):
"""Renderer to redirect /profile_/foo to <profile_prefix>/foo.
@@ -63,9 +63,8 @@ class ProfilePage(BaseRenderer):
# not a userpage?
username = self.get_username()
if not RE_USERNAME.match(username):
if RE_INVALID_USERNAME.search(username):
return False
# if there is prefix then we can allow all usernames
if prefix:
return True

View File

@@ -11,3 +11,4 @@ execute:frappe.delete_doc("DocType", "LMS Message")
community.patches.v0_0.course_instructor_update
execute:frappe.delete_doc("DocType", "Discussion Message")
execute:frappe.delete_doc("DocType", "Discussion Thread")
community.patches.v0_0.rename_chapters_and_lessons_doctype

View File

@@ -0,0 +1,32 @@
import frappe
def execute():
frappe.reload_doc("lms", "doctype", "lms_course")
frappe.reload_doc("lms", "doctype", "chapter")
frappe.reload_doc("lms", "doctype", "lesson")
frappe.reload_doc("lms", "doctype", "chapter_reference")
frappe.reload_doc("lms", "doctype", "lesson_reference")
if not frappe.db.count("Chapter Reference"):
move_chapters()
if not frappe.db.count("Lesson Reference"):
move_lessons()
def move_chapters():
docs = frappe.get_all("Chapters", fields=["*"])
for doc in docs:
keys = doc
keys.update({"doctype": "Chapter Reference"})
del keys["name"]
frappe.get_doc(keys).save()
def move_lessons():
docs = frappe.get_all("Lessons", fields=["*"])
for doc in docs:
keys = doc
keys.update({"doctype": "Lesson Reference"})
del keys["name"]
frappe.get_doc(keys).save()

View File

@@ -330,6 +330,11 @@ input[type=checkbox] {
.quiz-label {
margin-bottom: 0;
cursor: pointer;
}
.quiz-label p {
display: inline;
}
.course-card-wide {
@@ -519,7 +524,7 @@ input[type=checkbox] {
cursor: pointer;
display: flex;
align-items: center;
padding-bottom: 0.5rem;
padding-bottom: 1rem;
}
.chapter-description {
@@ -637,7 +642,7 @@ input[type=checkbox] {
.course-outline {
flex-direction: column;
padding: 16px 12px 16px;
padding: 1rem 0.75rem 0;
}
.lessons {
@@ -881,8 +886,8 @@ input[type=checkbox] {
.question {
flex-direction: column;
width: 688px;
margin: auto;
width: 85%;
margin: 0 auto;
}
.question p {
@@ -919,6 +924,10 @@ input[type=checkbox] {
flex-direction: column;
}
.lesson-content-card .alert-dismissible .close {
padding: 0.5rem;
}
.course-content-parent {
display: grid;
grid-gap: 2rem;

View File

@@ -29,8 +29,8 @@
data-correct="{{ question['is_correct_' + loop.index | string] }}" {% if question.multiple %}
type="checkbox" {% else %} type="radio" name="{{ question.question | urlencode }}" {% endif %}>
<img class="empty-checkbox mr-3" />
<span class="label-area">{{ frappe.utils.md_to_html(option) }}</span>
</label>
<span class="label-area">{{ frappe.utils.md_to_html(option) }}</span>
</div>
{% set explanation = question['explanation_' + loop.index | string] %}

View File

@@ -45,11 +45,18 @@
{% if membership or lesson.include_in_preview or is_instructor %}
<div class="common-card-style lesson-content-card markdown-source">{{ lesson.render_html() }}</div>
<div class="common-card-style lesson-content-card markdown-source">
{% if is_instructor %}
<small class="alert alert-secondary alert-dismissible">
This lesson is not available for preview. As you are the Instructor of the course only you can see it.
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
</small>
{% endif %}
{{ lesson.render_html() }}</div>
{% else %}
<div class="common-card-style lesson-content-card">
<div class="w-25 text-center" style="margin: 0 auto;">
<small>This lesson is not available for preview. Please join the course to access this lesson.</small>
<small>This lesson is not available for preview. Please join the course to access it.</small>
<a class="button is-primary ml-auto mr-auto mt-3" href="/courses/{{ course.name }}"> Start Learning </a>
</div>
</div>

View File

@@ -169,7 +169,8 @@ var parse_options = () => {
}
var add_icon = (element, icon) => {
$(element).parent().empty().html(`<img class="mr-3" src="/assets/community/icons/${icon}.svg">`);
var label = $(element).parent().find(".label-area p").text();
$(element).parent().empty().html(`<img class="mr-3" src="/assets/community/icons/${icon}.svg"> ${label}`);
}
var add_to_local_storage = (quiz_name, current_index, answer, is_correct) => {

View File

@@ -11,7 +11,7 @@ def get_context(context):
}
def get_courses():
course_names = frappe.get_all("LMS Course", filters={"is_published": True}, pluck="name")
course_names = frappe.get_all("LMS Course", filters={"is_published": True}, order_by="upcoming", pluck="name")
courses = []
for course in course_names:
courses.append(frappe.get_doc("LMS Course", course))

View File

@@ -1,5 +1,6 @@
import frappe
from community.page_renderers import get_profile_url_prefix
from urllib.parse import urlencode
def get_context(context):
context.no_cache = 1
@@ -9,14 +10,13 @@ def get_context(context):
except KeyError:
username = frappe.db.get_value("User", frappe.session.user, ["username"])
if username:
frappe.local.flags.redirect_location = get_profile_url_prefix() + username
frappe.local.flags.redirect_location = get_profile_url_prefix() + urlencode({"username": username})
raise frappe.Redirect
try:
context.member = frappe.get_doc("User", {"username": username})
except:
context.template = "www/404.html"
return
context.profile_tabs = get_profile_tabs(context.member)
def get_profile_tabs(user):