frappe / lms Goto Github PK
View Code? Open in Web Editor NEWEasy to Use, 100% Open Source Learning Management System
Home Page: https://frappelms.com
License: GNU Affero General Public License v3.0
Easy to Use, 100% Open Source Learning Management System
Home Page: https://frappelms.com
License: GNU Affero General Public License v3.0
Add the Batches section to the new course page.
When any user other than a mentor visits the page, all the upcoming batches should be shown.
Story #15
Should this be called practice or exercise?
It may be a good idea to have multiple exercises clubbed into one lesson.
Story #54
The website will not have a Sign-up option. It will only have Login.
When users come to the Landing Page they will see a textbox for entering email before the "Request Invite"
[Enter your email ] [Request Invite]
If the email is invalid or already used, it should show an error right there. Once the request is registered, the form will be replaced with a message "Thanks for your interest in Mon School. We have recorded your interest and we will get back to you shortly."
The information of this form will be saved in a doctype called Invite Request.
This doctype will have a status field. [Pending, Approved, Rejected, Registered].
When Admins change the status of the Request to Approved, these users will get another email. The email will have a link to a new signup form.
The NewSignup form will have the following fields.
Note: The invite code will be different for every user. We will be using the name of the document as the invite code.
Please note that the signup email could be different from the invite email. If the user uses a different email for signup it will be saved in a new field and the existing field will not be overridden.
Describe the bug
The add a new batch form, when provided with invalid dates for Start Time and End Time, doesn't create the batch and doesn't show any error either.
The console shows an exception.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
An appropriate error should be shown to the user.
Traceback
Traceback (most recent call last):
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/app.py", line 64, in application
response = frappe.handler.handle()
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/handler.py", line 32, in handle
data = execute_cmd(cmd)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/handler.py", line 68, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 1165, in call
return fn(*args, **newargs)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/doctype/web_form/web_form.py", line 430, in accept
doc.insert(ignore_permissions = True, ignore_mandatory = ignore_mandatory)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 249, in insert
self.db_insert()
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/model/base_document.py", line 362, in db_insert
), list(d.values()))
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/database/database.py", line 146, in sql
self._cursor.execute(query, values)
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/connections.py", line 517, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/connections.py", line 732, in _read_query_result
result.read()
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/connections.py", line 1075, in read
first_packet = self.connection._read_packet()
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/connections.py", line 684, in _read_packet
packet.check_error()
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/protocol.py", line 220, in check_error
err.raise_mysql_exception(self._data)
File "/Users/anand/fossunited/frappe-bench/env/lib/python3.7/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.InternalError: (1292, "Incorrect time value: 'doo' for column `_9513686da06c00d7`.`tablms batch`.`start_time` at row 1")
Add Mentors section to the new course page.
It should show all the mentors for the course, with a number showing the number of batches he has mentored.
You don't have to worry anout the "Apply Now" link as part of this issue. That is taken care as a separate issue.
Story #15
Add Instructors section to the new course page.
You may have to compute the number of courses authored by the instructor to show that number.
Story #15
with the batches feature, the course page is taking a new look.
The mockups captures the page for guest users or logged in users who are not one the instructors or mentors.
With the new design and course flow, we would like to organize the course content in two levels chapter and lessions, instead of Topic that we had earlier.
A chapter will have multiple lessons and each lesson could be of one of the following types:
There could also be more types added in the future.
For every student, the system will track the lessons completed and show progress for every chapter.
Noticed an issue with tab/space with one of the files. Let's use editorconfig to handle the indentation.
Requirements:
it must have at least 4 characters
the username is case insensitive and will always be stored in lowercase
it can only have characters in the range [a-z0-9-]
Describe the bug
If there is already a user signed with a name, another user can't signup with the same name, even if using a different email address.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
It should a new email account.
Screenshots
If there a course created by the Administrator, visiting the course page shows the following error.
Traceback (most recent call last):
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/render.py", line 49, in render
data = render_page_by_language(path)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/render.py", line 178, in render_page_by_language
return render_page(path)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/render.py", line 194, in render_page
return build(path)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/render.py", line 201, in build
return build_page(path)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/render.py", line 216, in build_page
context = get_context(path)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/context.py", line 28, in get_context
context = build_context(context)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/context.py", line 108, in build_context
update_controller_context(context, context.controller)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/context.py", line 56, in update_controller_context
ret = module.get_context(context)
File "/Users/anand/fossunited/frappe-bench/apps/community/community/www/courses/course.py", line 17, in get_context
context.instructor = get_instructor(context.course.owner)
File "/Users/anand/fossunited/frappe-bench/apps/community/community/www/courses/course.py", line 68, in get_instructor
instructor = frappe.get_doc("Community Member", {"email": owner})
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 841, in get_doc
doc = frappe.model.document.get_doc(*args, **kwargs)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 74, in get_doc
return controller(*args, **kwargs)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/website/website_generator.py", line 17, in __init__
super(WebsiteGenerator, self).__init__(*args, **kwargs)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 105, in __init__
frappe.DoesNotExistError)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 423, in throw
msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable, wide=wide, as_list=as_list)
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 402, in msgprint
_raise_exception()
File "/Users/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 356, in _raise_exception
raise raise_exception(msg)
frappe.exceptions.DoesNotExistError: Community Member {'email': 'Administrator'} not found
Steps to reproduce the behavior:
The course page should be rendered.
Create a portal page /sandbox and use it to try the widgets without having to mess with the real templates. This makes the development of widgets independent of actual templates where they will be used.
Also, the sandbox page should not be available on production. I think is a good idea to disable it always and enable only when environment variable FRAPPE_DEV
is set to true
.
The website will have a page to show case the recent skethes people have made.
First version of the page can be seen at:
https://dev.fossunited.org/sketches
Reimagine this page.
Design the course page in figma using the new theme.
The courses mockup has a good-enough color pallete, but there is lot of room to make it better or come up with a completely new colors.
It may be a good idea to think about the fonts along with it.
Change the prefix of all LMS doctypes from "community" to "lms"
Add a new lesson type for showing text.
Story #54
I've setup the home page in the application. It has all the elements, but the design is not in sync with the figma mockup.
Look into that and make it look like the design in figma.
Leave out the header part for now.
See README.md for instructions to setup a dev instance.
Course
- title
- description
Lesson
- course (links to course)
- title
- description
- contents
Sketch
- owner (links to user/communuty member)
- title
- language
- code
Challenge
- course (links to course)
- language
- description
/courses
page should display all the published coursesAdd course info page for a batch.
Story #24
Add a new lesson type for showing video.
Story #54
A topic will have multiple sections. Each section could be of type text, example, problem etc.
While it is possible implement this in Frappe with child doctypes, editing them is going to be quite painful. The author of the course would like to edit the entire topic in one go, review and make corrections. We need to provide the flexibility that the author needs and multiple sections for frappe to handle each section separately.
We need to track each section separately because, later we would like to save the code in each section, multiple revisions etc.
The topic doctype will have a contents
field of type markdown. It will support annotating different sections using special markup and this will be processed and split into multiple sections on save. The following is an example of typical markup.
# Drawing shapes
Let's see how to draw a circle.
{{ section type="example" id="shapes-example-1" runtime="python-canvas" }}
circle(100, 100, 50)
{{ end }}
The `circle` function will draw a circle on the canvas and it takes three inputs: `x` and `y`, the coordinates of the center of the circle and `d`, the diameter of the circle.
{{ section type="problem" id="shapes-problem-1" runtime="python-canvas" }}
Write a program to draw two circles touching each other.
![](two-circles.png)
----
# Your code here
# Hint: you need to call the circle function twice
{{ end }}
The preprocessor will process this and convert this into multiple sections as shown below as YAML:
sections:
- id: section-0001
type: text
contents: >
# Drawing shapes
Let's see how to draw a circle.
- id: shape-example-1
type: example
runtime: python-canvas
code: >
circle(100, 100, 50)
- id: section-0002
type: text
contents: >
The `circle` function will draw a circle on the canvas and it takes three inputs: `x` and `y`, the coordinates of the center of the circle and `d`, the diameter of the circle.
...
Add a new lesson type for showing quiz.
The quiz may have an optional hint. The user can submit the answer and the system will tell if the answer is correct.
Story #54
This issue proposes URL structure to be used by the community app.
Every user will have a username
and /<username>
will be the profile of that user, just like github.com/anandology
The username
field will have the following constraints.
The following names are reserved and can not be used.
- /app
- /admin
- /help
- /settings
- /events
- /hackathons
- /courses
- /sketches
- /blog
- /code
- /community
- /show
- /view
- /pages
- /system
Events will use /events
as the base url. Every event will have a slug and a event url will be /events/<event-slug>
.
The system should allow the mentor to see the progress of all students in a batch on a single dashboard. It should allow the mentor to see detailed progress of each student for each practice session.
The home page will have four sections.
See Figma mockup.
I've capured all the sections there. Feel free to play with colors. It would be good to place place an image to the right side of the hero section. May pick one from unDraw.
Style Fixes:
Functionality Fixes:
Time field should accept format HH: mm
Redirect to the Course Page after Save
Add primary details of the course to the new course page. The fileds include:
As of now, the video field is not present in the LMS Course doctype. That need to be added as well.
Story #15
Create a layout template for the batch page and add dummy pages for each of the following pages.
One possible option for the URLs can be:
/courses/the-joy-of-programming/JP01/learn
/courses/the-joy-of-programming/JP01/schedule
/courses/the-joy-of-programming/JP01/members
/courses/the-joy-of-programming/JP01/discuss
/courses/the-joy-of-programming/JP01/about
I'm not quite happy with using the batch number in the URL. For students we don't really need to see the batch name in the URLs.
The other option is:
/courses/the-joy-of-programming/learn
/courses/the-joy-of-programming/schedule
/courses/the-joy-of-programming/members
/courses/the-joy-of-programming/discuss
/courses/the-joy-of-programming/about
This makes the URLS a lot clean, but the issue is with mentors who are part of multiple batches. For them, we can change the URLs to one of the following:
/courses/the-joy-of-programming/learn/abcd123
/courses/the-joy-of-programming/learn/navgurukul
/courses/the-joy-of-programming/learn?batch=navgurukul
For now, we can go with option -1 and revisit the URLs later.
batch/learn
Story #24
Implement the "Add a new batch" feature.
This is used by mentors to create a new batch for a course. It should open up a form to select the start date, timeslot and days of the week for that batch.
Story #15
We would like to change the current URL structure as described below:
course pages
current: /courses/course?course=the-joy-of-programming
expected: ``/courses/the-joy-of-programming`
topic pages
current: /courses/topic?course=the-joy-of-programming&topic=getting-started
expected: /courses/the-joy-of-programming/getting-started
I think we should be able to use website_route_rules in hooks to achieve this.
Add a skeleton of the course page as per the design with dummy data.
Figma Mockup of the Course Page
Story #15
Currently, adding a new site requires doing the following:
home
courses
and sketches
in the top barInstead of forcing the developer to do all these things, we can create prepoopulate with all the data. For courses and sketches, it could be a couple of sample courses/sketches.
Create doctypes for chapter and lesson.
Lesson can be of one of the following types.
The doctype for lesson supports of these.
The fields would be:
The lesson type will have other fields to support each of the lesson type. They will be handled as separate issue.
Story #54
The mentors section has an apply now link. Clicking on that should create a Mentor Request in the system.
You may have to create a new doctype to support that.
The Mentor Request will have the following fields:
Community Member
LMS Course
Community Member
, the person who revied this requestYou've applied to become a mentor for this course. Your request is currently under review.
If you are not any more interested to mentor this course, you can [cancel your application].
The following people should be notified when the mentor request is created and when it's state is changed.
On Creation
State Changed to Approved/Rejected
State Changed to Withdrawn
Story #15
I found two licences in this repo - MIT in file licence.txt and AGPL in README.md.
Please look into this.
Add Your Batches section to the new course page in place of "Upcoming Batches" when the current user is a mentor of that course.
If the mentor has not scheduled any batches, it should the following variation:
You may have to add the time slot and days of the week to the Batch doctype.
Story #15
This story captures the all the pages and interaction for the batch page for both students and mentors.
As of now, we are focussing on the flow for students. The mentors may get an additional screen to track the progress of all students.
bench run-tests
is failing as it is unable to create "Community Member" object.
$ bench --site sitename run-tests
Traceback (most recent call last):
...
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 130, in run_all_tests
_add_test(app, path, filename, verbose,
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 255, in _add_test
make_test_records(doctype, verbose)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 272, in make_test_records
make_test_records(options, verbose, force)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 272, in make_test_records
make_test_records(options, verbose, force)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 273, in make_test_records
make_test_records_for_doctype(options, verbose, force)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 321, in make_test_records_for_doctype
frappe.local.test_objects[doctype] += make_test_objects(doctype, test_module.test_records, verbose, force)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/test_runner.py", line 372, in make_test_objects
d.insert()
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 258, in insert
self.run_method("after_insert")
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 847, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 1136, in composer
return composed(self, method, *args, **kwargs)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 1121, in runner
add_to_return_value(self, f(self, method, *args, **kwargs))
File "/home/anand/fossunited/frappe-bench/apps/community/community/community/doctype/community_member/community_member.py", line 39, in create_member_from_user
member.save(ignore_permissions=True)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 284, in save
return self._save(*args, **kwargs)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 306, in _save
self.insert()
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 232, in insert
self.set_new_name(set_name=set_name, set_child_names=set_child_names)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/document.py", line 422, in set_new_name
set_new_name(self)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/model/naming.py", line 55, in set_new_name
frappe.throw(_("{0} is required").format(doc.meta.get_label(fieldname)))
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 418, in throw
msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable, wide=wide, as_list=as_list)
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 397, in msgprint
_raise_exception()
File "/home/anand/fossunited/frappe-bench/apps/frappe/frappe/__init__.py", line 351, in _raise_exception
raise raise_exception(msg)
frappe.exceptions.ValidationError: User Name is required
Setup the build process for compiling less files to css. Port part of the styles.css to less.
Make it easy for other to contribute by setting up docker-compose.
Course Batches is a feature in the LMS that allows a group of students learn a course together with the help of some mentors.
A course can have multiple batches and each batch will have multiple students and mentors.
The platform allows all the members of a batch to discuss among themselves. The mentors will be able to see the progress of the students and leave comments on their work.
LMS Batch
fields:
- course: the course of the batch
- code: autogeneted primary key
- title: title of the batch
- description: description of the batch
- visibility: public | unlisted | private
- membership: open | restricted | invite_only | closed
- status: active | inactive
- stage: ready | in-progress | completed | cancelled
The batch code is autogenerated. The scheme to generate the code is the later sections.
LMS Batch Membership
fields:
- batch
- member
- member_type: student | mentor | staff
- role: member | admin
Admins of a batch will be able to add/invite new members, approve join requests and change the member type or role of any member.
A batch will always have at least one admin.
LMS Batch Join Request
TODO
LMS Batch Invitation
TODO
LMS Message
fields:
- batch
- author
- message: markdown
- pinned: boolean
Each course will have a 2-letter code and the batch code (or id) will be of the form XXDD where XX is the course code followed by two digits.
For example, the Joy of Programming course will have a code JP
and the batches of that course will be numbered as JP01
, JP02
etc.
Course Page: /courses/the-joy-of-programming
Discussion Page: /courses/the-joy-of-programming/JP01/discussion
short_code
field to the course doctypeLMS Batch
doctype [only accessible in the desk] and autogenerate the batch codeLMS Batch Membership
doctype [adding new memberships only possible from desk]LMS Message
doctype [adding new message is only available from desk]I've not added invitations and request-to-join etc. as they are not immediately required.
When student is part of an active batch, he can't join any other batch in the same course. However, a mentor or a staff can be part of multiple batches. How do we maintain these checks?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.