fix: conflicts
This commit is contained in:
@@ -1,22 +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 Widget, Widgets
|
||||
|
||||
class DiscussionMessage(Document):
|
||||
def after_insert(self):
|
||||
data = {
|
||||
"message": self,
|
||||
"widgets": Widgets()
|
||||
}
|
||||
template = frappe.render_template("community/templates/message_card.html", data)
|
||||
thread_info = frappe.db.get_value("Discussion Thread", self.thread, ["reference_doctype", "reference_docname"], as_dict=True)
|
||||
frappe.publish_realtime(event="publish_message",
|
||||
message = {
|
||||
"thread": self.thread,
|
||||
"template": template,
|
||||
"thread_info": thread_info
|
||||
},
|
||||
after_commit=True)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2021, FOSS United and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Discussion Thread', {
|
||||
frappe.ui.form.on('Discussion Reply', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
@@ -5,49 +5,31 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"thread",
|
||||
"column_break_2",
|
||||
"parent_message",
|
||||
"section_break_4",
|
||||
"message"
|
||||
"topic",
|
||||
"reply"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "message",
|
||||
"fieldname": "reply",
|
||||
"fieldtype": "Long Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Message"
|
||||
"label": "Reply"
|
||||
},
|
||||
{
|
||||
"fieldname": "thread",
|
||||
"fieldname": "topic",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Thread",
|
||||
"options": "Discussion Thread"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "parent_message",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Parent Message",
|
||||
"options": "Discussion Message"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break"
|
||||
"label": "Topic",
|
||||
"options": "Discussion Topic"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-12 15:59:04.811286",
|
||||
"modified": "2021-08-27 15:06:51.362714",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Community",
|
||||
"name": "Discussion Message",
|
||||
"name": "Discussion Reply",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -0,0 +1,29 @@
|
||||
# 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)
|
||||
@@ -4,5 +4,5 @@
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestDiscussionThread(unittest.TestCase):
|
||||
class TestDiscussionReply(unittest.TestCase):
|
||||
pass
|
||||
@@ -1,48 +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 DiscussionThread(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def submit_discussion(doctype, docname, message, title=None, thread_name=None):
|
||||
thread = []
|
||||
filters = {}
|
||||
if doctype and docname:
|
||||
filters = {
|
||||
"reference_doctype": doctype,
|
||||
"reference_docname": docname
|
||||
}
|
||||
|
||||
elif thread_name:
|
||||
filters = {
|
||||
"name": thread_name
|
||||
}
|
||||
|
||||
if filters:
|
||||
thread = frappe.get_all("Discussion Thread",filters)
|
||||
if len(thread):
|
||||
thread = thread[0]
|
||||
save_message(message, thread)
|
||||
|
||||
else:
|
||||
thread = frappe.get_doc({
|
||||
"doctype": "Discussion Thread",
|
||||
"title": title,
|
||||
"reference_doctype": doctype,
|
||||
"reference_docname": docname
|
||||
})
|
||||
thread.save(ignore_permissions=True)
|
||||
save_message(message, thread)
|
||||
|
||||
return thread.name
|
||||
|
||||
def save_message(message, thread):
|
||||
frappe.get_doc({
|
||||
"doctype": "Discussion Message",
|
||||
"message": message,
|
||||
"thread": thread.name
|
||||
}).save(ignore_permissions=True)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2021, FOSS United and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Discussion Message', {
|
||||
frappe.ui.form.on('Discussion Topic', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
@@ -33,7 +33,7 @@
|
||||
"modified": "2021-08-11 12:29:43.564123",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Community",
|
||||
"name": "Discussion Thread",
|
||||
"name": "Discussion Topic",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -54,4 +54,4 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# 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"])
|
||||
@@ -4,5 +4,5 @@
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestDiscussionMessage(unittest.TestCase):
|
||||
class TestDiscussionTopic(unittest.TestCase):
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
{% set docname = frappe.db.get_value("Web Page", {"route": ""}, ["name"])%}
|
||||
{{ widgets.DiscussionMessage(doctype="Web Page", docname=docname) }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"__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"
|
||||
}
|
||||
28
community/community/widgets/CommentBox.html
Normal file
28
community/community/widgets/CommentBox.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<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>
|
||||
@@ -1,70 +0,0 @@
|
||||
<div class="discussions">
|
||||
|
||||
<form class="discussion-form {% if doctype or thread %} discussion-on-page {% endif %}" id="discussion-form">
|
||||
|
||||
|
||||
<div class="form-group" {% if title or thread %} style="display: none;" {% endif %}>
|
||||
<div class="control-input-wrapper">
|
||||
<div class="control-input">
|
||||
<input type="text" autocomplete="off" class="input-with-feedback form-control thread-title"
|
||||
data-fieldtype="Data" data-fieldname="feedback_comments" placeholder="Title" spellcheck="false" {% if title
|
||||
%} value="{{ title }}" {% endif %}></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-secondary pull-right" id="submit-discussion"
|
||||
{% if doctype %} data-doctype="{{ doctype | urlencode}}" {% endif %}
|
||||
{% if docname %} data-docname="{{ docname | urlencode}}" {% endif %}
|
||||
{% if thread %} data-thread="{{ thread }}" {% endif %}>
|
||||
Post</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
$("#submit-discussion").click((e) => {
|
||||
submit_discussion(e);
|
||||
})
|
||||
})
|
||||
|
||||
var submit_discussion = (e) => {
|
||||
var message = $(".comment-field").val().trim();
|
||||
|
||||
if (message) {
|
||||
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_thread.discussion_thread.submit_discussion",
|
||||
args: {
|
||||
"doctype": doctype ? doctype : "",
|
||||
"docname": docname ? docname : "",
|
||||
"message": $(".comment-field").val(),
|
||||
"title": $(".thread-title").val(),
|
||||
"thread_name": $(e.currentTarget).attr("data-thread")
|
||||
},
|
||||
callback: (data) => {
|
||||
if (! $(".discussion-on-page").length) {
|
||||
$("#discussion-modal").modal("hide");
|
||||
window.location.href = `/discussions/${data.message}`;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,80 +1,54 @@
|
||||
{% if doctype and docname and not thread %}
|
||||
{% set topics = frappe.get_all("Discussion Topic",
|
||||
{"reference_doctype": doctype, "reference_docname": docname}, ["name", "title", "owner", "creation"]) %}
|
||||
|
||||
{% set thread_info = frappe.get_all("Discussion Thread", {"reference_doctype": doctype, "reference_docname": docname},
|
||||
["name"]) %}
|
||||
{% include "community/templates/discussions/topic_modal.html" %}
|
||||
|
||||
{% if thread_info | length %}
|
||||
{% set thread = thread_info[0].name %}
|
||||
<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 %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if thread %}
|
||||
{% set messages = frappe.get_all("Discussion Message", {"thread": thread}, ["name", "message", "owner", "creation"],
|
||||
order_by="creation") %}
|
||||
{% endif %}
|
||||
|
||||
{% if doctype %}
|
||||
<div class="course-home-headings mt-5"> Discussions </div>
|
||||
{% endif %}
|
||||
|
||||
<div class="messages mt-5">
|
||||
{% for message in messages %}
|
||||
{% include "community/templates/message_card.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if frappe.session.user == "Guest" or (condition is defined and not condition) %}
|
||||
<div class="d-flex flex-column align-items-center font-weight-bold">
|
||||
Want to join the discussion?
|
||||
{% if frappe.session.user == "Guest" %}
|
||||
<div class="button is-primary mt-5" id="login-from-discussion">Log In</div>
|
||||
{% elif not condition %}
|
||||
<div class="button is-primary mt-5" id="login-from-discussion" data-redirect="{{ redirect_to }}">{{ button_name }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ widgets.DiscussionComment(doctype=doctype, docname=docname, title=title, thread=thread ) }}
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
setup_socket_io();
|
||||
|
||||
$("#login-from-discussion").click((e) => {
|
||||
login_from_discussion(e);
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
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);
|
||||
var target = $("#submit-discussion");
|
||||
|
||||
frappe.socketio.socket.on("publish_message", (data) => {
|
||||
if (target.attr("data-thread") == data.thread
|
||||
|| (decodeURIComponent(target.attr("data-doctype")) == data.thread_info.reference_doctype
|
||||
&& decodeURIComponent(target.attr("data-docname")) == data.thread_info.reference_docname)) {
|
||||
$(".comment-field").val("");
|
||||
$(".messages").append(data.template);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var login_from_discussion = (e) => {
|
||||
var redirect = $(e.currentTarget).attr("data-redirect") || window.location.href;
|
||||
window.location.href = `/login?redirect-to=${redirect}`;
|
||||
}
|
||||
|
||||
</script>
|
||||
{% block script %}
|
||||
<script>{% include "community/templates/discussions/discussions.js" %}</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -141,9 +141,8 @@ website_route_rules = [
|
||||
{"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>", "to_route": "batch/learn"},
|
||||
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
|
||||
{"from_route": "/courses/<course>/join", "to_route": "batch/join"},
|
||||
{"from_route": "/discussions/<discussion>", "to_route": "discussions/discussion"},
|
||||
{"from_route": "/users/<string(minlength=4):username>", "to_route": "profiles/profile"},
|
||||
{"from_route": "/users", "to_route": "profiles/profile"},
|
||||
{"from_route": "/users", "to_route": "profiles/profile"}
|
||||
]
|
||||
|
||||
website_redirects = [
|
||||
|
||||
@@ -64,10 +64,11 @@
|
||||
})
|
||||
|
||||
var expand_the_first_chapter = () => {
|
||||
var elements = $(".collapse");
|
||||
var elements = $(".course-outline .collapse");
|
||||
elements.each((i, element) => {
|
||||
if (i <= 1) {
|
||||
if (i < 1) {
|
||||
show_section(element);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,3 +9,5 @@ community.patches.replace_member_with_user_in_mentor_request
|
||||
community.patches.v0_0.chapter_lesson_index_table
|
||||
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")
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
--received-message: var(--c8);
|
||||
--checkbox-size: 14px;
|
||||
--control-bg: var(--gray-100);
|
||||
--muted-text: #4C5A67;
|
||||
--button-background: #EEF0F2;
|
||||
--text-xs: 11px;
|
||||
--text-sm: 12px;
|
||||
@@ -109,8 +108,6 @@ input[type=checkbox] {
|
||||
.muted-text {
|
||||
font-size: 12px;
|
||||
line-height: 135%;
|
||||
color: var(--muted-text);
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.course-card-meta {
|
||||
@@ -146,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;
|
||||
}
|
||||
|
||||
@@ -165,7 +162,6 @@ input[type=checkbox] {
|
||||
.course-student-count {
|
||||
font-size: 12px;
|
||||
line-height: 135%;
|
||||
color: var(--muted-text);
|
||||
float: right;
|
||||
}
|
||||
|
||||
@@ -222,8 +218,13 @@ input[type=checkbox] {
|
||||
}
|
||||
}
|
||||
|
||||
.button-links {
|
||||
color: #4C5A67;
|
||||
}
|
||||
|
||||
.button-links:hover {
|
||||
text-decoration: none;
|
||||
color: #4C5A67;
|
||||
}
|
||||
|
||||
.icon-background {
|
||||
@@ -434,7 +435,7 @@ input[type=checkbox] {
|
||||
|
||||
.button {
|
||||
box-shadow: var(--btn-shadow);
|
||||
border-radius: 8px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1282,17 +1283,77 @@ pre {
|
||||
|
||||
.thread-card {
|
||||
flex-direction: column;
|
||||
padding: 1.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
textarea.form-control {
|
||||
.discussions-parent .form-control {
|
||||
background-color: #FFFFFF;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.discussion-on-page textarea.form-control {
|
||||
background-color: #FFFFFF;
|
||||
color: inherit;
|
||||
height: 160px;
|
||||
.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 {
|
||||
@@ -1300,17 +1361,24 @@ textarea.form-control {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.comment-field {
|
||||
font-size: inherit;
|
||||
.reply-card {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.thread-title {
|
||||
font-size: inherit;
|
||||
.discussions-parent .collapsing {
|
||||
transition: height 0s;
|
||||
}
|
||||
|
||||
.message-author {
|
||||
color: #192734;
|
||||
margin-left: 0.5rem;
|
||||
.discussion-topic-title {
|
||||
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 {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.00001 3.00001H12L15.5 3C16.6046 3 17.5 3.89543 17.5 5V9.78889V12.2556C17.5 13.3601 16.6046 14.2556 15.5 14.2556H14.5C14.2239 14.2556 14 14.4794 14 14.7556V16.4507C14 16.8715 13.5119 17.1041 13.185 16.839L10.2754 14.4789C10.0972 14.3344 9.87483 14.2556 9.64544 14.2556H4.49997C3.39539 14.2556 2.49995 13.3601 2.49997 12.2555L2.50001 9.78889V5.00001C2.50001 3.89544 3.39544 3.00001 4.50001 3.00001L6.00001 3.00001Z" stroke="#1F272E" stroke-miterlimit="10" stroke-linecap="square"/>
|
||||
<path d="M6 6.5H13" stroke="#1F272E" stroke-miterlimit="10" stroke-linecap="round"/>
|
||||
<path d="M6 9H10" stroke="#1F272E" stroke-miterlimit="10" stroke-linecap="round"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.66659 9.77761C2.66659 10.0919 2.79145 10.3934 3.01372 10.6157C3.23598 10.8379 3.53744 10.9628 3.85177 10.9628H10.9629L13.3333 13.3332V3.85169C13.3333 3.53736 13.2084 3.2359 12.9861 3.01364C12.7639 2.79137 12.4624 2.6665 12.1481 2.6665H3.85177C3.53744 2.6665 3.23598 2.79137 3.01372 3.01364C2.79145 3.2359 2.66659 3.53736 2.66659 3.85169V9.77761Z" stroke="#4C5A67" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 528 B |
3
community/public/icons/search.svg
Normal file
3
community/public/icons/search.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 7.44462C3.5 5.26607 5.26607 3.5 7.44462 3.5C9.62318 3.5 11.3892 5.26607 11.3892 7.44462C11.3892 8.50829 10.9683 9.47362 10.2838 10.1831C10.265 10.1972 10.247 10.2128 10.2299 10.2299C10.2128 10.247 10.1972 10.265 10.1831 10.2838C9.47362 10.9683 8.50829 11.3892 7.44462 11.3892C5.26607 11.3892 3.5 9.62318 3.5 7.44462ZM10.5696 11.2767C9.71788 11.9722 8.62996 12.3892 7.44462 12.3892C4.71378 12.3892 2.5 10.1755 2.5 7.44462C2.5 4.71378 4.71378 2.5 7.44462 2.5C10.1755 2.5 12.3892 4.71378 12.3892 7.44462C12.3892 8.62996 11.9722 9.71788 11.2767 10.5696L13.3538 12.6467C13.549 12.8419 13.549 13.1585 13.3538 13.3538C13.1585 13.549 12.8419 13.549 12.6467 13.3538L10.5696 11.2767Z" fill="#4C5A67"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 849 B |
3
community/public/icons/small-add-black.svg
Normal file
3
community/public/icons/small-add-black.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.5005 4.3335C8.5005 4.05735 8.27665 3.8335 8.0005 3.8335C7.72436 3.8335 7.5005 4.05735 7.5005 4.3335V7.50062H4.33337C4.05723 7.50062 3.83337 7.72447 3.83337 8.00062C3.83337 8.27676 4.05723 8.50062 4.33337 8.50062H7.5005V11.6677C7.5005 11.9439 7.72436 12.1677 8.0005 12.1677C8.27665 12.1677 8.5005 11.9439 8.5005 11.6677V8.50062H11.6676C11.9438 8.50062 12.1676 8.27676 12.1676 8.00062C12.1676 7.72447 11.9438 7.50062 11.6676 7.50062H8.5005V4.3335Z" fill="#4C5A67"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 619 B |
7
community/templates/discussions/button.html
Normal file
7
community/templates/discussions/button.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% 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 %}
|
||||
198
community/templates/discussions/discussions.js
Normal file
198
community/templates/discussions/discussions.js
Normal file
@@ -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 {
|
||||
|
||||
$('<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}`;
|
||||
}
|
||||
13
community/templates/discussions/reply_card.html
Normal file
13
community/templates/discussions/reply_card.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<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="/user/{{ 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>
|
||||
41
community/templates/discussions/reply_section.html
Normal file
41
community/templates/discussions/reply_section.html
Normal file
@@ -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")%}
|
||||
|
||||
<!-- 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 %}
|
||||
9
community/templates/discussions/search.html
Normal file
9
community/templates/discussions/search.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<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>
|
||||
20
community/templates/discussions/sidebar.html
Normal file
20
community/templates/discussions/sidebar.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<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>
|
||||
15
community/templates/discussions/topic_modal.html
Normal file
15
community/templates/discussions/topic_modal.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ widgets.CommentBox(doctype=doctype, docname=docname) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,12 +0,0 @@
|
||||
<div class="common-card-style thread-card mb-5">
|
||||
<div class="mb-4">
|
||||
{% set member = frappe.get_doc("User", message.owner) %}
|
||||
{{ widgets.Avatar(member=member, avatar_class="avatar-small")}}
|
||||
<a class="button-links" href="/users/{{ member.username }}">
|
||||
<span class="message-author">{{ member.full_name }}</span>
|
||||
</a>
|
||||
<span class="muted-text pull-right">{{ frappe.utils.format_datetime(message.creation, "dd MMM hh:mm") }}</span>
|
||||
</div>
|
||||
<div class="card-divider"></div>
|
||||
<div>{{ message.message }}</div>
|
||||
</div>
|
||||
@@ -27,14 +27,9 @@
|
||||
{% if membership %}
|
||||
{{ pagination(prev_url, next_url) }}
|
||||
{% endif %}
|
||||
|
||||
{% set title = lesson.title + " - " + course.title %}
|
||||
{% set condition = membership or is_instructor %}
|
||||
{{ widgets.DiscussionMessage(doctype="Lesson", docname=lesson.name,
|
||||
title=title, condition=condition, button_name="Start Learning",
|
||||
redirect_to="/courses/" + course.name) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ Discussions() }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -96,7 +91,7 @@
|
||||
Next
|
||||
<img class="ml-2" src="/assets/community/icons/side-arrow-white.svg">
|
||||
</a>
|
||||
{% elif course.enable_certification %}
|
||||
{% elif course.enable_certification %}
|
||||
<div class="button is-primary {% if course.get_course_progress() != 100 %} hide {% endif %}" id="certification">
|
||||
Get Certificate
|
||||
</div>
|
||||
@@ -106,6 +101,15 @@
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro Discussions() %}
|
||||
{% set is_instructor = frappe.session.user == course.instructor %}
|
||||
{% set title = lesson.title + " - " + course.title %}
|
||||
{% 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) }}
|
||||
{% endmacro %}
|
||||
|
||||
{%- block script %}
|
||||
{{ super() }}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
{% extends "templates/base.html" %}
|
||||
{% block title %}{{ thread.title }}{% endblock %}
|
||||
{% block head_include %}
|
||||
<style>
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="common-page-style">
|
||||
<div class="container">
|
||||
{{ widgets.BreadCrumb(thread=thread) }}
|
||||
<div class="course-home-headings">{{ thread.title }}</div>
|
||||
{{ widgets.DiscussionMessage(thread=thread.name) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,18 +0,0 @@
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
thread_name = frappe.form_dict["discussion"]
|
||||
except KeyError:
|
||||
redirect_to_discussions()
|
||||
|
||||
context.thread = frappe.db.get_value("Discussion Thread", thread_name, ["name", "title"], as_dict=True)
|
||||
|
||||
if not len(context.thread):
|
||||
redirect_to_discussions
|
||||
|
||||
def redirect_to_discussions():
|
||||
frappe.local.flags.redirect_location = "/discussions"
|
||||
raise frappe.Redirect
|
||||
@@ -1,65 +0,0 @@
|
||||
{% extends "templates/base.html" %}
|
||||
{% block title %}{{ 'Discussions' }}{% endblock %}
|
||||
{% block head_include %}
|
||||
<style>
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="common-page-style">
|
||||
<div class="container">
|
||||
<div class="courses-header">
|
||||
<span>{{_('Discussions')}}</span>
|
||||
<div id="new-topic" class="button is-primary pull-right">
|
||||
<img src="/assets/community/icons/small-add.svg">
|
||||
Start a Discussion</div>
|
||||
</div>
|
||||
<div class="card-divider-dark"></div>
|
||||
{% if threads | length %}
|
||||
<div class="cards-parent">
|
||||
{% for thread in threads %}
|
||||
<div class="common-card-style thread-card">
|
||||
<div class="course-card-title">{{ thread.title }}</div>
|
||||
<div class="card-divider"></div>
|
||||
<div>
|
||||
<span class="course-student-count">
|
||||
<span class="mr-4">
|
||||
<img class="icon-background" src="/assets/community/icons/message.svg" />
|
||||
{{ thread.message_count }}
|
||||
</span>
|
||||
<span class="mr-4">
|
||||
<img class="icon-background" src="/assets/community/icons/user.svg" />
|
||||
{{ thread.member_count }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<a class="stretched-link" href="/discussions/{{ thread.name }}"></a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center font-weight-bold mt-5">
|
||||
No discussions yet.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Topic Modal -->
|
||||
<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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ widgets.DiscussionComment() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,14 +0,0 @@
|
||||
frappe.ready(() => {
|
||||
$("#new-topic").click((e) => {
|
||||
show_new_topic_modal(e);
|
||||
})
|
||||
})
|
||||
|
||||
var show_new_topic_modal = (e) => {
|
||||
e.preventDefault();
|
||||
if (frappe.session.user == "Guest") {
|
||||
window.location.href = `/login?redirect-to=/discussions/`;
|
||||
return;
|
||||
}
|
||||
$("#discussion-modal").modal("show");
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
context.threads = get_threads()
|
||||
|
||||
def get_threads():
|
||||
threads = frappe.get_all("Discussion Thread", fields=["name", "title"])
|
||||
for thread in threads:
|
||||
messages = frappe.get_all("Discussion Message",
|
||||
{
|
||||
"thread": thread.name
|
||||
},
|
||||
["owner"],
|
||||
as_list=True)
|
||||
thread.message_count = len(messages)
|
||||
thread.member_count = len(set(messages))
|
||||
return threads
|
||||
Reference in New Issue
Block a user