Compare commits

..

91 Commits

Author SHA1 Message Date
Jannat Patel
f5af07086b Merge branch 'main' of https://github.com/frappe/school into rename-app-to-school 2021-10-19 19:20:31 +05:30
Jannat Patel
4d534db63f Merge pull request #241 from pateljannat/fix-styles 2021-10-19 19:18:46 +05:30
Jannat Patel
aec69e96cb fix: style for certificate button and card responsive 2021-10-19 19:09:42 +05:30
Jannat Patel
6172b09aa3 fix: conflicts 2021-10-19 12:37:16 +05:30
Jannat Patel
98c386729c Merge pull request #240 from pateljannat/fix-translation-issue 2021-10-18 13:29:58 +05:30
Jannat Patel
91ebcd8253 fix: translation issue 2021-10-18 13:28:48 +05:30
Jannat Patel
3a51299e8d Merge pull request #239 from pateljannat/fix-rating-issue 2021-10-18 13:18:26 +05:30
Jannat Patel
eaa8876f4e fix: made quotes same throughout file 2021-10-18 13:13:19 +05:30
Jannat Patel
7d80178b48 fix: allow import on course chapter lesson quiz 2021-10-18 13:02:11 +05:30
Jannat Patel
8090f2f397 fix: made strings translatable 2021-10-18 12:43:34 +05:30
Jannat Patel
bf986e26bc fix: rating issue 2021-10-18 12:24:37 +05:30
Jannat Patel
c95d957d2c refactor: build file and patch 2021-10-13 13:51:41 +05:30
Jannat Patel
b1aaddae59 Merge pull request #235 from anandology/fix-reindex-exercises
fix: error on reindex-exercises
2021-10-12 17:23:13 +05:30
Anand Chitipothu
8fe9bad2bb fix: error on reindex-exercises
Issue fossunited/mon_school#69
2021-10-12 12:38:26 +05:30
Jannat Patel
23dab6312d Merge pull request #233 from pateljannat/quiz-question-length-issue
fix: quiz question length issue
2021-10-12 10:48:32 +05:30
Jannat Patel
c91b1a7a23 fix: quiz question length issue 2021-10-12 10:34:15 +05:30
Jannat Patel
d07dbcc50a refactor: renamed app to school 2021-10-11 20:31:27 +05:30
Jannat Patel
49771a627d Merge pull request #232 from anandology/ignore-xss-for-lesson
fix: fixed the issue of lesson body getting mangled on save
2021-10-11 17:13:50 +05:30
Anand Chitipothu
25ec4ae7c6 fix: fixed the issue of lesson body getting mangled on save
enabled `ignore_xss_filter` for lesson body to disable sanitizing the
input.

Issue #231
2021-10-11 15:34:16 +05:30
Jannat Patel
13022e0bcc Merge pull request #229 from pateljannat/ix-profile-cards 2021-10-08 20:34:58 +05:30
pateljannat
cdc4b6992d fix: clickable course cards from profile page 2021-10-08 20:28:06 +05:30
Jannat Patel
f178f3806d Merge pull request #224 from pateljannat/change-patch-sequence 2021-10-06 21:52:34 +05:30
pateljannat
d84f621813 fix: patch sequence 2021-10-06 21:33:13 +05:30
Jannat Patel
7ba2ac1efd Merge pull request #222 from pateljannat/ci-fix 2021-10-04 13:39:51 +05:30
Jannat Patel
658a9e6172 fix: path to frappe-bench 2021-10-04 13:26:06 +05:30
Jannat Patel
0b44e78cc2 fix: removed frappe-path 2021-10-04 13:20:08 +05:30
Jannat Patel
1c5766d022 Merge pull request #205 from pateljannat/discussions-shift 2021-10-04 13:10:56 +05:30
pateljannat
3bff000cc9 fix: bench init command 2021-10-04 12:21:02 +05:30
pateljannat
30a8750f16 fix: ci 2021-10-04 10:34:47 +05:30
pateljannat
f3ad3f6d18 Merge branch 'main' of https://github.com/fossunited/community into discussions-shift 2021-10-03 12:12:31 +05:30
Jannat Patel
65a7dde47b Merge pull request #221 from pateljannat/fix-progress-api 2021-10-02 19:50:02 +05:30
pateljannat
38ebab59c7 fix: api call for progress save 2021-10-02 19:39:27 +05:30
Jannat Patel
b7f79b4832 Merge pull request #217 from pateljannat/remove-unused-doctypes 2021-10-02 19:00:21 +05:30
pateljannat
876a2f562f fix: conflicts 2021-10-02 18:54:05 +05:30
Jannat Patel
5f4fc2fb59 Merge pull request #219 from pateljannat/reload-doctypes-in-patch
fix: relaod doctypes in patch
2021-10-02 13:25:41 +05:30
pateljannat
44e8efd39b fix: relaod doctypes in patch 2021-10-02 13:12:04 +05:30
Jannat Patel
51c625da4d Merge pull request #218 from pateljannat/courses-page-headings 2021-10-01 19:40:50 +05:30
pateljannat
a795cd23a8 fix: conflicts 2021-10-01 11:52:20 +05:30
pateljannat
ebc3cf1cbf feat: live and upcoming course headers 2021-09-30 18:31:41 +05:30
pateljannat
c717b3ba9d fix: removed unused folders 2021-09-30 17:54:59 +05:30
pateljannat
0ed3c87f79 fix: conflicts 2021-09-30 17:36:15 +05:30
Jannat Patel
9499700988 Merge pull request #216 from pateljannat/rename-chapters-and-lessons
fix: renamed chapter and lesson doctype
2021-09-30 17:17:42 +05:30
pateljannat
8366721643 fix: indentation 2021-09-30 17:09:35 +05:30
pateljannat
66afd0fcdd fix: remove unused doctype 2021-09-30 16:20:44 +05:30
pateljannat
a105a1d3b4 fix: removed chapter and lesson links 2021-09-30 15:04:19 +05:30
pateljannat
5488947922 fix: rename parenttype for lesson reference 2021-09-30 11:27:27 +05:30
Jannat Patel
aa466f9fb7 Merge pull request #215 from fossunited/duplicate-course-interest 2021-09-30 11:24:59 +05:30
pateljannat
b3840e056f fix: naming series 2021-09-29 19:37:37 +05:30
pateljannat
ddffc8372b fix: condition to check course and chapter 2021-09-29 17:55:08 +05:30
pateljannat
dc877a9c09 fix: renamed chapter and lesson doctype 2021-09-29 16:42:07 +05:30
Anand Chitipothu
04d2384283 fix: avoid creating duplicate entries of LMS Course Interest 2021-09-29 13:34:38 +05:30
Jannat Patel
50938afe77 Merge pull request #214 from pateljannat/course-progress-report
feat: course progress summary
2021-09-28 20:10:00 +05:30
pateljannat
ea6bd1f598 fix: columns 2021-09-28 19:58:07 +05:30
pateljannat
fb0f9885c1 feat: course progress summary 2021-09-28 18:03:12 +05:30
pateljannat
4248a3af07 Merge branch 'main' of https://github.com/fossunited/community into discussions-shift 2021-09-28 11:16:46 +05:30
pateljannat
a3dc2402f7 fix: semicolon 2021-09-28 11:16:42 +05:30
Jannat Patel
153b439510 Merge pull request #211 from pateljannat/preview-message
fix: preview message
2021-09-27 13:00:46 +05:30
pateljannat
06b925435d fix: preview message 2021-09-27 12:46:11 +05:30
pateljannat
93c2c3cc45 fix: conflicts 2021-09-21 12:38:43 +05:30
Jannat Patel
04a3d58028 Merge pull request #210 from pateljannat/patch-for-chapters-and-lessons
fix: Patch for chapters and lessons
2021-09-21 10:21:31 +05:30
Jannat Patel
8551cfa32e fix: check if present before adding 2021-09-20 21:40:49 +05:30
Jannat Patel
b19c7f2fac fix: move data between doctypes 2021-09-20 18:11:19 +05:30
Jannat Patel
d135338088 fix: patch 2021-09-20 17:49:13 +05:30
Jannat Patel
b8fae5cd28 Merge pull request #209 from pateljannat/username-validation
fix: Username validation
2021-09-20 15:23:18 +05:30
Jannat Patel
29fe75d807 fix: regex in page renderer 2021-09-20 15:12:23 +05:30
Jannat Patel
1dbbf7c769 Merge branch 'main' of https://github.com/fossunited/community into username-validation 2021-09-20 13:44:51 +05:30
Jannat Patel
3be20b5658 Merge pull request #208 from pateljannat/misc
fix: minor issues
2021-09-20 12:26:59 +05:30
Jannat Patel
73b6ddf365 fix: deleted unnecessary file 2021-09-20 12:21:40 +05:30
Jannat Patel
64048a8a18 fix: minor issues 2021-09-20 12:10:35 +05:30
Jannat Patel
e245af57a8 fix: regex change for username 2021-09-19 19:15:45 +05:30
Jannat Patel
0ab708396a Merge pull request #207 from pateljannat/fixes
fix: issues
2021-09-16 18:21:58 +05:30
Jannat Patel
29855a0cbc fix: issues 2021-09-16 18:04:03 +05:30
Jannat Patel
ff6457171f Merge pull request #206 from kennethsequeira/patch-1
fix: spell check in Validation Message
2021-09-16 16:35:13 +05:30
Kenneth Sequeira
9fd59b5d38 fix: spell check in Validation Message
Change unedrscore to underscore
2021-09-16 15:59:32 +05:30
Jannat Patel
c750c62993 fix: style and message 2021-09-16 13:26:11 +05:30
Jannat Patel
a0d90ab16b fix: conflicts 2021-09-14 18:36:21 +05:30
Jannat Patel
af15d978c6 Merge pull request #204 from pateljannat/discussions-markdown-support
fix: discussions markdown support
2021-09-14 16:38:02 +05:30
Jannat Patel
f4271e7c0e fix: discussions markdown support 2021-09-14 16:22:56 +05:30
Jannat Patel
0440e1062d fix: shifting discussions from community app 2021-09-14 15:58:12 +05:30
Jannat Patel
2bc30d696a Merge pull request #203 from pateljannat/certification-redesign
fix: certificate-redesign
2021-09-11 11:21:07 +05:30
Jannat Patel
6dcd210031 certificate-redesign 2021-09-11 11:09:28 +05:30
Jannat Patel
c78c4c92b7 Merge pull request #200 from pateljannat/progress-indicators-and-dashboard
fix: profile and progress on dashboard
2021-09-10 19:52:16 +05:30
Jannat Patel
6a2c749a86 fix: formatting 2021-09-10 19:46:48 +05:30
Jan Doe
56d738474a fix: course card buttons 2021-09-10 18:54:27 +05:30
Jan Doe
7721f31342 fix: profile urls 2021-09-09 15:34:39 +05:30
Jan Doe
90e268ff2f fix: conflicts 2021-09-09 11:01:59 +05:30
Jannat Patel
69bdb75625 Merge pull request #202 from fossunited/profile-urls
Added support for making profile urls to be top-level
2021-09-09 10:26:23 +05:30
pateljannat
b9736cc6d6 fix: conflicts 2021-09-06 19:35:32 +05:30
pateljannat
3a2ebd42a7 fix: progress pill and certificate secondary cta 2021-09-02 13:26:45 +05:30
pateljannat
e0b25c1e6e fix: certificate link 2021-09-01 16:50:27 +05:30
pateljannat
13b968e18c fix: profile and progress on dashboard 2021-09-01 16:21:55 +05:30
495 changed files with 3363 additions and 1288 deletions

View File

@@ -53,19 +53,19 @@ jobs:
then
(cd && tar xzf ~/bench-cache/bench.tgz)
else
bench init ~/frappe-bench --skip-redis-config-generation
bench init ~/frappe-bench --skip-redis-config-generation --skip-assets --python "$(which python)"
mkdir -p ~/bench-cache
(cd && tar czf ~/bench-cache/bench.tgz frappe-bench)
fi
- name: add community app to bench
- name: add school app to bench
working-directory: /home/runner/frappe-bench
run: bench get-app community $GITHUB_WORKSPACE
run: bench get-app school $GITHUB_WORKSPACE
- name: create bench site
working-directory: /home/runner/frappe-bench
run: bench new-site --mariadb-root-password root --admin-password admin frappe.local
- name: install community app
- name: install school app
working-directory: /home/runner/frappe-bench
run: bench --verbose --site frappe.local install-app community
run: bench --verbose --site frappe.local install-app school
- name: allow tests
working-directory: /home/runner/frappe-bench
run: bench --site frappe.local set-config allow_tests true
@@ -74,5 +74,5 @@ jobs:
run: bench --site frappe.local build
- name: run tests
working-directory: /home/runner/frappe-bench
run: bench --site frappe.local run-tests --app community
run: bench --site frappe.local run-tests --app school

4
.gitignore vendored
View File

@@ -3,8 +3,8 @@
*.egg-info
*.swp
tags
community/docs/current
community/public/dist
school/docs/current
school/public/dist
__pycache__/
*.py[cod]
*$py.class

View File

@@ -4,15 +4,15 @@ include *.json
include *.md
include *.py
include *.txt
recursive-include community *.css
recursive-include community *.csv
recursive-include community *.html
recursive-include community *.ico
recursive-include community *.js
recursive-include community *.json
recursive-include community *.md
recursive-include community *.png
recursive-include community *.py
recursive-include community *.svg
recursive-include community *.txt
recursive-exclude community *.pyc
recursive-include school *.css
recursive-include school *.csv
recursive-include school *.html
recursive-include school *.ico
recursive-include school *.js
recursive-include school *.json
recursive-include school *.md
recursive-include school *.png
recursive-include school *.py
recursive-include school *.svg
recursive-include school *.txt
recursive-exclude school *.pyc

View File

@@ -1,4 +1,4 @@
## Community
## School
This app helps people organize and manage their own communities.
@@ -7,16 +7,16 @@ The App has following components:
1. Hackathons
1. LMS
Community is built on the [Frappe Framework](https://github.com/frappe/frappe), a full-stack web app framework built with Python & JavaScript.
School is built on the [Frappe Framework](https://github.com/frappe/frappe), a full-stack web app framework built with Python & JavaScript.
## Development Setup
**Step 1:** Clone the repo
```
$ git clone https://github.com/fossunited/community.git
$ git clone https://github.com/frappe/school.git
$ cd community
$ cd school
```
**Step 2:** Run docker-compose
@@ -59,15 +59,15 @@ To setup the repository locally follow the steps mentioned below:
1. Install bench and setup a frappe-bench directory by following the [Installation Steps](https://frappeframework.com/docs/user/en/installation).
1. Start the server by running bench start.
1. In a separate terminal window, create a new site by running bench new-site community.test.
1. Run bench get-app https://github.com/fossunited/community.
1. Run bench --site community.test install-app community.
1. Map your site to localhost with the command ```bench --site community.test add-to-hosts```
1. Now open the URL http://community.test:8000/ in your browser, you should see the app running.
1. In a separate terminal window, create a new site by running bench new-site school.test.
1. Run bench get-app https://github.com/frappe/school.
1. Run bench --site school.test install-app school.
1. Map your site to localhost with the command ```bench --site school.test add-to-hosts```
1. Now open the URL http://school.test:8000/ in your browser, you should see the app running.
### Contribution Guidelines (for The Hard Way)
1. Go to the apps/community directory of your installation and execute git pull --unshallow to ensure that you have the full git repository. Also fork the fossunited/community repository on GitHub.
1. Go to the apps/school directory of your installation and execute git pull --unshallow to ensure that you have the full git repository. Also fork the frappe/school repository on GitHub.
1. Check out a working branch in git (e.g. git checkout -b my-new-branch).
1. Make your proposed changes to the source
1. Run your local version (e.g. bench start in your bench installation). Make sure that your changes work the way you want them to.

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Discussion Reply', {
// refresh: function(frm) {
// }
});

View File

@@ -1,51 +0,0 @@
{
"actions": [],
"creation": "2021-08-11 10:59:38.597046",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"topic",
"reply"
],
"fields": [
{
"fieldname": "reply",
"fieldtype": "Long Text",
"in_list_view": 1,
"label": "Reply"
},
{
"fieldname": "topic",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Topic",
"options": "Discussion Topic"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-27 15:06:51.362714",
"modified_by": "Administrator",
"module": "Community",
"name": "Discussion Reply",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -1,29 +0,0 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from community.widgets import Widgets
class DiscussionReply(Document):
def after_insert(self):
data = {
"reply": self,
"topic": {
"name": self.topic
},
"widgets": Widgets()
}
template = frappe.render_template("community/templates/discussions/reply_card.html", data)
topic_info = frappe.get_all("Discussion Topic", {"name": self.topic}, ["reference_doctype", "reference_docname", "name", "title", "owner", "creation"])
sidebar = frappe.render_template("community/templates/discussions/sidebar.html", { "topic": topic_info[0], "widgets": Widgets() })
new_topic_template = frappe.render_template("community/templates/discussions/reply_section.html", { "topics": topic_info, "widgets": Widgets() })
frappe.publish_realtime(event="publish_message",
message = {
"template": template,
"topic_info": topic_info[0],
"sidebar": sidebar,
"new_topic_template": new_topic_template
},
after_commit=True)

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Discussion Topic', {
// refresh: function(frm) {
// }
});

View File

@@ -1,57 +0,0 @@
{
"actions": [],
"creation": "2021-08-11 10:55:29.341674",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"title",
"reference_doctype",
"reference_docname"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "reference_doctype",
"fieldtype": "Link",
"label": "Reference Doctype",
"options": "DocType"
},
{
"fieldname": "reference_docname",
"fieldtype": "Dynamic Link",
"label": "Reference Docname",
"options": "reference_doctype"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-11 12:29:43.564123",
"modified_by": "Administrator",
"module": "Community",
"name": "Discussion 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": "modified",
"sort_order": "DESC",
"title_field": "title",
"track_changes": 1
}

View File

@@ -1,35 +0,0 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class DiscussionTopic(Document):
pass
@frappe.whitelist()
def submit_discussion(doctype, docname, reply, title, topic_name=None):
if topic_name:
save_message(reply, topic_name)
return topic_name
topic = frappe.get_doc({
"doctype": "Discussion Topic",
"title": title,
"reference_doctype": doctype,
"reference_docname": docname
})
topic.save(ignore_permissions=True)
save_message(reply, topic.name)
return topic.name
def save_message(reply, topic):
frappe.get_doc({
"doctype": "Discussion Reply",
"reply": reply,
"topic": topic
}).save(ignore_permissions=True)
@frappe.whitelist()
def get_docname(route):
return frappe.db.get_value("Web Page", {"route": route}, ["name"])

View File

@@ -1,2 +0,0 @@
{% set docname = frappe.db.get_value("Web Page", {"route": ""}, ["name"])%}
{{ widgets.DiscussionMessage(doctype="Web Page", docname=docname) }}

View File

@@ -1,17 +0,0 @@
{
"__islocal": true,
"__unsaved": 1,
"creation": "2021-08-30 12:42:31.550200",
"docstatus": 0,
"doctype": "Web Template",
"fields": [],
"idx": 0,
"modified": "2021-08-30 12:42:31.550200",
"modified_by": "Administrator",
"module": "Community",
"name": "Discussions",
"owner": "Administrator",
"standard": 1,
"template": "",
"type": "Section"
}

View File

@@ -1,28 +0,0 @@
<form class="discussion-form">
<div class="form-group">
<div class="control-input-wrapper">
<div class="control-input">
<input type="text" autocomplete="off" class="input-with-feedback form-control topic-title" data-fieldtype="Data"
data-fieldname="feedback_comments" placeholder="Title" spellcheck="false"></input>
</div>
</div>
</div>
<div class="form-group">
<div class="control-input-wrapper">
<div class="control-input">
<textarea type="text" autocomplete="off" class="input-with-feedback form-control comment-field"
data-fieldtype="Text" data-fieldname="feedback_comments" placeholder="Enter a comment..."
spellcheck="false"></textarea>
</div>
</div>
</div>
<div class="comment-footer">
<div class="button is-default pull-right mb-5 submit-discussion" data-doctype="{{ doctype | urlencode }}"
data-docname="{{ docname | urlencode }}">
Post</div>
</div>
</form>

View File

@@ -1,54 +0,0 @@
{% set topics = frappe.get_all("Discussion Topic",
{"reference_doctype": doctype, "reference_docname": docname}, ["name", "title", "owner", "creation"]) %}
{% include "community/templates/discussions/topic_modal.html" %}
<div class="discussions-parent">
<div class="discussions-header">
<span class="course-home-headings">{{_('Discussions')}}</span>
{% if topics %}
{% include "community/templates/discussions/button.html" %}
{% endif %}
</div>
{% if topics %}
<div class="common-card-style thread-card course-content-parent" data-doctype="{{ doctype }}"
data-docname="{{ docname }}">
<div class="discussions-sidebar">
{% include "community/templates/discussions/search.html" %}
{% for topic in topics %}
{% set replies = frappe.get_all("Discussion Reply", {"topic": topic.name})%}
{% include "community/templates/discussions/sidebar.html" %}
{% endfor %}
</div>
<div class="mr-2" id="discussion-group">
{% include "community/templates/discussions/reply_section.html" %}
</div>
</div>
{% else %}
<div id="no-discussions" class="common-card-style thread-card">
<div class="no-discussions">
<div class="font-weight-bold">No Discussions</div>
<div class="muted-text mt-3 mb-3">There are no discussions for this {{ doctype | lower }}, why don't you start
one! </div>
{% if frappe.session.user == "Guest" %}
<div class="button is-primary mt-3" id="login-from-discussion">Log In</div>
{% elif not condition %}
<div class="button is-primary mt-3" id="login-from-discussion" data-redirect="{{ redirect_to }}">
{{ button_name }}
</div>
{% else %}
{% include "community/templates/discussions/button.html" %}
{% endif %}
</div>
</div>
</div>
{% endif %}
</div>
{% block script %}
<script>{% include "community/templates/discussions/discussions.js" %}</script>
{% endblock %}

View File

@@ -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 TestChapter(unittest.TestCase):
pass

View File

@@ -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 TestLesson(unittest.TestCase):
pass

View File

@@ -1,4 +0,0 @@
<div class="p-5 batch-header">
<h3>{{batch_name}}</h3>
<div class="text-muted">{{member_count}} members</div>
</div>

View File

@@ -1,21 +0,0 @@
<div class="breadcrumb">
{% if course %}
<a class="dark-links" href="/courses">All Courses</a>
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
{% if lesson %}
<a class="dark-links" href="/courses/{{ course.name }}">{{ course.title }}</a>
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
<span class="muted-text"> {{ lesson.title }}</span>
{% else %}
<span class="muted-text">{{ course.title }}</span>
{% endif %}
{% endif %}
{% if thread %}
<a class="dark-links" href="/discussions">Discussions</a>
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
<span class="muted-text">{{ thread.title }}</span>
{% endif %}
</div>

View File

@@ -1,90 +0,0 @@
<div class="common-card-style course-card">
<div class="course-image {% if not course.image %}default-image{% endif %}"
{% if course.image %} style="background-image: url( {{ course.image }} );" {% endif %}>
<div class="course-tags">
{% for tag in course.get_tags() %}
<div class="course-card-pills">{{ tag }}</div>
{% endfor %}
</div>
{% if not course.image %}
<div class="default-image-text">{{ course.title[0] }}</div>
{% endif %}
</div>
<div class="course-card-content">
<div class="course-card-meta muted-text">
{% if course.get_chapters() | length %}
<span>
{{ course.get_chapters() | length }} Chapters
</span>
{% endif %}
{% if course.get_chapters() | length and course.get_upcoming_batches() | length %}
<span class="font-weight-bold ml-3 mr-3"> . </span>
{% endif %}
{% if course.get_upcoming_batches() | length %}
<span class="">
{{ course.get_upcoming_batches() | length }} Open Batches
</span>
{% endif %}
</div>
<div class="course-card-title">{{ course.title }}</div>
<div class="card-divider"></div>
<div class="course-card-meta-2">
{{ widgets.Avatar(member=course.get_instructor(), avatar_class="avatar-small") }}
<span class="course-instructor">
{{ course.get_instructor().full_name }}
</span>
<span class="course-student-count">
{% if course.get_students() | length %}
<span class="mr-4">
<img class="icon-background" src="/assets/community/icons/user.svg" />
{{ course.get_students() | length }}
</span>
{% endif %}
{% set avg_rating = course.get_average_rating() %}
{% if avg_rating %}
<span>
<img class="icon-background" src="/assets/community/icons/rating.svg" />
{{ avg_rating }}
</span>
{% endif %}
</span>
</div>
{% set membership = course.get_membership(frappe.session.user) %}
{% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and
membership.current_lesson
else '1.1' %}
{% set query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" %}
{% if course.upcoming %}
<div class="view-course-link is-secondary border">
Upcoming Course <img class="ml-3" src="/assets/community/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% elif membership %}
<div class="view-course-link is-primary">
Continue Course <img class="ml-3" src="/assets/community/icons/white-arrow.svg" />
</div>
<a class="stretched-link" href="{{ course.get_learn_url(lesson_index) }}{{ query_parameter }}"></a>
{% else %}
<div class="view-course-link is-default">
View Course <img class="ml-3" src="/assets/community/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% endif %}
</div>
</div>
<script>
frappe.ready(() => {
$(".course-card-title").each((i, element) => {
var title = $(element).text();
var length = $(window).width() <= 375 ? 60 : 65;
var suffix = title.length > length ? "..." : "";
$(element).text(title.substring(0, length) + suffix);
})
})
</script>

View File

@@ -1,6 +0,0 @@
<div class="instructor">
{{ widgets.Avatar(member=instructor, avatar_class="avatar-medium") }}
<a class="ml-1 instructor-title" href="{{get_profile_url(instructor.username)}}">{{ instructor.full_name }}</a>
<div class="instructor-subtitle">Course Creator</div>
<!-- <div class="instructor-subtitle">Created {{instructor.get_course_count()}} courses</div> -->
</div>

View File

@@ -1,37 +0,0 @@
<div class="common-card-style">
<div class="certificate-content">
<div class="certificate-heading">
Certificate of Completion
</div>
<div class="certificate-para">
This is to certify that <span class="font-weight-bold">{{ student.full_name }}</span> has successfully completed
<span class="font-weight-bold">{{ course.title }}</span> online course on
<span class="font-weight-bold">{{ frappe.utils.format_date(certificate.issue_date, "medium") }}</span>
</div>
<div class="certificate-footer">
{% if instructor %}
<div>
<span>
Instructor:
</span>
<span class="font-weight-bold">
{{ instructor.full_name }}
</span>
</div>
{% endif %}
{% if certificate.expiry_date %}
<div>
<span>
Expiry Date:
</span>
<span class="font-weight-bold">
{{ frappe.utils.format_date(certificate.expiry_date, "medium") }}
</span>
</div>
{% endif %}
</div>
<img src="{{ logo }}" class="certificate-logo">
</div>
<div class="certificate-ribbon"></div>
</div>
<script src="/assets/community/js/html2canvas.js"></script>

View File

@@ -1,7 +0,0 @@
{% if frappe.session.user != "Guest" and
(condition is not defined or (condition is defined and condition )) %}
<span class="button is-secondary reply">
New Discussion
<img src="/assets/community/icons/small-add-black.svg">
</span>
{% endif %}

View File

@@ -1,198 +0,0 @@
frappe.ready(() => {
setup_socket_io();
set_docname_if_missing();
expand_first_discussion();
$(".search-field").keyup((e) => {
search_topic(e);
});
$(".reply").click((e) => {
show_new_topic_modal(e);
});
$("#login-from-discussion").click((e) => {
login_from_discussion(e);
});
$(".sidebar-topic").click((e) => {
if ($(e.currentTarget).attr("aria-expanded") == "true") {
e.stopPropagation();
}
});
$(document).on("click", ".submit-discussion", (e) => {
submit_discussion(e);
});
})
var show_new_topic_modal = (e) => {
e.preventDefault();
$("#discussion-modal").modal("show");
var topic = $(e.currentTarget).attr("data-topic");
$(".modal-headings").text(topic ? "Reply" : "Start a Discussion");
topic ? $(".topic-title").addClass("hide") : $(".topic-title").removeClass("hide");
$("#submit-discussion").attr("data-topic", topic ? topic : "");
}
var setup_socket_io = () => {
const assets = [
"/assets/frappe/js/lib/socket.io.min.js",
"/assets/frappe/js/frappe/socketio_client.js",
]
frappe.require(assets, () => {
if (window.dev_server) {
frappe.boot.socketio_port = "9000";
}
frappe.socketio.init(9000);
frappe.socketio.socket.on("publish_message", (data) => {
publish_message(data);
})
})
}
var publish_message = (data) => {
post_message_cleanup();
if ($(`.discussion-on-page[data-topic=${data.topic_info.name}]`).length) {
if ($(`.discussion-on-page[data-topic=${data.topic_info.name}] .card-divider-dark`).length) {
$(data.template).insertAfter(`.discussion-on-page[data-topic=${data.topic_info.name}] .card-divider-dark`);
}
else {
$('<div class="card-divider-dark mb-10"></div>' + data.template).insertAfter(`.discussion-on-page[data-topic=${data.topic_info.name}] .discussion-form`);
}
}
else if ((decodeURIComponent($(".discussions-parent .course-content-parent").attr("data-doctype")) == data.topic_info.reference_doctype
&& decodeURIComponent($(".discussions-parent .course-content-parent").attr("data-docname")) == data.topic_info.reference_docname)) {
$(data.sidebar).insertAfter(`.discussions-sidebar .form-group`);
$(`#discussion-group`).prepend(data.new_topic_template);
if (data.topic_info.owner == frappe.session.user) {
$(".discussion-on-page").collapse();
$(".sidebar-topic").first().click();
}
}
else {
window.location.reload();
}
update_reply_count(data.topic_info.name);
}
var post_message_cleanup = () => {
$(".comment-field").val("");
$("#discussion-modal").modal("hide");
$("#no-discussions").addClass("hide");
}
var update_reply_count = (topic) => {
var reply_count = $(`[data-target='#t${topic}']`).find(".reply-count").text();
reply_count = parseInt(reply_count) + 1;
$(`[data-target='#t${topic}']`).find(".reply-count").text(reply_count);
}
var set_docname_if_missing = () => {
if ($("[data-docname='None']").length) {
frappe.call({
method: "community.community.doctype.discussion_topic.discussion_topic.get_docname",
args: {
"route": window.location.href.split("/").slice(-1)[0]
},
callback: (data) => {
$("[data-docname='None']").attr("data-docname", data.message);
}
})
}
}
var expand_first_discussion = () => {
$($(".discussions-parent .collapse")[0]).addClass("show");
$($(".discussions-sidebar [data-toggle='collapse']")[0]).attr("aria-expanded", true);
}
var search_topic = (e) => {
var input = $(e.currentTarget).val();
var topics = $(".discussions-parent .discussion-topic-title");
if (input.length < 3 || input.trim() == "") {
topics.closest(".sidebar-parent").removeClass("hide");
return
}
topics.each((i, elem) => {
var topic_id = $(elem).parent().attr("data-target");
/* Check match in replies */
var match_in_reply = false;
var replies = $(`${topic_id}`);
for (var reply of replies.find(".reply-text")) {
if (has_common_substring($(reply).text(), input)) {
match_in_reply = true;
break;
}
}
/* Match found in title or replies, then show */
if (has_common_substring($(elem).text(), input) || match_in_reply) {
$(elem).closest(".sidebar-parent").removeClass("hide")
}
else {
$(elem).closest(".sidebar-parent").addClass("hide");
}
})
}
var has_common_substring = (str1, str2) => {
var str1_arr = str1.toLowerCase().split(" ");
var str2_arr = str2.toLowerCase().split(" ");
var substring_found = false;
for (var first_word of str1_arr) {
for (var second_word of str2_arr) {
if (first_word.indexOf(second_word) > -1) {
substring_found = true;
break;
}
}
}
return substring_found;
}
var submit_discussion = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
var title = $(".topic-title:visible").length ? $(".topic-title:visible").val().trim() : "";
var reply = $(".comment-field:visible").val().trim();
if (reply) {
var doctype = $(e.currentTarget).attr("data-doctype");
doctype = doctype ? decodeURIComponent(doctype) : doctype;
var docname = $(e.currentTarget).attr("data-docname");
docname = docname ? decodeURIComponent(docname) : docname;
frappe.call({
method: "community.community.doctype.discussion_topic.discussion_topic.submit_discussion",
args: {
"doctype": doctype ? doctype : "",
"docname": docname ? docname : "",
"reply": reply,
"title": title,
"topic_name": $(e.currentTarget).closest(".discussion-on-page").attr("data-topic")
}
})
}
}
var login_from_discussion = (e) => {
var redirect = $(e.currentTarget).attr("data-redirect") || window.location.href;
window.location.href = `/login?redirect-to=${redirect}`;
}

View File

@@ -1,13 +0,0 @@
<div class="reply-card">
{% set member = frappe.get_doc("User", reply.owner) %}
<div class="d-flex align-items-center muted-text">
{% set member = frappe.get_doc("User", reply.owner) %}
{{ widgets.Avatar(member=member, avatar_class="avatar-small")}}
<a class="button-links ml-2" href="{{ get_profile_url(member.username) }}">
{{ member.full_name }}
</a>
<div class="ml-2 frappe-timestamp" data-timestamp="{{ reply.creation }}"> just now </div>
</div>
<div class="card-divider mt-3"></div>
<div class="reply-text">{{ reply.reply }}</div>
</div>

View File

@@ -1,41 +0,0 @@
{% for topic in topics %}
{% set replies = frappe.get_all("Discussion Reply", {"topic": topic.name},
["reply", "owner", "creation"], order_by="creation desc")%}
<!-- Hack to reorganize the replies array. So even though we want reverse cronology, the first reply should appear first. -->
{% if replies.insert(0, replies.pop()) %}{% endif %}
{% if replies %}
<div class="collapse discussion-on-page" id="t{{ topic.name }}" data-topic="{{ topic.name }}"
data-parent="#discussion-group">
<div class="course-home-headings p-0">{{ topic.title }}</div>
{% for reply in replies %}
{% if loop.index == 2 %}
<div class="card-divider-dark mb-10"></div>
{% endif %}
{% include "community/templates/discussions/reply_card.html" %}
{% if loop.index == 1 %}
{% if frappe.session.user == "Guest" or (condition is defined and not condition) %}
<div class="d-flex flex-column align-items-center muted-text">
Want to join the discussion?
{% if frappe.session.user == "Guest" %}
<div class="button is-primary mt-3 mb-3" id="login-from-discussion">Log In</div>
{% elif not condition %}
<div class="button is-primary mt-3 mb-3" id="login-from-discussion" data-redirect="{{ redirect_to }}">{{ button_name }}
</div>
{% endif %}
</div>
{% else %}
{{ widgets.CommentBox(doctype=doctype, docname=docname) }}
{% endif %}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}

View File

@@ -1,9 +0,0 @@
<div class="form-group">
<div class="control-input-wrapper">
<div class="control-input">
<textarea type="text" autocomplete="off" class="input-with-feedback form-control search-field"
data-fieldtype="Text" data-fieldname="feedback_comments" placeholder="Search Topics"
spellcheck="false"></textarea>
</div>
</div>
</div>

View File

@@ -1,20 +0,0 @@
<div class="sidebar-parent">
<div class="sidebar-topic" data-target="#t{{ topic.name }}" data-toggle="collapse" aria-expanded="false">
<div class="discussion-topic-title">{{ topic.title }}</div>
<div class="mt-2 mb-3">
{% set creator = frappe.get_doc("User", topic.owner) %}
{{ widgets.Avatar(member=creator, avatar_class="avatar-small") }}
<span class="course-instructor">
{{ creator.full_name }}
</span>
<span class="muted-text pull-right">
<span class="mr-2">
<img src="/assets/community/icons/message.svg">
<span class="reply-count">{{ replies | length }}</span>
</span>
<span> {{ frappe.utils.format_date(topic.creation, "dd MMM YYYY") }} </span>
</span>
</div>
</div>
<div class="card-divider"></div>
</div>

View File

@@ -1,15 +0,0 @@
<div class="modal fade discussion-modal" id="discussion-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="course-home-headings modal-headings">Start a Discussion</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{{ widgets.CommentBox(doctype=doctype, docname=docname) }}
</div>
</div>
</div>
</div>

View File

@@ -1,13 +0,0 @@
<div class="discussion {% if message.is_author %} is-author {% endif %}">
<div class="d-flex justify-content-between">
<div class="font-weight-bold">
{{ message.author_name }}
</div>
<div class="text-muted">
{{ message.message_time }}
</div>
</div>
<div class="mt-5">
{{ message.message }}
</div>
</div>

View File

@@ -1,22 +0,0 @@
{% extends "templates/base.html" %}
{% from "www/hackathons/macros/card.html" import null_card %}
{% block title %}{{ 'Courses' }}{% endblock %}
{% block head_include %}
<style>
</style>
{% endblock %}
{% block content %}
<div class="common-page-style">
<div class="container">
<div class="courses-header">
{{ 'All Courses' }}
</div>
<div class="cards-parent">
{% for course in courses %}
{{ widgets.CourseCard(course=course) }}
{% endfor %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,18 +0,0 @@
import frappe
def get_context(context):
context.no_cache = 1
context.courses = get_courses()
context.metatags = {
"title": "All Courses",
"image": frappe.db.get_single_value("Website Settings", "banner_image"),
"description": "This page lists all the courses published on our website",
"keywords": "All Courses, Courses, Learn"
}
def get_courses():
course_names = frappe.get_all("LMS Course", filters={"is_published": True}, pluck="name")
courses = []
for course in course_names:
courses.append(frappe.get_doc("LMS Course", course))
return courses

View File

@@ -17,9 +17,9 @@ services:
bench:
image: anandology/frappe-bench
volumes:
- .:/home/bench/frappe-bench/apps/community
- .:/home/bench/frappe-bench/apps/school
environment:
- FRAPPE_APPS=community
- FRAPPE_APPS=school
- FRAPPE_ALLOW_TESTS=true
- FRAPPE_SITE_NAME=frappe.localhost
depends_on:

Some files were not shown because too many files have changed in this diff Show More