-
+
+ {% else %}
+
+
+
+
No Discussions
+
There are no discussions for this {{ doctype | lower }}, why don't you start
+ one!
+ {% if frappe.session.user == "Guest" %}
+
Log In
+ {% elif not condition %}
+
+ {{ button_name }}
- {% if loop.index != topics | length %}
-
+ {% else %}
+ {% include "community/templates/discussions/button.html" %}
{% endif %}
- {% endfor %}
-
-
-
- {% for topic in topics %}
- {% set replies = frappe.get_all("Discussion Reply", {"topic": topic.name},
- ["reply", "owner", "creation"], order_by="creation")%}
-
-
{{ topic.title }}
- {% for reply in replies %}
- {% include "community/templates/reply_card.html" %}
- {% endfor %}
-
- {% endfor %}
-
-
- {% if not topics %}
-
- No discussions yet.
-
- {% endif %}
-
-
+{% block script %}
+
+{% endblock %}
diff --git a/community/overrides/user.py b/community/overrides/user.py
index 51ba0bad..ffce3bb5 100644
--- a/community/overrides/user.py
+++ b/community/overrides/user.py
@@ -58,7 +58,7 @@ class CustomUser(User):
"""
return frappe.get_all(
'LMS Course', {
- 'owner': self.name,
+ 'instructor': self.name,
'is_published': True
})
diff --git a/community/public/css/style.css b/community/public/css/style.css
index 36649075..f066ac34 100644
--- a/community/public/css/style.css
+++ b/community/public/css/style.css
@@ -143,12 +143,12 @@ input[type=checkbox] {
}
.card-divider {
- border: 1px solid #F4F5F6;
+ border: 1px solid #EEF0F2;
margin-bottom: 1rem;
}
.card-divider-dark {
- border: 1px solid #E2E6E9;
+ border: 1px solid #C8CFD5;
margin-bottom: 16px;
}
@@ -221,6 +221,7 @@ input[type=checkbox] {
padding-right: 1rem;
}
}
+
.button-links {
color: #4C5A67;
}
@@ -1284,18 +1285,74 @@ pre {
padding: 1rem;
}
-textarea.form-control {
- height: 300px;
-}
-
-.discussion-on-page .form-control {
+.discussions-parent .form-control {
background-color: #FFFFFF;
font-size: inherit;
color: inherit;
+ padding: 0.75rem 1rem;
}
-.discussion-on-page textarea {
- height: 160px;
+.discussion-on-page .comment-field {
+ height: 48px;
+ box-shadow: inset 0px 0px 4px rgba(0, 0, 0, 0.2);
+ border-radius: 4px;
+}
+
+.modal .comment-field {
+ height: 300px;
+}
+
+.no-discussions {
+ width: 250px;
+ margin: 0 auto;
+ text-align: center;
+}
+
+.no-discussions .button {
+ margin: auto;
+}
+
+.discussions-header {
+ margin: 2.5rem 0 1.25rem;
+}
+
+.discussions-header .button {
+ float: right;
+}
+
+.discussions-parent .search-field {
+ background-color: #E2E6E9;
+ background-image: url(/assets/community/icons/search.svg);
+ background-repeat: no-repeat;
+ text-indent: 1.5rem;
+ background-position: 1rem 0.7rem;
+ height: 36px;
+ font-size: 12px;
+ padding: 0.65rem 0.9rem;
+}
+
+.discussions-sidebar {
+ background-color: #F4F5F6;
+ padding: 0.75rem;
+ border-radius: 4px;
+ max-height: 700px;
+ overflow-y: auto;
+}
+
+#discussion-group {
+ max-height: 700px;
+ overflow-y: auto;
+}
+
+.sidebar-topic {
+ padding: 0.75rem;
+ margin: 0.75rem 0;
+ cursor: pointer;
+}
+
+.sidebar-topic[aria-expanded="true"] {
+ background: #FFFFFF;
+ border-radius: 4px;
}
.comment-footer {
@@ -1315,6 +1372,14 @@ textarea.form-control {
color: var(--text-color);
}
+.discussion-on-page .topic-title {
+ display: none;
+}
+
+.discussions-sidebar .sidebar-parent:last-child .card-divider {
+ display: none;
+}
+
.certificate-page .common-card-style {
color: black;
font-size: 1.25rem;
diff --git a/community/public/icons/message.svg b/community/public/icons/message.svg
index 241069d5..0f46b786 100644
--- a/community/public/icons/message.svg
+++ b/community/public/icons/message.svg
@@ -1,3 +1,3 @@
-
-
+
+
diff --git a/community/public/icons/search.svg b/community/public/icons/search.svg
new file mode 100644
index 00000000..2cd7407c
--- /dev/null
+++ b/community/public/icons/search.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/community/templates/discussions/button.html b/community/templates/discussions/button.html
new file mode 100644
index 00000000..9148f770
--- /dev/null
+++ b/community/templates/discussions/button.html
@@ -0,0 +1,7 @@
+{% if frappe.session.user != "Guest" and
+(condition is not defined or (condition is defined and condition )) %}
+
+ New Discussion
+
+
+{% endif %}
diff --git a/community/templates/discussions/discussions.js b/community/templates/discussions/discussions.js
new file mode 100644
index 00000000..818b6096
--- /dev/null
+++ b/community/templates/discussions/discussions.js
@@ -0,0 +1,198 @@
+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 {
+
+ $('
' + 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}`;
+}
diff --git a/community/templates/discussions/reply_card.html b/community/templates/discussions/reply_card.html
new file mode 100644
index 00000000..ff60bc13
--- /dev/null
+++ b/community/templates/discussions/reply_card.html
@@ -0,0 +1,13 @@
+
+ {% set member = frappe.get_doc("User", reply.owner) %}
+
+ {% set member = frappe.get_doc("User", reply.owner) %}
+ {{ widgets.Avatar(member=member, avatar_class="avatar-small")}}
+
+ {{ member.full_name }}
+
+
just now
+
+
+
{{ reply.reply }}
+
diff --git a/community/templates/discussions/reply_section.html b/community/templates/discussions/reply_section.html
new file mode 100644
index 00000000..9db944a4
--- /dev/null
+++ b/community/templates/discussions/reply_section.html
@@ -0,0 +1,41 @@
+{% for topic in topics %}
+{% set replies = frappe.get_all("Discussion Reply", {"topic": topic.name},
+["reply", "owner", "creation"], order_by="creation desc")%}
+
+
+{% if replies.insert(0, replies.pop()) %}{% endif %}
+
+{% if replies %}
+
+
{{ topic.title }}
+ {% for reply in replies %}
+
+ {% if loop.index == 2 %}
+
+ {% endif %}
+
+ {% include "community/templates/discussions/reply_card.html" %}
+
+ {% if loop.index == 1 %}
+
+ {% if frappe.session.user == "Guest" or (condition is defined and not condition) %}
+
+ Want to join the discussion?
+ {% if frappe.session.user == "Guest" %}
+
Log In
+ {% elif not condition %}
+
{{ button_name }}
+
+ {% endif %}
+
+ {% else %}
+ {{ widgets.CommentBox(doctype=doctype, docname=docname) }}
+ {% endif %}
+
+ {% endif %}
+
+ {% endfor %}
+
+{% endif %}
+{% endfor %}
diff --git a/community/templates/discussions/search.html b/community/templates/discussions/search.html
new file mode 100644
index 00000000..2b4b6785
--- /dev/null
+++ b/community/templates/discussions/search.html
@@ -0,0 +1,9 @@
+
diff --git a/community/templates/discussions/sidebar.html b/community/templates/discussions/sidebar.html
new file mode 100644
index 00000000..ea74fb08
--- /dev/null
+++ b/community/templates/discussions/sidebar.html
@@ -0,0 +1,20 @@
+
diff --git a/community/templates/discussions/topic_modal.html b/community/templates/discussions/topic_modal.html
new file mode 100644
index 00000000..98682d6f
--- /dev/null
+++ b/community/templates/discussions/topic_modal.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ {{ widgets.CommentBox(doctype=doctype, docname=docname) }}
+
+
+
+
diff --git a/community/templates/reply_card.html b/community/templates/reply_card.html
deleted file mode 100644
index 4bcb5970..00000000
--- a/community/templates/reply_card.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
- {% set member = frappe.get_doc("User", reply.owner) %}
-
- {% set member = frappe.get_doc("User", reply.owner) %}
- {{ widgets.Avatar(member=member, avatar_class="avatar-medium")}}
-
-
-
Reply
-
-
-
{{ reply.reply }}
-
diff --git a/community/www/batch/learn.html b/community/www/batch/learn.html
index 49016c64..650e8a2c 100644
--- a/community/www/batch/learn.html
+++ b/community/www/batch/learn.html
@@ -102,8 +102,9 @@
{% endmacro %}
{% macro Discussions() %}
+{% set is_instructor = frappe.session.user == course.instructor %}
{% set title = lesson.title + " - " + course.title %}
-{% set condition = membership or is_instructor %}
+{% set condition = is_instructor if is_instructor else membership %}
{{ widgets.DiscussionMessage(doctype="Lesson", docname=lesson.name,
condition=condition, button_name="Start Learning",
redirect_to="/courses/" + course.name) }}