diff --git a/community/community/doctype/community_course/__init__.py b/community/community/doctype/community_course/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/community/community/doctype/community_course/community_course.js b/community/community/doctype/community_course/community_course.js
new file mode 100644
index 00000000..c1f014ed
--- /dev/null
+++ b/community/community/doctype/community_course/community_course.js
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, Frappe and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Community Course', {
+});
diff --git a/community/community/doctype/community_course/community_course.json b/community/community/doctype/community_course/community_course.json
new file mode 100644
index 00000000..3e0a4b07
--- /dev/null
+++ b/community/community/doctype/community_course/community_course.json
@@ -0,0 +1,64 @@
+{
+ "actions": [],
+ "allow_guest_to_view": 1,
+ "allow_rename": 1,
+ "autoname": "field:title",
+ "creation": "2021-03-01 16:49:33.622422",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "title",
+ "description",
+ "is_published"
+ ],
+ "fields": [
+ {
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Title",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Markdown Editor",
+ "label": "Description"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_published",
+ "fieldtype": "Check",
+ "label": "Published"
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "is_published_field": "is_published",
+ "links": [],
+ "modified": "2021-03-02 12:25:25.235975",
+ "modified_by": "Administrator",
+ "module": "Community",
+ "name": "Community Course",
+ "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": "DESC",
+ "title_field": "title",
+ "track_changes": 1,
+ "track_views": 1
+}
\ No newline at end of file
diff --git a/community/community/doctype/community_course/community_course.py b/community/community/doctype/community_course/community_course.py
new file mode 100644
index 00000000..0aebc502
--- /dev/null
+++ b/community/community/doctype/community_course/community_course.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.website.website_generator import WebsiteGenerator
+
+class CommunityCourse(WebsiteGenerator):
+ pass
diff --git a/community/community/doctype/community_course/templates/community_course.html b/community/community/doctype/community_course/templates/community_course.html
new file mode 100644
index 00000000..14cb508c
--- /dev/null
+++ b/community/community/doctype/community_course/templates/community_course.html
@@ -0,0 +1,21 @@
+{% extends "templates/web.html" %}
+
+{% block page_content %}
+
+
+ -
+
+ ← Courses
+
+
+
+
+
+
+{{ title }}
+
+{{description}}
+
+{% endblock %}
+
+
\ No newline at end of file
diff --git a/community/community/doctype/community_course/templates/community_course_row.html b/community/community/doctype/community_course/templates/community_course_row.html
new file mode 100644
index 00000000..b1d1de4c
--- /dev/null
+++ b/community/community/doctype/community_course/templates/community_course_row.html
@@ -0,0 +1,7 @@
+
diff --git a/community/community/doctype/community_course/test_community_course.py b/community/community/doctype/community_course/test_community_course.py
new file mode 100644
index 00000000..4fee6c4b
--- /dev/null
+++ b/community/community/doctype/community_course/test_community_course.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestCommunityCourse(unittest.TestCase):
+ pass
diff --git a/community/community/doctype/community_course_topic/__init__.py b/community/community/doctype/community_course_topic/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/community/community/doctype/community_course_topic/community_course_topic.js b/community/community/doctype/community_course_topic/community_course_topic.js
new file mode 100644
index 00000000..933ff0d8
--- /dev/null
+++ b/community/community/doctype/community_course_topic/community_course_topic.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2021, Frappe and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Community Course Topic', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/community/community/doctype/community_course_topic/community_course_topic.json b/community/community/doctype/community_course_topic/community_course_topic.json
new file mode 100644
index 00000000..46be90be
--- /dev/null
+++ b/community/community/doctype/community_course_topic/community_course_topic.json
@@ -0,0 +1,70 @@
+{
+ "actions": [],
+ "allow_guest_to_view": 1,
+ "autoname": "format:{title}",
+ "creation": "2021-03-02 07:20:41.686573",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "title",
+ "description",
+ "course",
+ "order"
+ ],
+ "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": "Community Course",
+ "reqd": 1
+ },
+ {
+ "fieldname": "order",
+ "fieldtype": "Int",
+ "label": "Order"
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2021-03-02 11:43:47.044344",
+ "modified_by": "Administrator",
+ "module": "Community",
+ "name": "Community Course 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
+}
\ No newline at end of file
diff --git a/community/community/doctype/community_course_topic/community_course_topic.py b/community/community/doctype/community_course_topic/community_course_topic.py
new file mode 100644
index 00000000..69c69fab
--- /dev/null
+++ b/community/community/doctype/community_course_topic/community_course_topic.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.website.website_generator import WebsiteGenerator
+
+class CommunityCourseTopic(WebsiteGenerator):
+ pass
diff --git a/community/community/doctype/community_course_topic/templates/community_course_lession.html b/community/community/doctype/community_course_topic/templates/community_course_lession.html
new file mode 100644
index 00000000..db123090
--- /dev/null
+++ b/community/community/doctype/community_course_topic/templates/community_course_lession.html
@@ -0,0 +1,7 @@
+{% extends "templates/web.html" %}
+
+{% block page_content %}
+{{ title }}
+{% endblock %}
+
+
\ No newline at end of file
diff --git a/community/community/doctype/community_course_topic/templates/community_course_lession_row.html b/community/community/doctype/community_course_topic/templates/community_course_lession_row.html
new file mode 100644
index 00000000..d7014b45
--- /dev/null
+++ b/community/community/doctype/community_course_topic/templates/community_course_lession_row.html
@@ -0,0 +1,4 @@
+
+
diff --git a/community/community/doctype/community_course_topic/test_community_course_topic.py b/community/community/doctype/community_course_topic/test_community_course_topic.py
new file mode 100644
index 00000000..dd64ad7e
--- /dev/null
+++ b/community/community/doctype/community_course_topic/test_community_course_topic.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestCommunityCourseTopic(unittest.TestCase):
+ pass
diff --git a/community/www/courses/course.html b/community/www/courses/course.html
new file mode 100644
index 00000000..43077b2e
--- /dev/null
+++ b/community/www/courses/course.html
@@ -0,0 +1,35 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ 'Courses' }}{% endblock %}
+{% from "www/courses/macros/card.html" import course_card, topic_card %}
+{% block head_include %}
+
+
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
{{ course.title }}
+
+
{{ course.description }}
+
+
+
+
+ {% for topic in course.topics %}
+
+
+
{{topic.description}}
+
+ {% endfor %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/community/www/courses/course.py b/community/www/courses/course.py
new file mode 100644
index 00000000..13426bea
--- /dev/null
+++ b/community/www/courses/course.py
@@ -0,0 +1,23 @@
+import frappe
+
+def get_context(context):
+ context.no_cache = 1
+ try:
+ course_id = frappe.form_dict['course']
+ except KeyError:
+ frappe.local.flags.redirect_location = '/courses'
+ raise frappe.Redirect
+ context.course = get_course(course_id)
+
+def get_course(name):
+ course = frappe.db.get_value('Community Course', name,
+ ['name', 'title', 'description'], as_dict=1)
+ course['topics'] = frappe.db.get_all('Community Course Topic',
+ filters={
+ 'course': name
+ },
+ fields=['name', 'title', 'description'],
+ order_by='creation'
+ )
+ print(course)
+ return course
\ No newline at end of file
diff --git a/community/www/courses/index.html b/community/www/courses/index.html
new file mode 100644
index 00000000..052c5921
--- /dev/null
+++ b/community/www/courses/index.html
@@ -0,0 +1,24 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ 'Courses' }}{% endblock %}
+{% from "www/courses/macros/card.html" import course_card %}
+{% block head_include %}
+
+
+
+{% endblock %}
+
+{% block content %}
+
+
+
{{ 'Courses' }}
+
+
+
+ {% for course in courses %}
+ {{ course_card(course) }}
+ {% endfor %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/community/www/courses/index.py b/community/www/courses/index.py
new file mode 100644
index 00000000..487b8f60
--- /dev/null
+++ b/community/www/courses/index.py
@@ -0,0 +1,13 @@
+import frappe
+
+def get_context(context):
+ context.no_cache = 1
+ context.courses = get_courses()
+
+def get_courses():
+ courses = frappe.get_all(
+ "Community Course",
+ fields=['name', 'title', 'description']
+ )
+ print(courses)
+ return courses
\ No newline at end of file
diff --git a/community/www/courses/macros/card.html b/community/www/courses/macros/card.html
new file mode 100644
index 00000000..9a3257a1
--- /dev/null
+++ b/community/www/courses/macros/card.html
@@ -0,0 +1,19 @@
+{% macro course_card(course) %}
+
+{% endmacro %}
+
+{% macro topic_card(course, topic) %}
+
+
+
+
{{topic.description}}
+
+
+{% endmacro %}
+
diff --git a/community/www/courses/topic.html b/community/www/courses/topic.html
new file mode 100644
index 00000000..5771c006
--- /dev/null
+++ b/community/www/courses/topic.html
@@ -0,0 +1,25 @@
+{% extends "templates/base.html" %}
+{% block title %}{{topic.title}} ({{course.title}}){% endblock %}
+{% block head_include %}
+
+
+
+{% endblock %}
+
+{% block content %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/community/www/courses/topic.py b/community/www/courses/topic.py
new file mode 100644
index 00000000..3ae6a6c7
--- /dev/null
+++ b/community/www/courses/topic.py
@@ -0,0 +1,34 @@
+import frappe
+
+def get_context(context):
+ context.no_cache = 1
+ course_name = get_queryparam("course", '/courses')
+ context.course = get_course(course_name)
+
+ topic_name = get_queryparam("topic", '/courses?course=' + course_name)
+ context.topic = get_topic(course_name, topic_name)
+
+ print("topic", context.topic)
+
+def get_queryparam(name, redirect_when_not_found):
+ try:
+ return frappe.form_dict[name]
+ except KeyError:
+ frappe.local.flags.redirect_location = redirect_when_not_found
+ raise frappe.Redirect
+
+def get_course(name):
+ try:
+ course = frappe.get_doc('Community Course', name)
+ except frappe.exceptions.DoesNotExistError:
+ raise frappe.NotFound
+ return course
+
+def get_topic(course_name, topic_name):
+ try:
+ topic = frappe.get_doc('Community Course Topic', topic_name)
+ except frappe.exceptions.DoesNotExistError:
+ raise frappe.NotFound
+ if topic.course != course_name:
+ raise frappe.NotFound
+ return topic