Compare commits

..

54 Commits

Author SHA1 Message Date
pateljannat
ff1363b437 fix: certificate, profile, quiz, and video markdown 2021-08-25 21:01:13 +05:30
Jannat Patel
952e3a9906 Merge pull request #190 from fossunited/web-form-changes
fix: web form issues
2021-08-24 21:23:23 +05:30
pateljannat
9d530e35fb fix: web form issues 2021-08-24 20:58:12 +05:30
Jannat Patel
2c2ad78eb7 Merge pull request #189 from sumaiya2908/event-registration
fix: attendee-route
2021-08-24 18:09:27 +05:30
Summayya
f61c5a2fa1 fix: implicit user in speaker and exhibitor 2021-08-24 17:47:58 +05:30
Summayya
3e24ff9678 fix: implicit user 2021-08-24 17:27:16 +05:30
Summayya
b0280c3be4 fix: attendee-route 2021-08-24 16:40:46 +05:30
Jannat Patel
b10eb5c979 Merge pull request #188 from fossunited/talks-thumbnail
fix: talk card schedule
2021-08-24 12:27:13 +05:30
pateljannat
e2072c72da fix: talk card schedule 2021-08-24 12:12:55 +05:30
Jannat Patel
84a43912db Merge pull request #186 from fossunited/fixes
fix: minor issues
2021-08-23 18:52:14 +05:30
pateljannat
841819436a fix: minor issues 2021-08-23 18:22:36 +05:30
pateljannat
14a984c75f Merge branch 'main' of https://github.com/frappe/community into fixes 2021-08-23 11:14:35 +05:30
Jannat Patel
445de61ce4 Merge pull request #185 from fossunited/web-form-url-fixes
fix: web form redirects
2021-08-23 10:32:40 +05:30
pateljannat
f83007788d fix: web form redirects 2021-08-23 10:22:40 +05:30
Jannat Patel
aefee791ca Merge pull request #184 from sumaiya2908/event-management
fix: redirections
2021-08-23 10:21:24 +05:30
Summayya
00154d80df fix: redirections 2021-08-23 10:08:43 +05:30
Summayya
a1e12d29ac fix: redirections 2021-08-23 10:02:06 +05:30
Jannat Patel
5069832165 Merge pull request #183 from fossunited/event-doctype-fixes
fix: event doctypes and templates
2021-08-20 17:41:56 +05:30
pateljannat
e2cb003935 fix: doctypes and templates 2021-08-20 17:35:13 +05:30
Jannat Patel
b83a10c282 Merge pull request #180 from sumaiya2908/event-management
Create web templates for event management
2021-08-20 15:34:48 +05:30
Summayya
c6fc0a22d2 fix: add user to exhibitor doctype 2021-08-20 15:26:47 +05:30
pateljannat
c6d3994383 fix: course page 2021-08-20 14:23:18 +05:30
Summayya
07f9721aeb fix: remove speaker-registration 2021-08-20 13:45:40 +05:30
Summayya
dba956e473 fix: remove speaker-registration 2021-08-20 13:41:11 +05:30
Summayya
2894a5e479 fix: change date format 2021-08-19 17:22:01 +05:30
Summayya
ad0913500c fix: link user to speaker/attendee 2021-08-19 16:08:54 +05:30
Jannat Patel
79a765b725 Merge pull request #182 from fossunited/profile-urls
fix: profile urls
2021-08-19 12:05:59 +05:30
pateljannat
eaec991f47 fix: chapter teaser drawer 2021-08-19 10:06:39 +05:30
pateljannat
e31b189045 fix: profile urls 2021-08-19 09:35:02 +05:30
Summayya
eb58b1c149 fix: remove hover 2021-08-18 23:53:02 +05:30
Summayya
af9760f944 fix: remove div in schedule template 2021-08-18 19:49:12 +05:30
Summayya
21b2412362 fix: remove dummy data 2021-08-18 19:41:37 +05:30
Summayya
7e5e167eec fix: remove dummy data 2021-08-18 19:40:35 +05:30
Jannat Patel
7bf254319b Merge pull request #181 from fossunited/certification
feat: certification
2021-08-18 18:39:12 +05:30
pateljannat
d7e1745c09 fix: added back update progress code 2021-08-18 18:17:40 +05:30
pateljannat
ef238c1b25 fix: export label 2021-08-18 18:08:33 +05:30
pateljannat
cb60d97bb7 feat: certification 2021-08-18 18:04:47 +05:30
Summayya
7c3189e273 fix:conflict 2021-08-18 11:41:09 +05:30
Summayya
ace74febc7 Template for Previous content 2021-08-18 11:37:04 +05:30
Summayya
8dbdabd52c Create web templates for event management 2021-08-17 22:31:15 +05:30
Jannat Patel
f0ee8d7b88 Merge pull request #173 from fossunited/sketch-redesign
fix: sketch cards
2021-08-16 13:47:05 +05:30
Jannat Patel
7e5203f058 Merge pull request #179 from fossunited/discussions
feat: Discussions
2021-08-16 13:45:00 +05:30
pateljannat
a3672e9d91 feat: discussions 2021-08-16 13:33:08 +05:30
pateljannat
7017382451 fix: removed sketch card 2021-08-11 11:40:57 +05:30
pateljannat
6c9d49bf8c discussion doctypes 2021-08-11 11:14:40 +05:30
pateljannat
2de058246b Merge branch 'main' of https://github.com/frappe/community into main 2021-08-11 10:46:11 +05:30
pateljannat
798ea30382 fix: chapter teaser jerk issue 2021-08-11 10:46:01 +05:30
pateljannat
3e2c6b3343 fix: sketch image call 2021-08-10 17:08:32 +05:30
pateljannat
5ea744de5c fix: removed unused file 2021-08-10 16:46:48 +05:30
pateljannat
aedb3d3d45 fix: sketch cards 2021-08-10 16:39:17 +05:30
Jannat Patel
83a2f42df9 Merge pull request #171 from fossunited/username-fixes
fix: username issues
2021-08-10 13:19:29 +05:30
pateljannat
66aace247c fix: conditions and tests 2021-08-10 10:28:59 +05:30
pateljannat
bc3db06960 fix: username issues 2021-08-09 16:54:02 +05:30
Jannat Patel
ddaa063587 Merge pull request #170 from fossunited/upcoming-course-notify
feat: notify me
2021-08-09 15:39:04 +05:30
143 changed files with 10625 additions and 532 deletions

View File

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

View File

@@ -0,0 +1,69 @@
{
"actions": [],
"creation": "2021-08-11 10:59:38.597046",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"thread",
"column_break_2",
"parent_message",
"section_break_4",
"message"
],
"fields": [
{
"fieldname": "message",
"fieldtype": "Long Text",
"in_list_view": 1,
"label": "Message"
},
{
"fieldname": "thread",
"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"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-12 15:59:04.811286",
"modified_by": "Administrator",
"module": "Community",
"name": "Discussion Message",
"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

@@ -0,0 +1,22 @@
# 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)

View File

@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors # Copyright (c) 2021, FOSS United and Contributors
# See license.txt # See license.txt
from __future__ import unicode_literals
# import frappe # import frappe
import unittest import unittest
class TestLMSMessage(unittest.TestCase): class TestDiscussionMessage(unittest.TestCase):
pass pass

View File

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

View File

@@ -0,0 +1,57 @@
{
"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 Thread",
"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

@@ -0,0 +1,48 @@
# 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)

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestDiscussionThread(unittest.TestCase):
pass

View File

@@ -1,5 +1,5 @@
{% set color = member.get_palette() %} {% set color = member.get_palette() %}
<a class="button-links" href="/{{member.username}}"> <a class="button-links" href="/user/{{member.username}}">
<span class="avatar {{ avatar_class }}" title="{{ member.full_name }}"> <span class="avatar {{ avatar_class }}" title="{{ member.full_name }}">
{% if member.user_image %} {% if member.user_image %}
<img class="avatar-frame standard-image" style="object-fit: cover;" src="{{ member.user_image }}" title="{{ member.full_name }}"> <img class="avatar-frame standard-image" style="object-fit: cover;" src="{{ member.user_image }}" title="{{ member.full_name }}">

View File

@@ -0,0 +1,70 @@
<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>

View File

@@ -0,0 +1,80 @@
{% if doctype and docname and not thread %}
{% set thread_info = frappe.get_all("Discussion Thread", {"reference_doctype": doctype, "reference_docname": docname},
["name"]) %}
{% if thread_info | length %}
{% set thread = thread_info[0].name %}
{% 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>

View File

View File

@@ -0,0 +1,14 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Attendee', {
onload: function (frm) {
frm.set_query('user', function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
};
});
}
});

View File

@@ -1,51 +1,47 @@
{ {
"actions": [], "actions": [],
"creation": "2021-03-19 12:19:32.355307", "creation": "2021-08-11 10:07:53.262504",
"doctype": "DocType", "doctype": "DocType",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [ "field_order": [
"author", "user",
"batch", "full_name",
"column_break_3", "column_break_3",
"author_name", "company",
"pin", "is_paid",
"section_break_6", "section_break_6",
"message" "what_are_you_hoping_to_learn"
], ],
"fields": [ "fields": [
{ {
"fieldname": "batch", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Data",
"in_list_view": 1, "label": "Company"
"label": "Batch",
"options": "LMS Batch"
}, },
{ {
"fieldname": "author", "fieldname": "what_are_you_hoping_to_learn",
"fieldtype": "Text",
"label": "What are you hoping to learn?"
},
{
"fieldname": "user",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1, "label": "User",
"label": "Author",
"options": "User" "options": "User"
}, },
{ {
"fieldname": "message", "fetch_from": "user.full_name",
"fieldtype": "Markdown Editor", "fieldname": "full_name",
"in_list_view": 1, "fieldtype": "Data",
"label": "Message" "label": "Full Name",
"read_only": 1
}, },
{ {
"default": "0", "default": "0",
"fieldname": "pin", "fieldname": "is_paid",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Pin" "label": "Is Paid"
},
{
"fetch_from": "author.full_name",
"fieldname": "author_name",
"fieldtype": "Data",
"label": "Author Name",
"read_only": 1
}, },
{ {
"fieldname": "column_break_3", "fieldname": "column_break_3",
@@ -58,10 +54,10 @@
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2021-05-21 11:49:34.911479", "modified": "2021-08-20 17:03:09.741997",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "Event Management",
"name": "LMS Message", "name": "Attendee",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {
@@ -77,9 +73,8 @@
"write": 1 "write": 1
} }
], ],
"quick_entry": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "author", "title_field": "user",
"track_changes": 1 "track_changes": 1
} }

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Attendee(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestAttendee(unittest.TestCase):
pass

View File

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

View File

@@ -0,0 +1,68 @@
{
"actions": [],
"autoname": "field:event_name",
"creation": "2021-08-11 10:05:41.072432",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event_name",
"start_date",
"end_date",
"event_description"
],
"fields": [
{
"fieldname": "event_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Event Name",
"reqd": 1,
"unique": 1
},
{
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Start Date",
"reqd": 1
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "End Date",
"reqd": 1
},
{
"fieldname": "event_description",
"fieldtype": "Markdown Editor",
"in_list_view": 1,
"label": "Event Description"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-18 23:51:30.432691",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Event Details",
"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

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class EventDetails(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestEventDetails(unittest.TestCase):
pass

View File

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

View File

@@ -0,0 +1,55 @@
{
"actions": [],
"creation": "2021-08-11 11:17:28.452289",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event",
"ticket",
"attendee"
],
"fields": [
{
"fieldname": "ticket",
"fieldtype": "Data",
"label": "Ticket"
},
{
"fieldname": "attendee",
"fieldtype": "Link",
"label": "attendee",
"options": "Attendee"
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-20 13:38:28.688115",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Event Ticket",
"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

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class EventTicket(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestEventTicket(unittest.TestCase):
pass

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors // Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('LMS Message', { frappe.ui.form.on('Exhibitor', {
// refresh: function(frm) { // refresh: function(frm) {
// } // }

View File

@@ -0,0 +1,87 @@
{
"actions": [],
"creation": "2021-08-16 16:26:46.189119",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event",
"is_paid",
"column_break_3",
"user",
"full_name",
"company",
"section_break_7",
"description"
],
"fields": [
{
"fetch_from": "user.full_name",
"fieldname": "full_name",
"fieldtype": "Data",
"label": "Full Name",
"read_only": 1
},
{
"fieldname": "company",
"fieldtype": "Data",
"label": "Company "
},
{
"fieldname": "description",
"fieldtype": "Text Editor",
"label": "Description"
},
{
"default": "0",
"fieldname": "is_paid",
"fieldtype": "Check",
"label": "Is Paid"
},
{
"fieldname": "user",
"fieldtype": "Link",
"label": "User",
"options": "User"
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details"
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_7",
"fieldtype": "Section Break"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-20 16:32:58.031324",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Exhibitor",
"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",
"title_field": "user",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Exhibitor(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestExhibitor(unittest.TestCase):
pass

View File

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

View File

@@ -0,0 +1,57 @@
{
"actions": [],
"creation": "2021-08-11 10:51:47.234690",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event",
"user",
"full_name"
],
"fields": [
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details"
},
{
"fieldname": "full_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Full Name",
"unique": 1
},
{
"fieldname": "user",
"fieldtype": "Data",
"label": "User"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-20 17:03:26.733195",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Host",
"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",
"title_field": "user",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Host(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestHost(unittest.TestCase):
pass

View File

@@ -0,0 +1,14 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Speaker', {
onload: function (frm) {
frm.set_query('user', function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
};
});
}
});

View File

@@ -0,0 +1,72 @@
{
"actions": [],
"creation": "2021-08-11 10:37:32.124651",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event",
"company",
"column_break_8",
"user",
"full_name"
],
"fields": [
{
"fieldname": "user",
"fieldtype": "Link",
"in_list_view": 1,
"label": "User",
"options": "User"
},
{
"fetch_from": "user.full_name",
"fieldname": "full_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Full Name",
"read_only": 1
},
{
"fieldname": "company",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Company"
},
{
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-20 16:53:43.968260",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Speaker",
"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",
"title_field": "user",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Speaker(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestSpeaker(unittest.TestCase):
pass

View File

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

View File

@@ -0,0 +1,139 @@
{
"actions": [],
"creation": "2021-08-18 08:42:58.711932",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"event",
"title",
"url",
"column_break_5",
"speaker",
"category",
"thumbnail",
"schedule_section",
"date",
"status",
"column_break_11",
"start_time",
"end_time",
"section_break_9",
"about",
"attachment",
"name_of_the_speaker"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "name_of_the_speaker",
"fieldtype": "Data",
"label": "Name of the Speaker"
},
{
"fieldname": "url",
"fieldtype": "Data",
"label": "Video Embed Link"
},
{
"fieldname": "thumbnail",
"fieldtype": "Attach",
"label": "Preview Image"
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details"
},
{
"fieldname": "about",
"fieldtype": "Text",
"label": "About the Talk"
},
{
"fieldname": "attachment",
"fieldtype": "Attach",
"label": "Attachment"
},
{
"fieldname": "speaker",
"fieldtype": "Link",
"label": "Speaker",
"options": "Speaker"
},
{
"default": "Pending",
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Status",
"options": "Pending\nApproved\nRejected"
},
{
"fieldname": "column_break_5",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_9",
"fieldtype": "Section Break"
},
{
"fieldname": "category",
"fieldtype": "Data",
"label": "Category"
},
{
"fieldname": "schedule_section",
"fieldtype": "Section Break"
},
{
"fieldname": "date",
"fieldtype": "Date",
"label": "Date"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"fieldname": "start_time",
"fieldtype": "Time",
"label": "Start Time"
},
{
"fieldname": "end_time",
"fieldtype": "Time",
"label": "End Time"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-24 16:47:34.557010",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Talk",
"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",
"title_field": "title",
"track_changes": 1
}

View File

@@ -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
class Talk(Document):
def before_save(self):
if not self.speaker:
self.save_speaker()
def save_speaker(self):
exists = frappe.db.exists({
'doctype': 'Speaker',
'user': frappe.session.user
})
if exists:
self.speaker = frappe.db.get_value(
'Speaker', {'user': frappe.session.user}, ["name"])
else:
speaker = frappe.get_doc({
"doctype": "Speaker",
"event": self.event,
"user": frappe.session.user
})
speaker.save(ignore_permissions=True)
self.speaker = speaker.name

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestTalk(unittest.TestCase):
pass

View File

@@ -0,0 +1,11 @@
frappe.ready(function () {
frappe.web_form.after_load = () => {
frappe.web_form.set_value("user", frappe.session.user);
}
frappe.web_form.after_save = () => {
setTimeout(function () {
window.location.href = '/about';
}, 2000);
}
})

View File

@@ -0,0 +1,77 @@
{
"accept_payment": 0,
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 0,
"allow_incomplete": 0,
"allow_multiple": 0,
"allow_print": 0,
"amount": 0.0,
"amount_based_on_field": 0,
"apply_document_permissions": 0,
"button_label": "",
"creation": "2021-08-19 15:26:56.594526",
"custom_css": "[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
"doc_type": "Attendee",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2021-08-24 19:57:25.516319",
"modified_by": "Administrator",
"module": "Event Management",
"name": "attendee-registration",
"owner": "Administrator",
"payment_button_label": "Buy Now",
"published": 1,
"route": "attendee-registration",
"route_to_success_link": 1,
"show_attachments": 0,
"show_in_grid": 0,
"show_sidebar": 0,
"sidebar_items": [],
"success_url": "/about",
"title": "Attendee Registration",
"web_form_fields": [
{
"allow_read_on_all_link_options": 0,
"default": "",
"fieldname": "user",
"fieldtype": "Data",
"hidden": 0,
"label": "User",
"max_length": 0,
"max_value": 0,
"options": "User",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "company",
"fieldtype": "Data",
"hidden": 0,
"label": "Company",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "what_are_you_hoping_to_learn",
"fieldtype": "Text",
"hidden": 0,
"label": "What are you hoping to learn",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
}
]
}

View File

@@ -0,0 +1,5 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -0,0 +1,12 @@
frappe.ready(function () {
frappe.web_form.after_load = () => {
frappe.web_form.set_value("user", frappe.session.user);
}
frappe.web_form.after_save = () => {
setTimeout(function () {
window.location.href = '/about';
}, 2000);
}
})

View File

@@ -0,0 +1,76 @@
{
"accept_payment": 0,
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 0,
"allow_incomplete": 0,
"allow_multiple": 0,
"allow_print": 0,
"amount": 0.0,
"amount_based_on_field": 0,
"apply_document_permissions": 0,
"button_label": "Save",
"creation": "2021-08-16 16:27:06.566564",
"custom_css": "[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
"doc_type": "Exhibitor",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2021-08-23 10:12:24.038572",
"modified_by": "Administrator",
"module": "Event Management",
"name": "exhibitor-registration",
"owner": "Administrator",
"payment_button_label": "Buy Now",
"published": 1,
"route": "exhibitor-registration",
"route_to_success_link": 0,
"show_attachments": 0,
"show_in_grid": 0,
"show_sidebar": 0,
"sidebar_items": [],
"success_url": "",
"title": "Exhibitor Registration",
"web_form_fields": [
{
"allow_read_on_all_link_options": 0,
"fieldname": "user",
"fieldtype": "Data",
"hidden": 0,
"label": "User",
"max_length": 0,
"max_value": 0,
"options": "User",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "company",
"fieldtype": "Data",
"hidden": 0,
"label": "Company ",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
"label": "Description",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
}
]
}

View File

@@ -0,0 +1,5 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -0,0 +1,11 @@
frappe.ready(function () {
frappe.web_form.after_load = () => {
frappe.web_form.set_value("user", frappe.session.user);
}
frappe.web_form.after_save = () => {
setTimeout(function () {
window.location.href = '/about';
}, 2000);
}
})

View File

@@ -0,0 +1,102 @@
{
"accept_payment": 0,
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 0,
"allow_incomplete": 0,
"allow_multiple": 0,
"allow_print": 0,
"amount": 0.0,
"amount_based_on_field": 0,
"apply_document_permissions": 0,
"button_label": "Submit",
"client_script": "",
"creation": "2021-08-19 15:16:22.341723",
"custom_css": "[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
"doc_type": "Talk",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2021-08-24 19:57:06.806994",
"modified_by": "Administrator",
"module": "Event Management",
"name": "purpose-a-talk",
"owner": "Administrator",
"payment_button_label": "Buy Now",
"published": 1,
"route": "propose-talk",
"route_to_success_link": 0,
"show_attachments": 0,
"show_in_grid": 0,
"show_sidebar": 0,
"sidebar_items": [],
"success_message": "Talk Submitted!",
"success_url": "/purpose-a-talk",
"title": "Propose a Talk",
"web_form_fields": [
{
"allow_read_on_all_link_options": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"label": "Title",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 1,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "category",
"fieldtype": "Data",
"hidden": 0,
"label": "Category",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "event",
"fieldtype": "Data",
"hidden": 0,
"label": "Event",
"max_length": 0,
"max_value": 0,
"options": "Event Details",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "thumbnail",
"fieldtype": "Attach",
"hidden": 0,
"label": "Preview Image",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "about",
"fieldtype": "Text Editor",
"hidden": 0,
"label": "About",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 1,
"show_in_filter": 0
}
]
}

View File

@@ -0,0 +1,5 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -0,0 +1,10 @@
frappe.ready(function () {
frappe.web_form.after_load = () => {
frappe.web_form.set_value("user", frappe.session.user);
}
frappe.web_form.after_save = () => {
setTimeout(function () {
window.location.href = '/event/conference2021/propose-talk';
}, 2000);
}
})

View File

@@ -0,0 +1,89 @@
{
"accept_payment": 0,
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 0,
"allow_incomplete": 0,
"allow_multiple": 0,
"allow_print": 0,
"amount": 0.0,
"amount_based_on_field": 0,
"apply_document_permissions": 0,
"button_label": "Register",
"creation": "2021-08-19 15:29:01.167930",
"custom_css": "[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
"doc_type": "Speaker",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2021-08-20 16:16:51.107177",
"modified_by": "Administrator",
"module": "Event Management",
"name": "speaker-registration",
"owner": "Administrator",
"payment_button_label": "Buy Now",
"published": 1,
"route": "speaker-registration",
"route_to_success_link": 1,
"show_attachments": 0,
"show_in_grid": 0,
"show_sidebar": 0,
"sidebar_items": [],
"success_url": "/speaker-registration",
"title": "Speaker Registration",
"web_form_fields": [
{
"allow_read_on_all_link_options": 0,
"fieldname": "event",
"fieldtype": "Link",
"hidden": 0,
"label": "Event",
"max_length": 0,
"max_value": 0,
"options": "Event Details",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"label": "User",
"max_length": 0,
"max_value": 0,
"options": "User",
"read_only": 1,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "full_name",
"fieldtype": "Data",
"hidden": 0,
"label": "Full Name",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 0,
"show_in_filter": 0
},
{
"allow_read_on_all_link_options": 0,
"fieldname": "company",
"fieldtype": "Data",
"hidden": 0,
"label": "Company",
"max_length": 0,
"max_value": 0,
"read_only": 0,
"reqd": 1,
"show_in_filter": 0
}
]
}

View File

@@ -0,0 +1,5 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -0,0 +1,28 @@
<div class="section-with-cards">
<h1 class="course-home-headings">{{title}}</h1>
{%- if subtitle -%}
<p class="section-description">{{ subtitle }}</p>
{%- endif -%}
<div>
<div class="mentors-section">
{% for exhibitor in exhibitor_details %}
{% set exhibitor_doc = frappe.db.get_value("Exhibitor", exhibitor.exhibitor, ["user", "company"], as_dict= True)
%}
{% set member = frappe.get_doc("User", exhibitor_doc.user) %}
<div class="common-card-style member-card">
{{ widgets.Avatar(member=member, avatar_class="avatar-large")}}
<div class="small-title member-card-title">
{{ member.full_name }}
</div>
<div class="small-title">
{{exhibitor_doc.company}}
</div>
<a class="stretched-link" href=""></a>
</div>
{% endfor %}
</div>
<div class="event-btn"><a href="/exhibitor-registration?new=1&user={{ frappe.session.user }}&event={{ event }}"
class="btn btn-primary ">Become an Exhibitor</a></div>
</div>
</div>

View File

@@ -0,0 +1,49 @@
{
"__unsaved": 1,
"creation": "2021-08-13 15:05:41.606772",
"docstatus": 0,
"doctype": "Web Template",
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"reqd": 0
},
{
"fieldname": "subtitle",
"fieldtype": "Data",
"label": "Subtitle",
"reqd": 0
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details",
"reqd": 0
},
{
"fieldname": "exhibitor_details",
"fieldtype": "Table Break",
"label": "Exhibitor Details",
"reqd": 0
},
{
"fieldname": "exhibitor",
"fieldtype": "Link",
"label": "Exhibitor",
"options": "Exhibitor",
"reqd": 0
}
],
"idx": 1,
"modified": "2021-08-20 16:28:22.779057",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Exhibitor Section",
"owner": "Administrator",
"standard": 1,
"template": "",
"type": "Section"
}

View File

@@ -0,0 +1,3 @@
<div class="section-with-cards">
<h1 class="course-home-headings">{{title}}</h1>
</div>

View File

@@ -0,0 +1,43 @@
{
"__unsaved": 1,
"creation": "2021-08-20 08:12:29.549625",
"docstatus": 0,
"doctype": "Web Template",
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"reqd": 0
},
{
"fieldname": "subtitle",
"fieldtype": "Data",
"label": "Subtitle",
"reqd": 0
},
{
"__unsaved": 1,
"fieldname": "hosts",
"fieldtype": "Table Break",
"label": "Hosts",
"reqd": 0
},
{
"fieldname": "host",
"fieldtype": "Link",
"label": "Host",
"options": "Host",
"reqd": 0
}
],
"idx": 0,
"modified": "2021-08-20 08:16:25.805456",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Host Section",
"owner": "Administrator",
"standard": 1,
"template": "",
"type": "Section"
}

View File

@@ -0,0 +1,30 @@
<div class="section-with-cards">
<h1 class="course-home-headings">{{section_title}}</h1>
{%- if subtitle -%}
<p class="section-description">{{ subtitle }}</p>
{%- endif -%}
<div class="mentors-section">
{% for speaker in speaker_details %}
{% set speaker_doc = frappe.db.get_value("Speaker", speaker.speaker, ["user", "company"], as_dict= True)
%}
{% set member = frappe.get_doc("User", speaker_doc.user) %}
<div class="common-card-style member-card">
{{ widgets.Avatar(member=member, avatar_class="avatar-large") }}
<div class="small-title member-card-title">
{{ member.full_name }}
</div>
<div class="small-title">
{{speaker_doc.company}}
</div>
<a class="stretched-link" href=""></a>
</div>
{% endfor %}
</div>
<div class="event-btn">
<a href='/propose-talk?new=1&event={{ event }}' class="btn btn-primary ">Propose a Talk</a>
</div>
</div>

View File

@@ -0,0 +1,49 @@
{
"__unsaved": 1,
"creation": "2021-08-12 21:15:14.492000",
"docstatus": 0,
"doctype": "Web Template",
"fields": [
{
"fieldname": "section_title",
"fieldtype": "Data",
"label": "Section Title",
"reqd": 1
},
{
"fieldname": "subtitle",
"fieldtype": "Data",
"label": "Subtitle",
"reqd": 0
},
{
"fieldname": "event_",
"fieldtype": "Link",
"label": "Event ",
"options": "Event Details",
"reqd": 0
},
{
"fieldname": "speaker_details",
"fieldtype": "Table Break",
"label": "Speaker Details",
"reqd": 0
},
{
"fieldname": "speaker",
"fieldtype": "Link",
"label": "Speaker",
"options": "Speaker",
"reqd": 0
}
],
"idx": 1,
"modified": "2021-08-20 10:59:54.965714",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Speaker Section",
"owner": "Administrator",
"standard": 1,
"template": "",
"type": "Section"
}

View File

@@ -0,0 +1,75 @@
<div class="section-with-cards">
<div class="course-home-headings">{{title}}</div>
{%- if subtitle -%}
<p class="section-description">{{ subtitle }}</p>
{%- endif -%}
<div class="cards-parent">
{% for talk in talk_details %}
{% set talk_doc = frappe.db.get_value('Talk', talk.talk,
["title", "category", "speaker", "url", "thumbnail", "date", "start_time", "end_time"], as_dict=True) %}
{% set speaker_info = frappe.db.get_value("Speaker", talk_doc.speaker, ["user"], as_dict=True) %}
{% set member = frappe.get_doc("User", speaker_info.user) %}
{% if talk_doc.thumbnail %}
{% set thumbnail = talk_doc.thumbnail %}
{% else %}
{% set video_id = talk_doc.url and talk_doc.url.split("/")[-1] %}
{% set thumbnail = video_id and "https://img.youtube.com/vi/" + video_id + "/maxresdefault.jpg" %}
{% endif %}
<div class="common-card-style flex-column">
<div class="course-image {% if not thumbnail %}default-image{% endif %}" {% if thumbnail %}
style="background-image: url( {{ thumbnail }} );" {% endif %}>
<div class="course-tags">
{% for tag in talk_doc.category.split(",") %}
<div class="course-card-pills">{{ tag }}</div>
{% endfor %}
</div>
{% if not thumbnail %}
<div class="default-image-text">{{ talk_doc.title[0] }}</div>
{% endif %}
</div>
<div class="course-card-content">
<div class="course-card-content"></div>
<div class="course-card-title">{{talk_doc.title}}</div>
<div class="muted-text mb-3">
{% if talk_doc.date %}
<span>
<img src="/assets/community/icons/calendar.svg">
{{ frappe.utils.format_date(talk_doc.date, "medium") }}
</span>
{% endif %}
<span class="pull-right">
{% if talk_doc.start_time %}
<span class="mr-3">
<b>From:</b>
{{ frappe.utils.format_time(talk_doc.start_time, "HH:mm") }}
</span>
{% endif %}
{% if talk_doc.end_time %}
<span>
<b>To:</b>
{{ frappe.utils.format_time(talk_doc.end_time, "HH:mm") }}
</span>
{% endif %}
</span>
</div>
<div class="card-divider"></div>
<div class="course-card-meta-2">
{{ widgets.Avatar(member=member, avatar_class="avatar-small")}}
<span class="course-instructor"> {{ member.full_name }} </span>
<span class="small-title company-name"></span>
</div>
<div class="view-talk-link">
Vew Talk
<img class="ml-3" src="/assets/community/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="{{talk_doc.url}}"></a>
</div>
</div>
{% endfor %}
</div>
</div>

View File

@@ -0,0 +1,49 @@
{
"__unsaved": 1,
"creation": "2021-08-13 11:34:07.611034",
"docstatus": 0,
"doctype": "Web Template",
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"reqd": 1
},
{
"fieldname": "subtitle",
"fieldtype": "Data",
"label": "Subtitle",
"reqd": 0
},
{
"fieldname": "event",
"fieldtype": "Link",
"label": "Event",
"options": "Event Details",
"reqd": 1
},
{
"fieldname": "talk_details",
"fieldtype": "Table Break",
"label": "Talk Details",
"reqd": 0
},
{
"fieldname": "talk",
"fieldtype": "Link",
"label": "Talk",
"options": "Talk",
"reqd": 0
}
],
"idx": 1,
"modified": "2021-08-20 10:58:45.556636",
"modified_by": "Administrator",
"module": "Event Management",
"name": "Talk Section",
"owner": "Administrator",
"standard": 1,
"template": "",
"type": "Section"
}

View File

@@ -85,7 +85,8 @@ web_include_css = "community.bundle.css"
# Override standard doctype classes # Override standard doctype classes
override_doctype_class = { override_doctype_class = {
"User": "community.overrides.user.CustomUser" "User": "community.overrides.user.CustomUser",
"Web Template": "community.overrides.web_template.CustomWebTemplate"
} }
# Document Events # Document Events
@@ -130,56 +131,28 @@ fixtures = ["Custom Field"]
# auto_cancel_exempted_doctypes = ["Auto Repeat"] # auto_cancel_exempted_doctypes = ["Auto Repeat"]
# Add all simple route rules here # Add all simple route rules here
primary_rules = [ website_route_rules = [
{"from_route": "/sketches/<sketch>", "to_route": "sketches/sketch"}, {"from_route": "/sketches/<sketch>", "to_route": "sketches/sketch"},
{"from_route": "/courses/<course>", "to_route": "courses/course"}, {"from_route": "/courses/<course>", "to_route": "courses/course"},
{"from_route": "/courses/<course>/<topic>", "to_route": "courses/topic"}, {"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
{"from_route": "/hackathons/<hackathon>", "to_route": "hackathons/hackathon"}, {"from_route": "/hackathons/<hackathon>", "to_route": "hackathons/hackathon"},
{"from_route": "/hackathons/<hackathon>/<project>", "to_route": "hackathons/project"}, {"from_route": "/hackathons/<hackathon>/<project>", "to_route": "hackathons/project"},
{"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"}, {"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"},
{"from_route": "/courses/<course>/home", "to_route": "batch/home"}, {"from_route": "/courses/<course>/home", "to_route": "batch/home"},
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"}, {"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
{"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>", "to_route": "batch/learn"}, {"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>", "to_route": "batch/learn"},
{"from_route": "/courses/<course>/schedule", "to_route": "batch/schedule"}, {"from_route": "/courses/<course>/schedule", "to_route": "batch/schedule"},
{"from_route": "/courses/<course>/members", "to_route": "batch/members"}, {"from_route": "/courses/<course>/members", "to_route": "batch/members"},
{"from_route": "/courses/<course>/discuss", "to_route": "batch/discuss"}, {"from_route": "/courses/<course>/discuss", "to_route": "batch/discuss"},
{"from_route": "/courses/<course>/about", "to_route": "batch/about"}, {"from_route": "/courses/<course>/about", "to_route": "batch/about"},
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"}, {"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
{"from_route": "/courses/<course>/join", "to_route": "batch/join"} {"from_route": "/courses/<course>/join", "to_route": "batch/join"},
{"from_route": "/discussions/<discussion>", "to_route": "discussions/discussion"},
{"from_route": "/user/<string(minlength=4):username>", "to_route": "profiles/profile"},
] ]
# Any frappe default URL is blocked by profile-rules, add it here to unblock it
whitelist = [
"/home",
"/login",
"/update-password",
"/update-profile",
"/third-party-apps",
"/website_script.js",
"/courses",
"/sketches",
"/admin",
"/socket.io",
"/hackathons",
"/dashboard",
"/join-request",
"/add-a-new-batch",
"/new-sign-up",
"/message",
"/about",
"/edit-profile"
]
whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist]
# regex rule to match all profiles
profile_rules = [
{"from_route": "/<string(minlength=4):username>", "to_route": "profiles/profile"},
]
website_route_rules = primary_rules + whitelist_rules + profile_rules
website_redirects = [ website_redirects = [
{"source": "/update-profile", "target": "/edit-profile"}, {"source": "/update-profile", "target": "/edit-profile"},
] ]
update_website_context = 'community.widgets.update_website_context' update_website_context = 'community.widgets.update_website_context'
@@ -202,4 +175,5 @@ community_markdown_macro_renderers = {
"Exercise": "community.plugins.exercise_renderer", "Exercise": "community.plugins.exercise_renderer",
"Quiz": "community.plugins.quiz_renderer", "Quiz": "community.plugins.quiz_renderer",
"YouTubeVideo": "community.plugins.youtube_video_renderer", "YouTubeVideo": "community.plugins.youtube_video_renderer",
"Video": "community.plugins.video_renderer"
} }

View File

@@ -8,7 +8,9 @@
"field_order": [ "field_order": [
"course", "course",
"title", "title",
"column_break_3",
"description", "description",
"section_break_5",
"lessons" "lessons"
], ],
"fields": [ "fields": [
@@ -20,7 +22,7 @@
}, },
{ {
"fieldname": "description", "fieldname": "description",
"fieldtype": "Markdown Editor", "fieldtype": "Small Text",
"label": "Description" "label": "Description"
}, },
{ {
@@ -35,6 +37,14 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Lessons", "label": "Lessons",
"options": "Lessons" "options": "Lessons"
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_5",
"fieldtype": "Section Break"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
@@ -45,7 +55,7 @@
"link_fieldname": "chapter" "link_fieldname": "chapter"
} }
], ],
"modified": "2021-07-27 16:28:08.667964", "modified": "2021-08-19 13:43:51.025072",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Chapter", "name": "Chapter",

View File

@@ -3,11 +3,6 @@
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
from ..lesson.lesson import update_progress
class ExerciseSubmission(Document): class ExerciseSubmission(Document):
pass
def after_insert(self):
course_details = frappe.get_doc("LMS Course", self.course)
if not (course_details.is_mentor(frappe.session.user) or frappe.flags.in_test):
update_progress(self.lesson)

View File

@@ -17,6 +17,15 @@ frappe.ui.form.on('Lesson', {
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col-sm-4">
Video
</div>
<div class="col-sm-4">
{{ Video("url_of_source") }}
</div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-sm-4"> <div class="col-sm-4">
YouTube Video YouTube Video

View File

@@ -91,42 +91,5 @@ def save_progress(lesson, course, status):
"lesson": lesson, "lesson": lesson,
"status": status, "status": status,
}).save(ignore_permissions=True) }).save(ignore_permissions=True)
return "OK" course_details = frappe.get_doc("LMS Course", course)
return course_details.get_course_progress()
def update_progress(lesson):
user = frappe.session.user
if not all_dynamic_content_submitted(lesson, user):
return
if frappe.db.exists("LMS Course Progress", {"lesson": lesson, "owner": user}):
course_progress = frappe.get_doc("LMS Course Progress", {"lesson": lesson, "owner": user})
course_progress.status = "Complete"
course_progress.save(ignore_permissions=True)
def all_dynamic_content_submitted(lesson, user):
all_exercises_submitted = check_all_exercise_submission(lesson, user)
all_quiz_submitted = check_all_quiz_submitted(lesson, user)
return all_exercises_submitted and all_quiz_submitted
def check_all_exercise_submission(lesson, user):
exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, pluck="name", ignore_permissions=True)
if not len(exercise_names):
return True
query = {
"exercise": ["in", exercise_names],
"owner": user
}
if frappe.db.count("Exercise Submission", query) == len(exercise_names):
return True
return False
def check_all_quiz_submitted(lesson, user):
quizzes = frappe.get_list("LMS Quiz", {"lesson": lesson}, pluck="name", ignore_permissions=True)
if not len(quizzes):
return True
query = {
"quiz": ["in", quizzes],
"owner": user
}
if frappe.db.count("LMS Quiz Submission", query) == len(quizzes):
return True
return False

View File

@@ -35,14 +35,6 @@ class LMSBatch(Document):
filters['member_type'] = member_type filters['member_type'] = member_type
return frappe.db.exists("LMS Batch Membership", filters) return frappe.db.exists("LMS Batch Membership", filters)
def get_messages(self):
messages = frappe.get_all("LMS Message", {"batch": self.name}, ["*"], order_by="creation")
for message in messages:
message.message = frappe.utils.md_to_html(message.message)
if message.author == frappe.session.user:
message.author_name = "You"
message.is_author = True
return messages
def get_membership(self, email): def get_membership(self, email):
"""Returns the membership document of given user. """Returns the membership document of given user.

View File

@@ -0,0 +1,14 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Certification', {
onload: function (frm) {
frm.set_query("student", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
};
});
}
});

View File

@@ -0,0 +1,70 @@
{
"actions": [],
"creation": "2021-08-16 15:47:19.494055",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"student",
"issue_date",
"column_break_3",
"course",
"expiry_date"
],
"fields": [
{
"fieldname": "student",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Student",
"options": "User"
},
{
"fieldname": "issue_date",
"fieldtype": "Date",
"label": "Issue Date"
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "course",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Course",
"options": "LMS Course"
},
{
"fieldname": "expiry_date",
"fieldtype": "Date",
"label": "Expiry Date"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-16 15:47:19.494055",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Certification",
"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

@@ -0,0 +1,45 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe.utils import nowdate, add_years
from frappe import _
from frappe.utils.pdf import get_pdf
class LMSCertification(Document):
def validate(self):
certificates = frappe.get_all("LMS Certification", {
"student": self.student,
"course": self.course,
"expiry_date": [">", nowdate()]
})
if len(certificates):
full_name = frappe.db.get_value("User", self.student, "full_name")
course_name = frappe.db.get_value("LMS Course", self.course, "title")
frappe.throw(_("There is already a valid certificate for user {0} for the course {1}").format(full_name, course_name))
@frappe.whitelist()
def create_certificate(course):
course_details = frappe.get_doc("LMS Course", course)
certificate = course_details.is_certified()
if certificate:
return certificate
else:
expires_after_yrs = int(course_details.expiry)
expiry_date = None
if expires_after_yrs:
expiry_date = add_years(nowdate(), expires_after_yrs)
certificate = frappe.get_doc({
"doctype": "LMS Certification",
"student": frappe.session.user,
"course": course,
"issue_date": nowdate(),
"expiry_date": expiry_date
})
certificate.save(ignore_permissions=True)
return certificate.name

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestLMSCertification(unittest.TestCase):
pass

View File

@@ -4,6 +4,7 @@
frappe.ui.form.on('LMS Course', { frappe.ui.form.on('LMS Course', {
onload: function (frm) { onload: function (frm) {
frm.set_query("chapter", "chapters", function () { frm.set_query("chapter", "chapters", function () {
return { return {
filters: { filters: {
@@ -11,6 +12,14 @@ frappe.ui.form.on('LMS Course', {
} }
}; };
}); });
frm.set_query("instructor", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
};
});
} }
}); });

View File

@@ -18,14 +18,21 @@
"video_link", "video_link",
"image", "image",
"column_break_3", "column_break_3",
"instructor",
"tags", "tags",
"section_break_7",
"is_published", "is_published",
"column_break_9",
"upcoming", "upcoming",
"column_break_11",
"disable_self_learning", "disable_self_learning",
"section_break_5", "section_break_5",
"short_introduction", "short_introduction",
"description", "description",
"chapters" "chapters",
"certification_section",
"enable_certification",
"expiry"
], ],
"fields": [ "fields": [
{ {
@@ -94,6 +101,46 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Chapters", "label": "Chapters",
"options": "Chapters" "options": "Chapters"
},
{
"fieldname": "instructor",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Instructor",
"options": "User"
},
{
"fieldname": "section_break_7",
"fieldtype": "Section Break",
"label": "Course Settings"
},
{
"fieldname": "column_break_9",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"fieldname": "certification_section",
"fieldtype": "Section Break",
"label": "Certification"
},
{
"default": "0",
"fieldname": "enable_certification",
"fieldtype": "Check",
"label": "Enable Certification"
},
{
"default": "0",
"depends_on": "enable_certification",
"fieldname": "expiry",
"fieldtype": "Select",
"label": "Certification Expires After Years",
"options": "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
@@ -115,7 +162,7 @@
"link_fieldname": "course" "link_fieldname": "course"
} }
], ],
"modified": "2021-07-28 19:01:50.677445", "modified": "2021-08-25 11:04:57.211898",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Course", "name": "LMS Course",

View File

@@ -144,6 +144,8 @@ class LMSCourse(Document):
return batch_name and frappe.get_doc("LMS Batch", batch_name) return batch_name and frappe.get_doc("LMS Batch", batch_name)
def get_instructor(self): def get_instructor(self):
if self.instructor:
return frappe.get_doc("User", self.instructor)
return frappe.get_doc("User", self.owner) return frappe.get_doc("User", self.owner)
def get_chapters(self): def get_chapters(self):
@@ -347,6 +349,16 @@ class LMSCourse(Document):
"next": numbers[index+1] if index+1 < len(numbers) else None "next": numbers[index+1] if index+1 < len(numbers) else None
} }
def is_certified(self):
certificate = frappe.get_all("LMS Certification",
{
"student": frappe.session.user,
"course": self.name
})
if len(certificate):
return certificate[0].name
return
@frappe.whitelist() @frappe.whitelist()
def reindex_exercises(doc): def reindex_exercises(doc):
course_data = json.loads(doc) course_data = json.loads(doc)

View File

@@ -1,110 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.utils import add_days, nowdate
class LMSMessage(Document):
def after_insert(self):
self.publish_message()
#Todo: Adding email preference field for users
#self.send_email()
def publish_message(self):
template = self.get_message_template()
message = frappe._dict({
"author_name": self.author_name,
"message_time": frappe.utils.format_datetime(self.creation, "dd-mm-yyyy HH:mm"),
"message": frappe.utils.md_to_html(self.message)
})
js = """
$(".msger-input").val("");
var template = `{0}`;
var message = {1};
var session_user = ("{2}" == frappe.session.user) ? true : false;
message.author_name = session_user ? "You" : message.author_name
message.is_author = session_user;
template = frappe.render_template(template, {{
"message": message
}})
$(".messages").append(template);
var message_element = document.getElementsByClassName("messages")[0]
message_element.scrollTo(0, message_element.scrollHeight);
""".format(template, message, self.owner)
frappe.publish_realtime(event="eval_js", message=js, after_commit=True)
def get_message_template(self):
return """
<li class="{% if message.is_author %} ours {% endif %}">
<div class="d-flex justify-content-between">
<div class="font-weight-bold">
{{ message.author_name }}
</div>
<small class="">
{{ message.message_time }}
</small>
</div>
<div class="message-para">
{{ message.message }}
</div>
</li>
"""
def send_email(self):
membership = frappe.get_all("LMS Batch Membership", {"batch": self.batch}, ["member"])
for entry in membership:
member = frappe.get_doc("User", entry.member)
if member.name != self.author:
#Todo: wrap sendmail in frappe.enqueue, else messages takes long to display.
frappe.sendmail(
recipients = member.email,
subject = _("New Message on ") + self.batch,
header = _("New Message on ") + self.batch,
template = "lms_message",
args = {
"author": self.author,
"message": frappe.utils.md_to_html(self.message),
"creation": frappe.utils.format_datetime(self.creation, "medium"),
"course": frappe.db.get_value("LMS Batch", self.batch, ["course"])
}
)
def send_daily_digest():
#Todo: Optimize this
emails = frappe._dict()
messages = frappe.get_all("LMS Message", {"creation": [">=", add_days(nowdate(), -1)]}, ["message", "batch", "author", "creation"])
for message in messages:
membership = frappe.get_all("LMS Batch Membership", {"batch": message.batch}, ["member"])
for entry in membership:
member = frappe.db.get_value("User", entry.member, ["name", "email"], as_dict=1)
if member.name != message.author:
if member.name in emails.keys():
emails[member.name]["messages"].append(message)
else:
emails[member.name] = frappe._dict({
"email": member.email,
"messages": [message]
})
for email in emails:
group_by_batch = frappe._dict()
for message in emails[email]["messages"]:
if message.batch in group_by_batch.keys():
group_by_batch[message.batch].append(message)
else:
group_by_batch[message.batch] = [message]
frappe.sendmail(
recipients = frappe.db.get_value("User", email, "email"),
subject = _("Message Digest"),
header = _("Message Digest"),
template = "lms_daily_digest",
args = {
"batches": group_by_batch
},
delayed = False
)

View File

@@ -1,12 +1,10 @@
# Copyright (c) 2021, FOSS United and contributors # Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt # For license information, please see license.txt
from community.lms.doctype.lesson.lesson import update_progress
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
import json import json
from frappe import _ from frappe import _
from ..lesson.lesson import update_progress
class LMSQuiz(Document): class LMSQuiz(Document):
def validate(self): def validate(self):

View File

@@ -20,6 +20,7 @@ import markdown
from markdown import Extension from markdown import Extension
from markdown.inlinepatterns import InlineProcessor from markdown.inlinepatterns import InlineProcessor
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
import html as HTML
def markdown_to_html(text): def markdown_to_html(text):
"""Renders markdown text into html. """Renders markdown text into html.
@@ -109,4 +110,5 @@ def sanitize_html(html, macro):
classname = "" classname = ""
if macro == "YouTubeVideo": if macro == "YouTubeVideo":
classname = "lesson-video" classname = "lesson-video"
return "<div class='" + classname + "'>" + "\n".join(str(node) for node in nodes) + "</div>" return "<div class='" + classname + "'>" + "\n".join(str(node) for node in nodes) + "</div>"

View File

@@ -8,7 +8,7 @@ frappe.ready(function () {
frappe.web_form.after_save = () => { frappe.web_form.after_save = () => {
setTimeout(() => { setTimeout(() => {
window.location.href = `/${frappe.web_form.get_value(["username"])}`; window.location.href = `/user/${frappe.web_form.get_value(["username"])}`;
}) })
} }
}) })

View File

@@ -1,8 +1,9 @@
<div class="breadcrumb"> <div class="breadcrumb">
<a class="dark-links" href="/courses">All Courses</a>
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
{% if course %} {% 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 %} {% if lesson %}
<a class="dark-links" href="/courses/{{ course.name }}">{{ course.title }}</a> <a class="dark-links" href="/courses/{{ course.name }}">{{ course.title }}</a>
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg"> <img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
@@ -12,8 +13,9 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if member_name %} {% if thread %}
<span class="muted-text">{{ member_name }}</span> <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 %} {% endif %}
</div> </div>

View File

@@ -1,6 +1,6 @@
<div> <div>
<div class="small-title chapter-title" data-target="#{{ course.get_slugified_chapter_title(chapter.title) }}" <div class="chapter-title small-title" data-target="#{{ course.get_slugified_chapter_title(chapter.title) }}"
data-toggle="collapse" aria-expanded="false"> data-toggle="collapse" aria-expanded="false">
<img class="chapter-icon" src="/assets/community/icons/chevron-right.svg"> <img class="chapter-icon" src="/assets/community/icons/chevron-right.svg">
{{ index }}. {{ chapter.title }} {{ index }}. {{ chapter.title }}
@@ -14,15 +14,15 @@
</div> </div>
{% endif %} {% endif %}
{% set is_instructor = frappe.session.user == course.instructor %}
<div class="lessons"> <div class="lessons">
{% for lesson in course.get_lessons(chapter) %} {% for lesson in course.get_lessons(chapter) %}
<div class="lesson-info{% if membership.current_lesson == lesson.name %} active-lesson {% endif %}"> <div class="lesson-info{% if membership.current_lesson == lesson.name %} active-lesson {% endif %}">
{% if membership or lesson.include_in_preview %} {% if membership or lesson.include_in_preview or is_instructor %}
<a class="lesson-links" <a class="lesson-links" href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}"> data-course="{{ course.name }}">
{{ lesson.title }} {{ lesson.title }}
@@ -56,6 +56,11 @@
<script> <script>
frappe.ready(() => { frappe.ready(() => {
expand_the_active_chapter(); expand_the_active_chapter();
$(".chapter-title").click((e) => {
rotate_chapter_icon(e);
});
}) })
var expand_the_first_chapter = () => { var expand_the_first_chapter = () => {
@@ -97,4 +102,14 @@
$(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)"); $(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)");
} }
var rotate_chapter_icon = (e) => {
e.preventDefault();
var icon = $(e.currentTarget).children(".chapter-icon");
if (icon.css("transform") == "none") {
icon.css("transform", "rotate(90deg)");
} else {
icon.css("transform", "none");
}
}
</script> </script>

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