@@ -26,16 +26,6 @@ def get_data(): | |||
"name": "Blogger", | |||
"description": _("User ID of a blog writer."), | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Website Group", | |||
"description": _("Web Site Forum Page."), | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Post", | |||
"description": _("List of Web Site Forum's Posts."), | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Website Slideshow", | |||
@@ -25,15 +25,13 @@ web_include_css = [ | |||
"style_settings.css" | |||
] | |||
website_clear_cache = "frappe.website.doctype.website_group.website_group.clear_cache" | |||
write_file_keys = ["file_url", "file_name"] | |||
notification_config = "frappe.core.notifications.get_notification_config" | |||
before_tests = "frappe.utils.install.before_tests" | |||
website_generators = ["Web Page", "Blog Post", "Website Group", "Blog Category", "Web Form"] | |||
website_generators = ["Web Page", "Blog Post", "Blog Category", "Web Form"] | |||
# login | |||
@@ -76,9 +74,6 @@ doc_events = { | |||
"frappe.email.doctype.email_alert.email_alert.trigger_email_alerts" | |||
], | |||
"on_trash": "frappe.core.doctype.notification_count.notification_count.clear_doctype_notifications" | |||
}, | |||
"Website Route Permission": { | |||
"on_update": "frappe.website.doctype.website_group.website_group.clear_cache_on_doc_event" | |||
} | |||
} | |||
@@ -93,8 +88,5 @@ scheduler_events = { | |||
"frappe.desk.doctype.event.event.send_event_digest", | |||
"frappe.sessions.clear_expired_sessions", | |||
"frappe.email.doctype.email_alert.email_alert.trigger_daily_alerts", | |||
], | |||
"hourly": [ | |||
"frappe.website.doctype.website_group.website_group.clear_event_cache" | |||
] | |||
} |
@@ -57,3 +57,4 @@ frappe.patches.v4_2.refactor_website_routing | |||
frappe.patches.v4_2.set_assign_in_doc | |||
frappe.patches.v4_3.remove_allow_on_submit_customization | |||
frappe.patches.v5_0.communication_parent | |||
frappe.patches.v5_0.clear_website_group |
@@ -1,12 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "docperm") | |||
# delete same as cancel (map old permissions) | |||
frappe.db.sql("""update tabDocPerm set `delete`=ifnull(`cancel`,0)""") | |||
# can't cancel if can't submit | |||
frappe.db.sql("""update tabDocPerm set `cancel`=0 where ifnull(`submit`,0)=0""") | |||
frappe.clear_cache() |
@@ -1,23 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
for dt in frappe.db.sql_list("""select name from `tabDocType` where ifnull(issingle, 0)=0"""): | |||
desc = dict((d["Field"], d) for d in frappe.db.sql("desc `tab{}`".format(dt), as_dict=True)) | |||
alter_table = [] | |||
if desc["name"]["Type"] != "varchar(255)": | |||
alter_table.append("change `name` `name` varchar(255) not null") | |||
for fieldname in ("modified_by", "owner", "parent", "parentfield", "parenttype"): | |||
if desc[fieldname]["Type"] != "varchar(255)": | |||
alter_table.append("change `{fieldname}` `{fieldname}` varchar(255)".format(fieldname=fieldname)) | |||
if alter_table: | |||
alter_table_query = "alter table `tab{doctype}` {alter_table}".format(doctype=dt, alter_table=",\n".join(alter_table)) | |||
# print alter_table_query | |||
frappe.db.sql_ddl(alter_table_query) | |||
@@ -1,39 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.custom.doctype.custom_field.custom_field import create_custom_field | |||
def execute(): | |||
if "match" in frappe.db.get_table_columns("DocPerm"): | |||
create_custom_field_for_owner_match() | |||
def create_custom_field_for_owner_match(): | |||
frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 where `match`='owner'""") | |||
for dt in frappe.db.sql_list("""select distinct parent from `tabDocPerm` | |||
where `match`='owner' and permlevel=0 and parent != 'User'"""): | |||
# a link field pointing to User already exists | |||
if (frappe.db.get_value("DocField", {"parent": dt, "fieldtype": "Link", "options": "User", "default": "__user"}) | |||
or frappe.db.get_value("Custom Field", {"dt": dt, "fieldtype": "Link", "options": "User", "default": "__user"})): | |||
print "User link field already exists for", dt | |||
continue | |||
fieldname = "{}_owner".format(frappe.scrub(dt)) | |||
create_custom_field(dt, frappe._dict({ | |||
"permlevel": 0, | |||
"label": "{} Owner".format(dt), | |||
"fieldname": fieldname, | |||
"fieldtype": "Link", | |||
"options": "User", | |||
"default": "__user" | |||
})) | |||
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=owner""".format(doctype=dt, | |||
fieldname=fieldname)) | |||
# commit is required so that we don't lose these changes because of an error in next loop's ddl | |||
frappe.db.commit() |
@@ -1,10 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
frappe.db.sql("update `tabDefaultValue` set parenttype='__default' where parenttype='Control Panel'") | |||
frappe.db.sql("update `tabDefaultValue` set parent='__default' where parent='Control Panel'") | |||
frappe.clear_cache() |
@@ -1,13 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
for name in frappe.db.sql_list("""select name from `tabCustom Field` | |||
where fieldtype="Select" and options like "link:%" """): | |||
custom_field = frappe.get_doc("Custom Field", name) | |||
custom_field.fieldtype = "Link" | |||
custom_field.options = custom_field.options[5:] | |||
custom_field.save() |
@@ -1,14 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils.scheduler import disable_scheduler, enable_scheduler | |||
from frappe.utils import cint | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "system_settings") | |||
if cint(frappe.db.get_global("disable_scheduler")): | |||
disable_scheduler() | |||
else: | |||
enable_scheduler() |
@@ -1,36 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import os | |||
from frappe.utils import get_files_path | |||
from frappe.utils.file_manager import get_content_hash, get_file | |||
def execute(): | |||
frappe.reload_doc('core', 'doctype', 'file_data') | |||
for name, file_name, file_url in frappe.db.sql( | |||
"""select name, file_name, file_url from `tabFile Data` | |||
where file_name is not null"""): | |||
b = frappe.get_doc('File Data', name) | |||
old_file_name = b.file_name | |||
b.file_name = os.path.basename(old_file_name) | |||
if old_file_name.startswith('files/') or old_file_name.startswith('/files/'): | |||
b.file_url = os.path.normpath('/' + old_file_name) | |||
else: | |||
b.file_url = os.path.normpath('/files/' + old_file_name) | |||
try: | |||
_file_name, content = get_file(name) | |||
b.content_hash = get_content_hash(content) | |||
except IOError: | |||
print 'Warning: Error processing ', name | |||
_file_name = old_file_name | |||
b.content_hash = None | |||
try: | |||
b.save() | |||
except frappe.DuplicateEntryError: | |||
frappe.delete_doc(b.doctype, b.name) | |||
@@ -1,13 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
attach_fields = (frappe.db.sql("""select parent, fieldname from `tabDocField` where fieldtype='Attach'""") + | |||
frappe.db.sql("""select dt, fieldname from `tabCustom Field` where fieldtype='Attach'""")) | |||
for doctype, fieldname in attach_fields: | |||
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=concat("/", `{fieldname}`) | |||
where `{fieldname}` like 'files/%'""".format(doctype=doctype, fieldname=fieldname)) |
@@ -1,11 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.installer import make_site_dirs | |||
def execute(): | |||
make_site_dirs() | |||
if frappe.local.conf.backup_path and frappe.local.conf.backup_path.startswith("public"): | |||
raise Exception, "Backups path in conf set to public directory" |
@@ -1,4 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
pass |
@@ -1,10 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
for doctype in frappe.db.sql_list("""select name from `tabDocType` where istable=1"""): | |||
frappe.db.sql("""delete from `tab{0}` where parent like "old_par%:%" """.format(doctype)) | |||
frappe.db.sql("""delete from `tabDocField` where parent="0" """) |
@@ -1,10 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
user_owner = frappe.db.get_value("Custom Field", {"fieldname": "user_owner"}) | |||
if user_owner: | |||
frappe.delete_doc("Custom Field", user_owner) |
@@ -1,18 +0,0 @@ | |||
import frappe | |||
from frappe.model import rename_field | |||
from frappe.model.meta import get_table_columns | |||
def execute(): | |||
tables = frappe.db.sql_list("show tables") | |||
if "tabUser" not in tables: | |||
frappe.rename_doc("DocType", "Profile", "User", force=True) | |||
if frappe.db.exists("DocType", "Website Route Permission"): | |||
frappe.reload_doc("website", "doctype", "website_route_permission") | |||
if "profile" in get_table_columns("Website Route Permission"): | |||
rename_field("Website Route Permission", "profile", "user") | |||
frappe.reload_doc("website", "doctype", "blogger") | |||
if "profile" in get_table_columns("Blogger"): | |||
rename_field("Blogger", "profile", "user") |
@@ -1,31 +0,0 @@ | |||
import frappe | |||
from frappe.model import rename_field | |||
def execute(): | |||
tables = frappe.db.sql_list("show tables") | |||
for doctype in ("Website Sitemap", "Website Sitemap Config"): | |||
if "tab{}".format(doctype) in tables: | |||
frappe.delete_doc("DocType", doctype, force=1) | |||
frappe.db.sql("drop table `tab{}`".format(doctype)) | |||
if "tabWebsite Route Permission" not in tables: | |||
frappe.rename_doc("DocType", "Website Sitemap Permission", "Website Route Permission", force=True) | |||
for d in ("Blog Category", "Blog Post", "Web Page", "Website Group"): | |||
frappe.reload_doc("website", "doctype", frappe.scrub(d)) | |||
rename_field_if_exists(d, "parent_website_sitemap", "parent_website_route") | |||
frappe.reload_doc("website", "doctype", "website_route_permission") | |||
rename_field_if_exists("Website Route Permission", "website_sitemap", "website_route") | |||
for d in ("blog_category", "blog_post", "web_page", "website_group", "post", "user_vote"): | |||
frappe.reload_doc("website", "doctype", d) | |||
def rename_field_if_exists(doctype, old_fieldname, new_fieldname): | |||
try: | |||
rename_field(doctype, old_fieldname, new_fieldname) | |||
except Exception, e: | |||
if e.args[0] != 1054: | |||
raise |
@@ -1,21 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils.momentjs import data as momentjs_data | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "user") | |||
ss = frappe.get_doc("System Settings", "System Settings") | |||
if ss.time_zone in momentjs_data.get("links"): | |||
ss.time_zone = momentjs_data["links"][ss.time_zone] | |||
ss.ignore_mandatory = True | |||
ss.save() | |||
for user, time_zone in frappe.db.sql("select name, time_zone from `tabUser` where ifnull(time_zone, '')!=''"): | |||
if time_zone in momentjs_data.get("links"): | |||
user = frappe.get_doc("User", user) | |||
user.time_zone = momentjs_data["links"][user.time_zone] | |||
user.save() |
@@ -1,10 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "report") | |||
frappe.db.sql("""update `tabReport` r set r.module=(select d.module from `tabDocType` d | |||
where d.name=r.ref_doctype) where ifnull(r.module, '')=''""") |
@@ -1,8 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "todo") | |||
try: | |||
frappe.db.sql("""update tabToDo set status = if(ifnull(checked,0)=0, 'Open', 'Closed')""") | |||
except: | |||
pass |
@@ -1,11 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
for name in frappe.db.sql_list("select name from `tabUser` where ifnull(user_image, '')=''"): | |||
user = frappe.get_doc("User", name) | |||
user.update_gravatar() | |||
user.db_set("user_image", user.user_image) |
@@ -1,24 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import frappe.permissions | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "docperm") | |||
table_columns = frappe.db.get_table_columns("DocPerm") | |||
if "restricted" in table_columns: | |||
frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 where ifnull(apply_user_permissions, 0)=0 | |||
and restricted=1""") | |||
if "match" in table_columns: | |||
frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 | |||
where ifnull(apply_user_permissions, 0)=0 and ifnull(`match`, '')!=''""") | |||
# change Restriction to User Permission in tabDefaultValue | |||
frappe.db.sql("""update `tabDefaultValue` set parenttype='User Permission' where parenttype='Restriction'""") | |||
frappe.clear_cache() | |||
@@ -1,24 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
pass | |||
# from frappe.website.doctype.website_template.website_template import \ | |||
# get_pages_and_generators, get_template_controller | |||
# | |||
# frappe.reload_doc("website", "doctype", "website_template") | |||
# frappe.reload_doc("website", "doctype", "website_route") | |||
# | |||
# for app in frappe.get_installed_apps(): | |||
# pages, generators = get_pages_and_generators(app) | |||
# for g in generators: | |||
# doctype = frappe.get_attr(get_template_controller(app, g["path"], g["fname"]) + ".doctype") | |||
# module = frappe.db.get_value("DocType", doctype, "module") | |||
# frappe.reload_doc(frappe.scrub(module), "doctype", frappe.scrub(doctype)) | |||
# | |||
# frappe.db.sql("""update `tabBlog Category` set `title`=`name` where ifnull(`title`, '')=''""") | |||
# frappe.db.sql("""update `tabWebsite Route` set idx=null""") | |||
# for doctype in ["Blog Category", "Blog Post", "Web Page", "Website Group"]: | |||
# frappe.db.sql("""update `tab{}` set idx=null""".format(doctype)) | |||
# | |||
# from frappe.website.doctype.website_template.website_template import rebuild_website_template | |||
# rebuild_website_template() |
@@ -1,18 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
for d in frappe.db.sql("""select name, dt, insert_after from `tabCustom Field` | |||
where docstatus < 2""", as_dict=1): | |||
dt_meta = frappe.get_meta(d.dt) | |||
if not dt_meta.get_field(d.insert_after): | |||
cf = frappe.get_doc("Custom Field", d.name) | |||
df = dt_meta.get("fields", {"label": d.insert_after}) | |||
if df: | |||
cf.insert_after = df[0].fieldname | |||
else: | |||
cf.insert_after = None | |||
cf.save() |
@@ -1,11 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
for table in frappe.db.sql_list("show tables"): | |||
for field in frappe.db.sql("desc `%s`" % table): | |||
if field[1]=="datetime": | |||
frappe.db.sql("alter table `%s` change `%s` `%s` datetime(6)" % \ | |||
(table, field[0], field[0])) | |||
elif field[1]=="time": | |||
frappe.db.sql("alter table `%s` change `%s` `%s` time(6)" % \ | |||
(table, field[0], field[0])) |
@@ -1,11 +0,0 @@ | |||
import frappe, json | |||
def execute(): | |||
frappe.clear_cache() | |||
installed = frappe.get_installed_apps() | |||
if "webnotes" in installed: | |||
installed.remove("webnotes") | |||
if "frappe" not in installed: | |||
installed = ["frappe"] + installed | |||
frappe.db.set_global("installed_apps", json.dumps(installed)) | |||
frappe.clear_cache() |
@@ -1,21 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
# frappe.db.sql("""update `tabWebsite Route` ws set ref_doctype=(select wsc.ref_doctype | |||
# from `tabWebsite Template` wsc where wsc.name=ws.website_template) | |||
# where ifnull(page_or_generator, '')!='Page'""") | |||
frappe.reload_doc("website", "doctype", "website_settings") | |||
# original_home_page = frappe.db.get_value("Website Settings", "Website Settings", "home_page") | |||
# | |||
# home_page = frappe.db.sql("""select name from `tabWebsite Route` | |||
# where (name=%s or docname=%s) and name!='index'""", (original_home_page, original_home_page)) | |||
# home_page = home_page[0][0] if home_page else original_home_page | |||
# | |||
# frappe.db.set_value("Website Settings", "Website Settings", "home_page", home_page) |
@@ -1,11 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
return | |||
# frappe.reload_doc("core", "doctype", "outgoing_email_settings") | |||
# if (frappe.db.get_value("Outgoing Email Settings", "Outgoing Email Settings", "mail_server") or "").strip(): | |||
# frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "enabled", 1) |
@@ -1,24 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "print_settings") | |||
print_settings = frappe.get_doc("Print Settings") | |||
print_settings.print_style = "Modern" | |||
try: | |||
import pdfkit | |||
except ImportError: | |||
pass | |||
else: | |||
# if someone has already configured in Outgoing Email Settings | |||
# outgoing_email_settings = frappe.db.get_singles_dict("Outgoing Email Settings") | |||
# if "send_print_as_pdf" in outgoing_email_settings: | |||
# print_settings.send_print_as_pdf = outgoing_email_settings.send_print_as_pdf | |||
# print_settings.pdf_page_size = outgoing_email_settings.pdf_page_size | |||
print_settings.send_print_as_pdf = 1 | |||
print_settings.save() |
@@ -1,98 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import os | |||
from frappe.utils.file_manager import get_content_hash, get_file, get_file_name | |||
from frappe.utils import get_files_path, get_site_path | |||
# The files missed by the previous patch might have been replaced with new files | |||
# with the same filename | |||
# | |||
# This patch does the following, | |||
# * Detect which files were replaced and rename them with name{hash:5}.extn and | |||
# update filedata record for the new file | |||
# | |||
# * make missing_files.txt in site dir with files that should be recovered from | |||
# a backup from a time before version 3 migration | |||
# | |||
# * Patch remaining unpatched file data records. | |||
def execute(): | |||
frappe.db.auto_commit_on_many_writes = True | |||
rename_replacing_files() | |||
for name, file_name, file_url in frappe.db.sql( | |||
"""select name, file_name, file_url from `tabFile Data` | |||
where ifnull(file_name, '')!='' and ifnull(content_hash, '')=''"""): | |||
b = frappe.get_doc('File Data', name) | |||
old_file_name = b.file_name | |||
b.file_name = os.path.basename(old_file_name) | |||
if old_file_name.startswith('files/') or old_file_name.startswith('/files/'): | |||
b.file_url = os.path.normpath('/' + old_file_name) | |||
else: | |||
b.file_url = os.path.normpath('/files/' + old_file_name) | |||
try: | |||
_file_name, content = get_file(name) | |||
b.content_hash = get_content_hash(content) | |||
except IOError: | |||
print 'Warning: Error processing ', name | |||
b.content_hash = None | |||
b.ignore_duplicate_entry_error = True | |||
b.save() | |||
frappe.db.auto_commit_on_many_writes = False | |||
def get_replaced_files(): | |||
ret = [] | |||
new_files = dict(frappe.db.sql("select name, file_name from `tabFile Data` where file_name not like 'files/%'")) | |||
old_files = dict(frappe.db.sql("select name, file_name from `tabFile Data` where ifnull(content_hash, '')=''")) | |||
invfiles = invert_dict(new_files) | |||
for nname, nfilename in new_files.iteritems(): | |||
if 'files/' + nfilename in old_files.values(): | |||
ret.append((nfilename, invfiles[nfilename])) | |||
return ret | |||
def rename_replacing_files(): | |||
replaced_files = get_replaced_files() | |||
if len(replaced_files): | |||
missing_files = [v[0] for v in replaced_files] | |||
with open(get_site_path('missing_files.txt'), 'w') as f: | |||
f.write(('\n'.join(missing_files) + '\n').encode('utf-8')) | |||
for file_name, file_datas in replaced_files: | |||
print 'processing ' + file_name | |||
content_hash = frappe.db.get_value('File Data', file_datas[0], 'content_hash') | |||
if not content_hash: | |||
continue | |||
new_file_name = get_file_name(file_name, content_hash) | |||
if os.path.exists(get_files_path(new_file_name)): | |||
continue | |||
print 'skipping ' + file_name | |||
try: | |||
os.rename(get_files_path(file_name), get_files_path(new_file_name)) | |||
except OSError: | |||
print 'Error renaming ', file_name | |||
for name in file_datas: | |||
f = frappe.get_doc('File Data', name) | |||
f.file_name = new_file_name | |||
f.file_url = '/files/' + new_file_name | |||
f.save() | |||
def invert_dict(ddict): | |||
ret = {} | |||
for k,v in ddict.iteritems(): | |||
if not ret.get(v): | |||
ret[v] = [k] | |||
else: | |||
ret[v].append(k) | |||
return ret | |||
def get_file_name(fname, hash): | |||
if '.' in fname: | |||
partial, extn = fname.rsplit('.', 1) | |||
else: | |||
partial = fname | |||
extn = '' | |||
return '{partial}{suffix}.{extn}'.format(partial=partial, extn=extn, suffix=hash[:5]) |
@@ -1,11 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("core", "doctype", "print_settings") | |||
print_settings = frappe.get_doc("Print Settings") | |||
print_settings.with_letterhead = 1 | |||
print_settings.save() |
@@ -1,7 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
# clear all static web pages | |||
frappe.delete_doc("DocType", "Website Route", force=1) | |||
frappe.delete_doc("Page", "sitemap-browser", force=1) | |||
frappe.db.sql("drop table if exists `tabWebsite Route`") |
@@ -1,10 +0,0 @@ | |||
import frappe | |||
def execute(): | |||
for name in frappe.db.sql_list("""select name from `tabToDo` | |||
where ifnull(reference_type, '')!='' and ifnull(reference_name, '')!=''"""): | |||
try: | |||
frappe.get_doc("ToDo", name).on_update() | |||
except Exception, e: | |||
if e.args[0]!=1146: | |||
raise |
@@ -0,0 +1,7 @@ | |||
import frappe | |||
def execute(): | |||
frappe.delete_doc("DocType", "Post") | |||
frappe.delete_doc("DocType", "Website Group") | |||
frappe.delete_doc("DocType", "Website Route Permission") | |||
frappe.delete_doc("DocType", "User Vote") |
@@ -1,19 +0,0 @@ | |||
{% include "templates/includes/post_editor.html" %} | |||
<script> | |||
frappe.require("/assets/js/canvasResize.min.js"); | |||
$(function() { | |||
website.bind_add_post(); | |||
{%- if view.name == "edit" -%} | |||
website.bind_save_post(); | |||
{% if post -%} website.post = "{{ post.name }}"; {%- endif %} | |||
{%- endif -%} | |||
{%- if group.group_type == "Events" -%} | |||
website.setup_event_editor(); | |||
{%- elif group.group_type == "Tasks" -%} | |||
website.setup_tasks_editor(); | |||
{%- endif -%} | |||
}); | |||
</script> |
@@ -1,27 +0,0 @@ | |||
<div class="small text-muted post-list-help"></div> | |||
<div class="post-list"> | |||
{{ post_list_html }} | |||
</div> | |||
<div class="text-center"> | |||
<button class="btn btn-default btn-more hide">More</button> | |||
</div> | |||
<script> | |||
$(function() { | |||
if($(".post").length===20) { | |||
frappe.setup_pagination(); | |||
} | |||
{% if group.group_type == "Forum" -%} | |||
website.toggle_edit(true); | |||
{% elif group.group_type == "Tasks" %} | |||
website.toggle_edit(); | |||
{% elif group.group_type == "Events" %} | |||
website.toggle_edit(); | |||
website.format_event_timestamps(); | |||
{%- endif %} | |||
}); | |||
</script> |
@@ -1,64 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils import now_datetime, get_datetime_str | |||
from frappe.website.permissions import get_access | |||
@frappe.whitelist(allow_guest=True) | |||
def get_post_list_html(group, view, limit_start=0, limit_length=20): | |||
from frappe.website.doctype.website_group.website_group import get_views | |||
# verify permission for paging | |||
if frappe.local.form_dict.cmd == "get_post_list_html": | |||
doc = frappe.get_doc("Website Group", group) | |||
access = get_access(doc, doc.get_route()) | |||
if not access.get("read"): | |||
return frappe.PermissionError | |||
conditions = "" | |||
values = [group] | |||
group_type = frappe.db.get_value("Website Group", group, "group_type") | |||
if group_type == "Events": | |||
# should show based on time upto precision of hour | |||
# because the current hour should also be in upcoming | |||
values.append(now_datetime().replace(minute=0, second=0, microsecond=0)) | |||
if view in ("feed", "closed"): | |||
order_by = "p.creation desc" | |||
if view == "closed": | |||
conditions += " and p.is_task=1 and p.status='Closed'" | |||
elif view in ("popular", "open"): | |||
now = get_datetime_str(now_datetime()) | |||
order_by = """(p.upvotes + post_reply_count - (timestampdiff(hour, p.creation, \"{}\") / 2)) desc, | |||
p.creation desc""".format(now) | |||
if view == "open": | |||
conditions += " and p.is_task=1 and p.status='Open'" | |||
elif view == "upcoming": | |||
conditions += " and p.is_event=1 and p.event_datetime >= %s" | |||
order_by = "p.event_datetime asc" | |||
elif view == "past": | |||
conditions += " and p.is_event=1 and p.event_datetime < %s" | |||
order_by = "p.event_datetime desc" | |||
values += [int(limit_start), int(limit_length)] | |||
posts = frappe.db.sql("""select p.*, pr.user_image, pr.first_name, pr.last_name, | |||
(select count(pc.name) from `tabPost` pc where pc.parent_post=p.name) as post_reply_count | |||
from `tabPost` p, `tabUser` pr | |||
where p.website_group = %s and pr.name = p.owner and ifnull(p.parent_post, '')='' | |||
{conditions} order by {order_by} limit %s, %s""".format(conditions=conditions, order_by=order_by), | |||
tuple(values), as_dict=True) | |||
context = { "posts": posts, "limit_start": limit_start, "view": get_views(group_type)[view] } | |||
return frappe.get_template("templates/includes/post_list.html").render(context) | |||
@@ -1,33 +0,0 @@ | |||
<div class="small text-muted post-list-help"></div> | |||
<div class="parent-post">{{ parent_post_html }}</div> | |||
<div class="text-center"> | |||
<button type="button" style="margin-bottom: 15px" | |||
class="btn btn-default btn-earlier-replies hide"> | |||
<span class="btn-earlier-label">Show</span> Earlier Replies</button> | |||
</div> | |||
<div class="post-list"> | |||
{{ post_list_html }} | |||
</div> | |||
<div style="margin-top: 15px"> | |||
{% include "templates/includes/post_editor.html" %} | |||
</div> | |||
<script> | |||
frappe.require("/assets/js/canvasResize.min.js"); | |||
$(function() { | |||
website.toggle_edit(true); | |||
website.toggle_upvote(); | |||
website.bind_add_post(); | |||
// show/hide earlier replies | |||
website.toggle_earlier_replies(); | |||
{%- if group.group_type == "Events" -%} | |||
website.format_event_timestamps(); | |||
{%- endif -%} | |||
website.toggle_post_editor(); | |||
$('[data-view="post"]').removeClass("hide"); | |||
}); | |||
</script> |
@@ -1,156 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.utils import get_fullname | |||
from frappe.website.permissions import get_access | |||
from frappe.utils.file_manager import save_file | |||
def get_post_context(context): | |||
post = frappe.get_doc("Post", frappe.form_dict.name) | |||
if post.parent_post: | |||
raise frappe.PermissionError | |||
def _get_post_context(): | |||
fullname = get_fullname(post.owner) | |||
return { | |||
"title": "{} by {}".format(post.title, fullname), | |||
"parent_post_html": get_parent_post_html(post, context), | |||
"post_list_html": get_child_posts_html(post, context), | |||
"parent_post": post.name | |||
} | |||
cache_key = "website_group_post:{}".format(post.name) | |||
return frappe.cache().get_value(cache_key, lambda: _get_post_context()) | |||
def get_parent_post_html(post, context): | |||
user = frappe.get_doc("User", post.owner) | |||
for fieldname in ("first_name", "last_name", "user_image", "location"): | |||
post.set(fieldname, user.get(fieldname)) | |||
return frappe.get_template("templates/includes/inline_post.html")\ | |||
.render({"post": post, "view": context.view}) | |||
def get_child_posts_html(post, context): | |||
posts = frappe.db.sql("""select p.*, pr.user_image, pr.first_name, pr.last_name | |||
from tabPost p, tabUser pr | |||
where p.parent_post=%s and pr.name = p.owner | |||
order by p.creation asc""", (post.name,), as_dict=True) | |||
return frappe.get_template("templates/includes/post_list.html")\ | |||
.render({ | |||
"posts": posts, | |||
"parent_post": post.name, | |||
"view": context.view | |||
}) | |||
def clear_post_cache(post=None): | |||
cache = frappe.cache() | |||
posts = [post] if post else frappe.db.sql_list("select name from `tabPost`") | |||
for post in posts: | |||
cache.delete_value("website_group_post:{}".format(post)) | |||
@frappe.whitelist(allow_guest=True) | |||
def add_post(group, content, picture, picture_name, title=None, parent_post=None, | |||
assigned_to=None, status=None, event_datetime=None): | |||
doc = frappe.get_doc("Website Group", group) | |||
access = get_access(doc, doc.get_route()) | |||
if not access.get("write"): | |||
raise frappe.PermissionError | |||
if parent_post: | |||
if frappe.db.get_value("Post", parent_post, "parent_post"): | |||
frappe.throw(_("Cannot reply to a reply")) | |||
group = frappe.get_doc("Website Group", group) | |||
post = frappe.get_doc({ | |||
"doctype":"Post", | |||
"title": (title or "").title(), | |||
"content": content, | |||
"website_group": group.name, | |||
"parent_post": parent_post or None | |||
}) | |||
if not parent_post: | |||
if group.group_type == "Tasks": | |||
post.is_task = 1 | |||
post.assigned_to = assigned_to | |||
elif group.group_type == "Events": | |||
post.is_event = 1 | |||
post.event_datetime = event_datetime | |||
post.ignore_permissions = True | |||
post.insert() | |||
if picture_name and picture: | |||
process_picture(post, picture_name, picture) | |||
# send email | |||
if parent_post: | |||
post.run_method("send_email_on_reply") | |||
return post.parent_post or post.name | |||
@frappe.whitelist(allow_guest=True) | |||
def save_post(post, content, picture=None, picture_name=None, title=None, | |||
assigned_to=None, status=None, event_datetime=None): | |||
post = frappe.get_doc("Post", post) | |||
group = frappe.get_doc("Website Group", post.website_group) | |||
access = get_access(group, group.get_route()) | |||
if not access.get("write"): | |||
raise frappe.PermissionError | |||
# TODO improve error message | |||
if frappe.session.user != post.owner: | |||
for fieldname in ("title", "content"): | |||
if post.get(fieldname) != locals().get(fieldname): | |||
frappe.throw(_("Cannot change {0}").format(fieldname)) | |||
if picture and picture_name: | |||
frappe.throw(_("Cannot change picture")) | |||
post.update({ | |||
"title": (title or "").title(), | |||
"content": content, | |||
"assigned_to": assigned_to, | |||
"status": status, | |||
"event_datetime": event_datetime | |||
}) | |||
post.ignore_permissions = True | |||
post.save() | |||
if picture_name and picture: | |||
process_picture(post, picture_name, picture) | |||
return post.parent_post or post.name | |||
def process_picture(post, picture_name, picture): | |||
from frappe.website.doctype.website_group.website_group import clear_cache | |||
post.picture_url = save_file(picture_name, picture, "Post", post.name, decode=True).file_url | |||
frappe.db.set_value("Post", post.name, "picture_url", post.picture_url) | |||
clear_cache(website_group=post.website_group) | |||
@frappe.whitelist() | |||
def suggest_user(group, term): | |||
"""suggest a user that has read permission in this group tree""" | |||
users = frappe.db.sql("""select | |||
pr.name, pr.first_name, pr.last_name, | |||
pr.user_image, pr.location | |||
from `tabUser` pr | |||
where (pr.first_name like %(term)s or pr.last_name like %(term)s) | |||
and pr.user_type = 'Website User' and pr.enabled=1""", | |||
{"term": "%{}%".format(term), "group": group}, as_dict=True) | |||
template = frappe.get_template("templates/includes/user_display.html") | |||
return [{ | |||
"value": "{} {}".format(pr.first_name or "", pr.last_name or "").strip(), | |||
"user_html": template.render({"user": pr}), | |||
"user": pr.name | |||
} for pr in users] |
@@ -1,77 +0,0 @@ | |||
<div class="permission-editor-area"> | |||
<div class="well permission-editor"> | |||
<h4>1. Edit Description</h4> | |||
<div class="row"> | |||
<div class="col-xs-12"> | |||
<p> | |||
<textarea class="form-control control-description" | |||
style="height: 100px;">{{ group.group_description or "" }}</textarea> | |||
</p> | |||
<div> | |||
<button class="btn btn-default btn-update-description" | |||
onclick="website.update_group_description()">Update</button> | |||
</div> | |||
</div> | |||
</div> | |||
<hr> | |||
<h4>2. Add Sub Groups</h4> | |||
<div class="row"> | |||
<div class="col-xs-12"> | |||
<div class="form-group"> | |||
<input class="form-control control-add-group" placeholder="New Group Name" /> | |||
<p class="help-block small">Only letters, numbers and spaces</p> | |||
</div> | |||
<div class="form-group"> | |||
<label>Group Type</label> | |||
<select class="form-control control-add-group-type" data-fieldname="group_type"> | |||
{%- for group_type in ("Forum", "Tasks", "Events") -%} | |||
<option value="{{ group_type }}">{{ group_type }}</option> | |||
{%- endfor -%} | |||
</select> | |||
</div> | |||
<div class="checkbox" style="position: static;"> | |||
<label> | |||
<input type="checkbox" class="control-add-group-public_read" | |||
{{ "checked" if public_read else "disabled" }}> <span>Allow all users to read</span> | |||
</label> | |||
<p class="help-block small">Private if unchecked, only users with explicit read access will be allowed to read</p> | |||
</div> | |||
<div class="checkbox" style="position: static;"> | |||
<label> | |||
<input type="checkbox" class="control-add-group-public_write" | |||
{{ "checked" if public_write else "disabled" }}> <span>Allow all users to write</span> | |||
<p class="help-block small">Public Forum</p> | |||
</label> | |||
</div> | |||
<div> | |||
<button class="btn btn-default btn-add-group"><i class="icon-plus"></i> Add</button> | |||
</div> | |||
</div> | |||
</div> | |||
<hr> | |||
<h4>3. Manage Users</h4> | |||
<input class="form-control add-user-control" type="text" placeholder="Select User" /> | |||
<br> | |||
<table class="table table-bordered"> | |||
<thead> | |||
<tr> | |||
<th style="width: 55%">User</th> | |||
<th style="width: 15%">Read</th> | |||
<th style="width: 15%">Write</th> | |||
<th style="width: 15%">Admin</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
{% for user in users %} | |||
{% include "templates/includes/sitemap_permission.html" %} | |||
{% endfor %} | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
<script> | |||
$(function() { | |||
website.setup_settings(); | |||
}) | |||
</script> |
@@ -1,104 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.permissions import get_access | |||
from frappe.email.bulk import send | |||
@frappe.whitelist() | |||
def suggest_user(term, group): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
users = frappe.db.sql("""select pr.name, pr.first_name, pr.last_name, | |||
pr.user_image, pr.location | |||
from `tabUser` pr | |||
where (pr.first_name like %(term)s or pr.last_name like %(term)s) | |||
and pr.user_type = "Website User" | |||
and pr.user_image is not null and pr.enabled=1 | |||
and not exists(select wsp.name from `tabWebsite Route Permission` wsp | |||
where wsp.website_route=%(group)s and wsp.user=pr.name)""", | |||
{"term": "%{}%".format(term), "group": pathname}, as_dict=True) | |||
template = frappe.get_template("templates/includes/user_display.html") | |||
return [{ | |||
"value": "{} {}".format(pr.first_name or "", pr.last_name or ""), | |||
"user_html": template.render({"user": pr}), | |||
"user": pr.name | |||
} for pr in users] | |||
@frappe.whitelist() | |||
def add_sitemap_permission(group, user): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
permission = frappe.get_doc({ | |||
"doctype": "Website Route Permission", | |||
"website_route": pathname, | |||
"user": user, | |||
"read": 1 | |||
}) | |||
permission.insert(ignore_permissions=True) | |||
user = permission.as_dict() | |||
user.update(frappe.db.get_value("User", user.user, | |||
["name", "first_name", "last_name", "user_image", "location"], as_dict=True)) | |||
return frappe.get_template("templates/includes/sitemap_permission.html").render({ | |||
"user": user | |||
}) | |||
@frappe.whitelist() | |||
def update_permission(group, user, perm, value): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
permission = frappe.get_doc("Website Route Permission", | |||
{"website_route": pathname, "user": user, "reference": group}) | |||
permission.set(perm, int(value)) | |||
permission.save(ignore_permissions=True) | |||
# send email | |||
if perm=="admin" and int(value): | |||
subject = "You have been made Administrator of Group " + doc.group_title | |||
send(recipients=[user], | |||
subject= subject, add_unsubscribe_link=False, | |||
message="""<h3>Group Notification<h3>\ | |||
<p>%s</p>\ | |||
<p style="color: #888">This is just for your information.</p>""" % subject) | |||
@frappe.whitelist() | |||
def update_description(group, description): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
group = frappe.get_doc("Website Group", group) | |||
group.group_description = description | |||
group.save(ignore_permissions=True) | |||
@frappe.whitelist() | |||
def add_website_group(group, new_group, public_read, public_write, group_type="Forum"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
frappe.get_doc({ | |||
"doctype": "Website Group", | |||
"group_name": group + "-" + new_group, | |||
"group_title": new_group, | |||
"parent_website_group": group, | |||
"group_type": group_type, | |||
"public_read": int(public_read), | |||
"public_write": int(public_write) | |||
}).insert(ignore_permissions=True) |
@@ -8,7 +8,6 @@ from frappe.website.doctype.website_settings.website_settings import get_website | |||
from frappe.website.template import render_blocks | |||
from frappe.website.router import get_route_info | |||
from frappe.website.utils import can_cache | |||
from frappe.website.permissions import get_access | |||
def get_context(path): | |||
context = None | |||
@@ -28,10 +27,7 @@ def get_context(path): | |||
context = get_route_info(path) | |||
# permission may be required for rendering | |||
if context.doc and context.doc.doctype=="Website Group": | |||
context["access"] = get_access(context.doc, context.pathname) | |||
else: | |||
context["access"] = frappe._dict({"public_read":1, "public_write":1}) | |||
context["access"] = frappe._dict({"public_read":1, "public_write":1}) | |||
context = build_context(context) | |||
add_data_path(context) | |||
@@ -1,128 +0,0 @@ | |||
{ | |||
"autoname": "P.#######", | |||
"creation": "2014-01-07 14:00:04.000000", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "Transaction", | |||
"fields": [ | |||
{ | |||
"fieldname": "title", | |||
"fieldtype": "Data", | |||
"label": "Title", | |||
"permlevel": 0, | |||
"reqd": 0 | |||
}, | |||
{ | |||
"fieldname": "content", | |||
"fieldtype": "Text", | |||
"in_list_view": 1, | |||
"label": "Content", | |||
"permlevel": 0, | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "picture_url", | |||
"fieldtype": "Attach", | |||
"label": "Picture URL", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "website_group", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Website Group", | |||
"options": "Website Group", | |||
"permlevel": 0, | |||
"reqd": 1, | |||
"search_index": 1 | |||
}, | |||
{ | |||
"fieldname": "is_event", | |||
"fieldtype": "Check", | |||
"label": "Is Event", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "event_datetime", | |||
"fieldtype": "Datetime", | |||
"label": "Event Datetime", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "is_task", | |||
"fieldtype": "Check", | |||
"label": "Is Task", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "assigned_to", | |||
"fieldtype": "Link", | |||
"label": "Assigned To", | |||
"options": "User", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "assigned_to_fullname", | |||
"fieldtype": "Data", | |||
"label": "Assigned To Fullname", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
"label": "Status", | |||
"options": "\nOpen\nClosed", | |||
"permlevel": 0, | |||
"reqd": 0 | |||
}, | |||
{ | |||
"fieldname": "parent_post", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Parent Post", | |||
"options": "Post", | |||
"permlevel": 0, | |||
"search_index": 1 | |||
}, | |||
{ | |||
"fieldname": "unsubscribe", | |||
"fieldtype": "Check", | |||
"label": "Unsubscribe", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "upvotes", | |||
"fieldtype": "Int", | |||
"label": "Upvotes", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "replies", | |||
"fieldtype": "Int", | |||
"label": "Replies", | |||
"permlevel": 0 | |||
} | |||
], | |||
"icon": "icon-comment", | |||
"idx": 1, | |||
"modified": "2014-03-03 14:53:19.000000", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Post", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"export": 1, | |||
"permlevel": 0, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"write": 1 | |||
} | |||
] | |||
} |
@@ -1,99 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.utils import get_fullname | |||
from frappe.email.bulk import send | |||
from frappe.model.document import Document | |||
class Post(Document): | |||
def validate(self): | |||
if not self.parent_post and not self.title: | |||
frappe.throw(_("Title is required")) | |||
self.assigned_to = frappe.db.get_value(self.doctype, self.name, "assigned_to") | |||
if self.is_task: | |||
if not self.status: | |||
self.status = "Open" | |||
if self.assigned_to: | |||
if not self.assigned_to_fullname: | |||
self.assigned_to_fullname = get_fullname(self.assigned_to) | |||
else: | |||
self.assigned_to_fullname = None | |||
else: | |||
self.assigned_to = self.assigned_to_fullname = self.status = None | |||
if self.is_event: | |||
if not self.event_datetime: | |||
frappe.throw(_("Please specify Event date and time")) | |||
else: | |||
self.event_datetime = None | |||
def on_update(self): | |||
from frappe.templates.website_group.post import clear_post_cache | |||
from frappe.website.doctype.website_group.website_group import clear_cache | |||
clear_cache(website_group=self.website_group) | |||
clear_post_cache(self.parent_post or self.name) | |||
if self.assigned_to and self.assigned_to != self.assigned_to \ | |||
and frappe.session.user != self.assigned_to: | |||
# send assignment email | |||
frappe.sendmail(recipients=[self.assigned_to], | |||
subject="You have been assigned this Task by {}".format(get_fullname(self.modified_by)), | |||
content=self.get_reply_email_message(self.name, get_fullname(self.owner))) | |||
def send_email_on_reply(self): | |||
owner_fullname = get_fullname(self.owner) | |||
parent_post = frappe.get_doc("Post", self.parent_post) | |||
message = self.get_reply_email_message(self.name, owner_fullname) | |||
# send email to the owner of the post, if he/she is different | |||
if parent_post.owner != self.owner: | |||
send(recipients=[parent_post.owner], | |||
subject="{someone} replied to your post".format(someone=owner_fullname), | |||
message=message, | |||
# to allow unsubscribe | |||
doctype='Post', | |||
email_field='owner', | |||
# for tracking sent status | |||
ref_doctype=self.doctype, ref_docname=self.name) | |||
# send email to members who part of the conversation | |||
participants = frappe.db.sql("""select owner, name from `tabPost` | |||
where parent_post=%s and owner not in (%s, %s) order by creation asc""", | |||
(self.parent_post, parent_post.owner, self.owner), as_dict=True) | |||
send(recipients=[p.owner for p in participants], | |||
subject="{someone} replied to a post by {other}".format(someone=owner_fullname, | |||
other=get_fullname(parent_post.owner)), | |||
message=message, | |||
# to allow unsubscribe | |||
doctype='Post', | |||
email_field='owner', | |||
# for tracking sent status | |||
ref_doctype=self.doctype, ref_docname=self.name) | |||
def get_reply_email_message(self, post_name, owner_fullname=None): | |||
message = self.content | |||
if self.picture_url: | |||
message += """<div><img src="{url}" style="max-width: 100%"></div>"""\ | |||
.format(url=self.picture_url) | |||
message += "<p>By {fullname}</p>".format(fullname=owner_fullname) | |||
message += "<p><a href='/post/{post_name}'>Click here to view the post</a></p>".format(fullname=owner_fullname, | |||
post_name=post_name) | |||
return message |
@@ -1,43 +0,0 @@ | |||
{ | |||
"autoname": "_VOTE.#######", | |||
"creation": "2014-01-17 16:26:21.000000", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "Transaction", | |||
"fields": [ | |||
{ | |||
"fieldname": "ref_doctype", | |||
"fieldtype": "Link", | |||
"label": "Ref DocType", | |||
"options": "DocType", | |||
"permlevel": 0, | |||
"search_index": 0 | |||
}, | |||
{ | |||
"fieldname": "ref_name", | |||
"fieldtype": "Data", | |||
"label": "Ref Name", | |||
"permlevel": 0, | |||
"search_index": 0 | |||
} | |||
], | |||
"idx": 1, | |||
"modified": "2014-01-21 15:45:30.000000", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "User Vote", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"export": 1, | |||
"permlevel": 0, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"write": 1 | |||
} | |||
] | |||
} |
@@ -1,55 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.permissions import get_access | |||
from frappe.website.doctype.website_group.website_group import clear_cache | |||
from frappe.model.document import Document | |||
class UserVote(Document): | |||
def after_insert(self): | |||
clear_cache(self.ref_name) | |||
def validate(self): | |||
# if new | |||
if self.get("__islocal"): | |||
if frappe.db.get_value("User Vote", {"ref_doctype": self.ref_doctype, | |||
"ref_name": self.ref_name, "owner": frappe.session.user}): | |||
raise frappe.DuplicateEntryError | |||
def on_update(self): | |||
self.update_ref_count() | |||
def on_trash(self): | |||
self.update_ref_count(-1) | |||
def update_ref_count(self, cnt=0): | |||
count = frappe.db.sql("""select count(*) from `tabUser Vote` where ref_doctype=%s and ref_name=%s""", | |||
(self.ref_doctype, self.ref_name))[0][0] | |||
frappe.db.set_value(self.ref_doctype, self.ref_name, "upvotes", count + cnt) | |||
def on_doctype_update(): | |||
frappe.db.add_index("User Vote", ["ref_doctype", "ref_name"]) | |||
# don't allow guest to give vote | |||
@frappe.whitelist() | |||
def set_vote(ref_doctype, ref_name): | |||
website_group_name = frappe.db.get_value(ref_doctype, ref_name, "website_group") | |||
group = frappe.get_doc("Website Group", website_group_name) | |||
if not get_access(group, group.get_route()).get("read"): | |||
raise frappe.PermissionError | |||
try: | |||
user_vote = frappe.get_doc({ | |||
"doctype": "User Vote", | |||
"ref_doctype": ref_doctype, | |||
"ref_name": ref_name | |||
}) | |||
user_vote.ignore_permissions = True | |||
user_vote.insert() | |||
return "ok" | |||
except frappe.DuplicateEntryError: | |||
return "duplicate" |
@@ -1,7 +0,0 @@ | |||
[ | |||
{ | |||
"doctype": "Website Group", | |||
"group_name": "_Test Website Group 1", | |||
"group_title": "_Test Website Group 1" | |||
} | |||
] |
@@ -1,10 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# See license.txt | |||
import frappe | |||
import unittest | |||
test_records = frappe.get_test_records('Website Group') | |||
class TestWebsiteGroup(unittest.TestCase): | |||
pass |
@@ -1,153 +0,0 @@ | |||
{ | |||
"creation": "2014-01-29 15:57:42", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "Master", | |||
"fields": [ | |||
{ | |||
"fieldname": "name_and_description", | |||
"fieldtype": "Section Break", | |||
"label": "Name and Description", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "group_name", | |||
"fieldtype": "Data", | |||
"label": "Group Name", | |||
"permlevel": 0, | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "group_title", | |||
"fieldtype": "Data", | |||
"label": "Group Title", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "group_type", | |||
"fieldtype": "Select", | |||
"label": "Group Type", | |||
"options": "Forum\nTasks\nEvents", | |||
"permlevel": 0, | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "parent_website_group", | |||
"fieldtype": "Link", | |||
"label": "Parent Website Group", | |||
"options": "Website Group", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"description": "Display in the sidebar of this Website Route node", | |||
"fieldname": "parent_website_route", | |||
"fieldtype": "Read Only", | |||
"in_list_view": 0, | |||
"label": "Parent Website Route", | |||
"options": "", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "column_break_6", | |||
"fieldtype": "Column Break", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "group_description", | |||
"fieldtype": "Text", | |||
"label": "Group Description", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "page_name", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Page Name", | |||
"no_copy": 1, | |||
"permlevel": 0, | |||
"reqd": 0 | |||
}, | |||
{ | |||
"fieldname": "details", | |||
"fieldtype": "Section Break", | |||
"label": "Details", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "public_read", | |||
"fieldtype": "Check", | |||
"label": "Anyone Can Read", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "public_write", | |||
"fieldtype": "Check", | |||
"label": "Anyone Can Write", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "column_break_12", | |||
"fieldtype": "Column Break", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "upvotes", | |||
"fieldtype": "Int", | |||
"label": "Upvotes", | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "replies", | |||
"fieldtype": "Int", | |||
"label": "Replies", | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "lft", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"label": "lft", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "rgt", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"label": "rgt", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "old_parent", | |||
"fieldtype": "Read Only", | |||
"hidden": 1, | |||
"label": "Old Parent", | |||
"permlevel": 0 | |||
} | |||
], | |||
"icon": "icon-group", | |||
"idx": 1, | |||
"modified": "2014-08-19 14:33:40.664635", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Website Group", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"export": 1, | |||
"permlevel": 0, | |||
"read": 1, | |||
"report": 1, | |||
"role": "Website Manager", | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC" | |||
} |
@@ -1,251 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.website_generator import WebsiteGenerator | |||
from frappe.website.render import can_cache | |||
from frappe.templates.website_group.forum import get_post_list_html | |||
from frappe.utils.nestedset import NestedSet | |||
class WebsiteGroup(WebsiteGenerator, NestedSet): | |||
no_cache = True | |||
template = "templates/generators/website_group.html" | |||
parent_website_route_field = "parent_website_group" | |||
page_title_field = "group_title" | |||
def on_update(self): | |||
WebsiteGenerator.on_update(self) | |||
NestedSet.on_update(self) | |||
clear_cache(website_group=self.name) | |||
def on_trash(self): | |||
WebsiteGenerator.on_trash(self) | |||
NestedSet.on_trash(self) | |||
def after_insert(self): | |||
clear_cache(website_group=self.name) | |||
def get_context(self, context): | |||
group, view = guess_group_view(context) | |||
try: | |||
if not has_access(context.access, view): | |||
raise frappe.PermissionError | |||
return get_group_context(group, view, context) | |||
except frappe.DoesNotExistError: | |||
return { | |||
"content": '<div class="alert alert-danger full-page">' | |||
'The page you are looking for does not exist.</div>' | |||
} | |||
except frappe.PermissionError: | |||
return { | |||
"content": '<div class="alert alert-danger full-page">' | |||
'You are not permitted to view this page.</div>' | |||
} | |||
return context | |||
def get_group_context(group, view, context): | |||
cache_key = "website_group_context:{}:{}".format(group, view) | |||
views = get_views(context.doc.group_type) | |||
view = frappe._dict(views.get(view)) | |||
if can_cache(view.no_cache): | |||
group_context = frappe.cache().get_value(cache_key) | |||
if group_context: | |||
return group_context | |||
group_context = build_group_context(group, view, views, context) | |||
if can_cache(view.get("no_cache")): | |||
frappe.cache().set_value(cache_key, group_context) | |||
group_context.children = context.doc.get_children() | |||
return group_context | |||
def build_group_context(group, view, views, context): | |||
title = "{} - {}".format(context.doc.group_title, view.get("label")) | |||
group_context = frappe._dict({ | |||
"group": context.doc, | |||
"view": view, | |||
"views": [v[1] for v in sorted(views.iteritems(), key=lambda (k, v): v.get("idx"))], | |||
"title": title, | |||
"pathname": context.pathname | |||
}) | |||
group_context.update(build_view_context(group_context)) | |||
return group_context | |||
def build_view_context(context): | |||
from frappe.templates.website_group.post import get_post_context | |||
if context.view.name in ("popular", "feed", "open", "closed", "upcoming", "past"): | |||
context.post_list_html = get_post_list_html(context.group.name, context.view.name) | |||
elif context.view.name == "edit": | |||
context.post = frappe.get_doc("Post", frappe.form_dict.name).as_dict() | |||
if context.post.assigned_to: | |||
context.user = frappe.get_doc("User", context.post.assigned_to) | |||
elif context.view.name == "settings": | |||
context.users = frappe.db.sql("""select p.*, wsp.`read`, wsp.`write`, wsp.`admin` | |||
from `tabUser` p, `tabWebsite Route Permission` wsp | |||
where wsp.website_route=%s and wsp.user=p.name""", context.pathname, as_dict=True) | |||
elif context.view.name == "post": | |||
context.update(get_post_context(context)) | |||
return context | |||
def guess_group_view(context): | |||
group = context.docname | |||
view = frappe.form_dict.view or get_default_view(context.doc.group_type) | |||
return group, view | |||
def get_default_view(group_type): | |||
for view, opts in get_views(group_type).iteritems(): | |||
if opts.get("default"): | |||
return view | |||
def get_views(group_type=None): | |||
if group_type: | |||
group_views = frappe._dict(views[group_type]) | |||
else: | |||
group_views = {} | |||
for group_type in views: | |||
group_views.update(views[group_type].copy()) | |||
group_views.update(common_views) | |||
if group_type == "Forum": | |||
group_views["post"]["upvote"] = True | |||
return group_views | |||
def has_access(access, view): | |||
if view=="settings": | |||
return access.get("admin") | |||
elif view in ("add", "edit"): | |||
return access.get("write") | |||
else: | |||
return access.get("read") | |||
def clear_cache(website_group=None): | |||
from frappe.templates.website_group.post import clear_post_cache | |||
if website_group: | |||
website_groups = [website_group] | |||
else: | |||
clear_post_cache() | |||
website_groups = frappe.db.sql_list("""select name from `tabWebsite Group`""") | |||
cache = frappe.cache() | |||
all_views = get_views() | |||
for group in website_groups: | |||
for view in all_views: | |||
cache.delete_value("website_group_context:{}:{}".format(group, view)) | |||
def clear_event_cache(): | |||
for group in frappe.db.sql_list("""select name from `tabWebsite Group` where group_type='Event'"""): | |||
clear_cache(website_group=group) | |||
views = { | |||
"Forum": { | |||
"popular": { | |||
"name": "popular", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Popular", | |||
"icon": "icon-heart", | |||
"default": True, | |||
"upvote": True, | |||
"idx": 1 | |||
}, | |||
"feed": { | |||
"name": "feed", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Feed", | |||
"icon": "icon-rss", | |||
"upvote": True, | |||
"idx": 2 | |||
} | |||
}, | |||
"Tasks": { | |||
"open": { | |||
"name": "open", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Open", | |||
"icon": "icon-inbox", | |||
"default": True, | |||
"upvote": True, | |||
"idx": 1 | |||
}, | |||
"closed": { | |||
"name": "closed", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Closed", | |||
"icon": "icon-smile", | |||
"idx": 2 | |||
} | |||
}, | |||
"Events": { | |||
"upcoming": { | |||
"name": "upcoming", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Upcoming", | |||
"icon": "icon-calendar", | |||
"default": True, | |||
"idx": 1 | |||
}, | |||
"past": { | |||
"name": "past", | |||
"template_path": "templates/website_group/forum.html", | |||
"label": "Past", | |||
"icon": "icon-time", | |||
"idx": 2 | |||
} | |||
} | |||
} | |||
common_views = { | |||
"post": { | |||
"name": "post", | |||
"template_path": "templates/website_group/post.html", | |||
"label": "Post", | |||
"icon": "icon-comments", | |||
"hidden": True, | |||
"no_cache": True, | |||
"idx": 3 | |||
}, | |||
"edit": { | |||
"name": "edit", | |||
"template_path": "templates/website_group/edit_post.html", | |||
"label": "Edit Post", | |||
"icon": "icon-pencil", | |||
"hidden": True, | |||
"no_cache": True, | |||
"idx": 4 | |||
}, | |||
"add": { | |||
"name": "add", | |||
"template_path": "templates/website_group/edit_post.html", | |||
"label": "Add Post", | |||
"icon": "icon-plus", | |||
"hidden": True, | |||
"idx": 5 | |||
}, | |||
"settings": { | |||
"name": "settings", | |||
"template_path": "templates/website_group/settings.html", | |||
"label": "Settings", | |||
"icon": "icon-cog", | |||
"hidden": True, | |||
"idx": 6 | |||
} | |||
} |
@@ -1,79 +0,0 @@ | |||
{ | |||
"autoname": "WSP.######", | |||
"creation": "2014-01-29 17:56:29", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"fields": [ | |||
{ | |||
"fieldname": "website_route", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Website Route", | |||
"options": "", | |||
"permlevel": 0, | |||
"reqd": 1, | |||
"search_index": 1 | |||
}, | |||
{ | |||
"fieldname": "user", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "User", | |||
"options": "User", | |||
"permlevel": 0, | |||
"reqd": 1, | |||
"search_index": 1 | |||
}, | |||
{ | |||
"fieldname": "read", | |||
"fieldtype": "Check", | |||
"in_list_view": 1, | |||
"label": "Read", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "write", | |||
"fieldtype": "Check", | |||
"in_list_view": 1, | |||
"label": "Write", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "admin", | |||
"fieldtype": "Check", | |||
"in_list_view": 1, | |||
"label": "Admin", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "reference", | |||
"fieldtype": "Link", | |||
"label": "reference", | |||
"options": "Website Group", | |||
"permlevel": 0 | |||
} | |||
], | |||
"icon": "icon-shield", | |||
"idx": 1, | |||
"modified": "2014-08-20 12:56:15.141568", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Website Route Permission", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 0, | |||
"export": 1, | |||
"import": 0, | |||
"permlevel": 0, | |||
"read": 1, | |||
"report": 1, | |||
"role": "Website Manager", | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC" | |||
} |
@@ -1,16 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.permissions import remove_empty_permissions, clear_permissions | |||
from frappe.model.document import Document | |||
class WebsiteRoutePermission(Document): | |||
def on_update(self): | |||
remove_empty_permissions() | |||
clear_permissions(self.user) | |||
@@ -1,564 +0,0 @@ | |||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
frappe.provide("website"); | |||
$.extend(website, { | |||
toggle_permitted: function() { | |||
if(website.access) { | |||
// hide certain views | |||
$('li[data-view="add"]').toggleClass("hide", !website.access.write); | |||
$('li[data-view="settings"]').toggleClass("hide", !website.access.admin); | |||
$('li[data-view="edit"]').toggleClass("hide", website.view!=="edit"); | |||
// show message | |||
if(!website.access.write) { | |||
var sid = frappe.get_cookie("sid"); | |||
if(!sid || sid==="Guest") { | |||
$(".post-list-help").html("Please login to post"); | |||
} else { | |||
$(".post-list-help").html("You do not have permission to post"); | |||
} | |||
} else { | |||
$(".post-list-help").html(""); | |||
} | |||
} | |||
}, | |||
setup_pagination: function() { | |||
var $btn = $(".btn-more") | |||
.removeClass("hide") | |||
.on("click", function() { | |||
frappe.call({ | |||
btn: $btn, | |||
type: "GET", | |||
args: { | |||
cmd: "frappe.templates.website_group.forum.get_post_list_html", | |||
limit_start: $(".post").length, | |||
limit_length: 20, | |||
group: website.group, | |||
view: website.view, | |||
pathname: website.pathname | |||
}, | |||
callback: function(data) { | |||
$(".post-list").append(data.message); | |||
$btn.toggleClass("hide", !(data.message && data.message.length===opts.args.limit_length)); | |||
website.toggle_upvote(); | |||
} | |||
}) | |||
}); | |||
}, | |||
bind_add_post: function() { | |||
$(".btn-post-add").on("click", website.add_post); | |||
$pic_input = $(".control-post-add-picture").on("change", website.add_picture); | |||
$(".btn-post-add-picture").on("click", function() { | |||
$pic_input.click(); | |||
}); | |||
}, | |||
add_post: function() { | |||
if(website.post) { | |||
frappe.msgprint(__("Post already exists. Cannot add again!")); | |||
return; | |||
} | |||
website._update_post(this, "frappe.templates.website_group.post.add_post"); | |||
}, | |||
bind_save_post: function() { | |||
$(".btn-post-add").addClass("hide"); | |||
$(".btn-post-save").removeClass("hide").on("click", website.save_post); | |||
$(".post-picture").toggleClass("hide", !$(".post-picture").attr("src")); | |||
}, | |||
save_post: function() { | |||
if(!website.post) { | |||
frappe.msgprint(__("Post does not exist. Please add post!")); | |||
return; | |||
} | |||
website._update_post(this, "frappe.templates.website_group.post.save_post"); | |||
}, | |||
_update_post: function(btn, cmd) { | |||
var values = website.get_editor_values(); | |||
if(!values) { | |||
return; | |||
} | |||
frappe.call({ | |||
btn: btn, | |||
type: "POST", | |||
args: $.extend({ | |||
cmd: cmd, | |||
group: website.group, | |||
post: website.post || undefined, | |||
}, values), | |||
callback: function(data) { | |||
var url = window.location.pathname + "?view=post&name=" + data.message; | |||
window.location.href = url; | |||
} | |||
}); | |||
}, | |||
get_editor_values: function() { | |||
var values = {}; | |||
$.each($('.post-editor [data-fieldname]'), function(i, ele) { | |||
var $ele = $(ele); | |||
values[$ele.attr("data-fieldname")] = $ele.val(); | |||
}); | |||
values.parent_post = $(".post-editor").attr("data-parent-post"); | |||
values.picture_name = $(".control-post-add-picture").val() || null; | |||
var dataurl = $(".post-picture img").attr("src"); | |||
values.picture = dataurl ? dataurl.split(",")[1] : "" | |||
// validations | |||
if(!values.parent_post && !values.title) { | |||
frappe.msgprint(__("Please enter title!")); | |||
return; | |||
} else if(!values.content) { | |||
frappe.msgprint(__("Please enter some text!")); | |||
return; | |||
} else if($('.post-editor [data-fieldname="event_datetime"]').length && !values.event_datetime) { | |||
frappe.msgprint(__("Please enter Event's Date and Time!")); | |||
return; | |||
} | |||
// post process | |||
// convert links in content | |||
values.content = website.process_external_links(values.content); | |||
return values; | |||
}, | |||
process_external_links: function(content) { | |||
return content.replace(/([^\s]*)(http|https|ftp):\/\/[^\s\[\]\(\)]+/g, function(match, p1) { | |||
// mimicing look behind! should not have anything in p1 | |||
// replace(/match/g) | |||
// replace(/(p1)(p2)/g) | |||
// so, when there is a character before http://, it shouldn't be replaced! | |||
if(p1) return match; | |||
return "["+match+"]("+match+")"; | |||
}); | |||
}, | |||
add_picture: function() { | |||
if (this.type === 'file' && this.files && this.files.length > 0) { | |||
$.each(this.files, function (idx, fileobj) { | |||
if (/^image\//.test(fileobj.type)) { | |||
$.canvasResize(fileobj, { | |||
width: 500, | |||
height: 0, | |||
crop: false, | |||
quality: 80, | |||
callback: function(data, width, height) { | |||
$(".post-picture").removeClass("hide").find("img").attr("src", data); | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
return false; | |||
}, | |||
setup_tasks_editor: function() { | |||
// assign events | |||
var $post_editor = $(".post-editor"); | |||
var $control_assign = $post_editor.find('.control-assign'); | |||
var bind_close = function() { | |||
var close = $post_editor.find("a.close") | |||
if(close.length) { | |||
close.on("click", function() { | |||
// clear assignment | |||
$post_editor.find(".assigned-to").addClass("hide"); | |||
$post_editor.find(".assigned-user").html(""); | |||
$post_editor.find('[data-fieldname="assigned_to"]').val(null); | |||
$control_assign.val(null); | |||
}); | |||
} | |||
} | |||
if($control_assign.length) { | |||
website.setup_autosuggest({ | |||
$control: $control_assign, | |||
select: function(value, item) { | |||
var $assigned_to = $post_editor.find(".assigned-to").removeClass("hide"); | |||
$assigned_to.find(".assigned-user").html(item.user_html); | |||
$post_editor.find('[data-fieldname="assigned_to"]').val(value); | |||
bind_close(); | |||
}, | |||
method: "frappe.templates.website_group.post.suggest_user" | |||
}); | |||
bind_close(); | |||
} | |||
}, | |||
setup_event_editor: function() { | |||
var $post_editor = $(".post-editor"); | |||
var $control_event = $post_editor.find('.control-event').empty(); | |||
var $event_field = $post_editor.find('[data-fieldname="event_datetime"]'); | |||
var set_event = function($control) { | |||
var datetime = website.datetimepicker.obj_to_str($control_event.datepicker("getDate")); | |||
if($event_field.val() !== datetime) { | |||
$event_field.val(datetime); | |||
} | |||
}; | |||
website.setup_datepicker({ | |||
$control: $control_event, | |||
onClose: function() { set_event($control_event) } | |||
}); | |||
if($event_field.val()) { | |||
$control_event.val(website.datetimepicker.format_datetime($event_field.val())); | |||
} | |||
}, | |||
format_event_timestamps: function() { | |||
var get_day = function(num) { | |||
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", | |||
"Friday", "Saturday"][num]; | |||
} | |||
var get_month = function(num) { | |||
return ["January", "February", "March", "April", "May", "June", | |||
"July", "August", "September", "October", "November", "December"][num-1]; | |||
} | |||
var format = function(datetime) { | |||
if(!datetime) return ""; | |||
var date = datetime.split(" ")[0].split("-"); | |||
var time = datetime.split(" ")[1].split(":"); | |||
var tt = "am"; | |||
if(time[0] >= 12) { | |||
time[0] = parseInt(time[0]) - 12; | |||
tt = "pm"; | |||
} | |||
if(!parseInt(time[0])) { | |||
time[0] = 12; | |||
} | |||
var hhmm = [time[0], time[1]].join(":") | |||
// DD, d MM, yy hh:mm tt | |||
var dateobj = new Date(date[0], date[1], date[2]) | |||
return repl("%(day)s, %(date)s %(month)s, %(year)s %(time)s", { | |||
day: get_day(dateobj.getDay()), | |||
date: date[2], | |||
month: get_month(dateobj.getMonth()), | |||
year: date[0], | |||
time: hhmm + " " + tt | |||
}) | |||
} | |||
$(".event-timestamp").each(function() { | |||
$(this).html(format($(this).attr("data-timestamp"))); | |||
}) | |||
}, | |||
toggle_earlier_replies: function() { | |||
var $earlier_replies = $(".child-post").slice(0, $(".child-post").length - 2); | |||
var $btn = $(".btn-earlier-replies").on("click", function() { | |||
if($earlier_replies.hasClass("hide")) { | |||
$earlier_replies.removeClass("hide"); | |||
$(".btn-earlier-label").html("Hide"); | |||
} else { | |||
$earlier_replies.addClass("hide"); | |||
$(".btn-earlier-label").html("Show"); | |||
} | |||
}); | |||
if($earlier_replies.length) { | |||
$btn.toggleClass("hide", false).click(); | |||
} | |||
}, | |||
toggle_edit: function(only_owner) { | |||
if(only_owner) { | |||
var user = frappe.get_cookie("user_id"); | |||
$(".edit-post").each(function() { | |||
$(this).toggleClass("hide", !(website.access.write && $(this).attr("data-owner")===user)); | |||
}); | |||
} else { | |||
$(".edit-post").toggleClass("hide", !website.access.write); | |||
} | |||
}, | |||
toggle_upvote: function() { | |||
if(!website.access.read || !website.upvote) { | |||
$(".upvote").remove(); | |||
} | |||
}, | |||
toggle_post_editor: function() { | |||
$(".post-editor").toggleClass("hide", !website.access.write); | |||
}, | |||
setup_upvote: function() { | |||
if(window.website.setup_upvote_done) return; | |||
window.website.setup_upvote_done = true; | |||
$(document).on("click", ".post-list .upvote a, .parent-post .upvote a", function() { | |||
console.log("clicked"); | |||
var sid = frappe.get_cookie("sid"); | |||
if(!sid || sid==="Guest") { | |||
frappe.msgprint(__("Please login to Upvote!")); | |||
return; | |||
} | |||
var $post = $(this).parents(".post"); | |||
var post = $post.attr("data-name"); | |||
var $btn = $(this).prop("disabled", true); | |||
$.ajax({ | |||
url: "/", | |||
type: "POST", | |||
data: { | |||
cmd: "frappe.website.doctype.user_vote.user_vote.set_vote", | |||
ref_doctype: "Post", | |||
ref_name: post | |||
}, | |||
statusCode: { | |||
200: function(data) { | |||
if(data.exc) { | |||
console.log(data.exc); | |||
} else { | |||
var text_class = data.message === "ok" ? "text-success" : "text-danger"; | |||
if(data.message==="ok") { | |||
var count = parseInt($post.find(".upvote-count").text()); | |||
$post.find(".upvote-count").text(count + 1).removeClass("hide"); | |||
} | |||
$btn.addClass(text_class); | |||
setTimeout(function() { $btn.removeClass(text_class); }, 2000); | |||
} | |||
} | |||
} | |||
}).always(function() { | |||
$btn.prop("disabled", false); | |||
}); | |||
return false; | |||
}); | |||
}, | |||
setup_autosuggest: function(opts) { | |||
if(opts.$control.hasClass("ui-autocomplete-input")) return; | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.min.js"); | |||
frappe.require("/assets/frappe/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css"); | |||
var $user_suggest = opts.$control.autocomplete({ | |||
source: function(request, response) { | |||
$.ajax({ | |||
url: "/", | |||
data: { | |||
cmd: opts.method, | |||
term: request.term, | |||
group: website.group | |||
}, | |||
success: function(data) { | |||
if(data.exc) { | |||
console.log(data.exc); | |||
} else { | |||
response(data.message); | |||
} | |||
} | |||
}); | |||
}, | |||
select: function(event, ui) { | |||
opts.$control.val(""); | |||
opts.select(ui.item.user, ui.item); | |||
} | |||
}); | |||
$user_suggest.data( "ui-autocomplete" )._renderItem = function(ul, item) { | |||
return $("<li>").html("<a style='padding: 5px;'>" + item.user_html + "</a>") | |||
.css("padding", "5px") | |||
.appendTo(ul); | |||
}; | |||
return opts.$control | |||
}, | |||
setup_datepicker: function(opts) { | |||
if(opts.$control.hasClass("hasDatetimepicker")) return; | |||
// libs required for datetime picker | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.min.js"); | |||
frappe.require("/assets/frappe/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css"); | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.slider.min.js"); | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.sliderAccess.js"); | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.css"); | |||
frappe.require("/assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.js"); | |||
opts.$control.datetimepicker({ | |||
timeFormat: "hh:mm tt", | |||
dateFormat: 'DD, d MM, yy', | |||
changeYear: true, | |||
yearRange: "-70Y:+10Y", | |||
stepMinute: 5, | |||
hour: 10, | |||
onClose: opts.onClose | |||
}); | |||
website.setup_datetime_functions(); | |||
return opts.$control; | |||
}, | |||
setup_datetime_functions: function() { | |||
// requires datetime picker | |||
frappe.provide("website.datetimepicker"); | |||
website.datetimepicker.str_to_obj = function(datetime_str) { | |||
return $.datepicker.parseDateTime("yy-mm-dd", "HH:mm:ss", datetime_str); | |||
}; | |||
website.datetimepicker.obj_to_str = function(datetime) { | |||
if(!datetime) { | |||
return ""; | |||
} | |||
// requires datepicker | |||
var date_str = $.datepicker.formatDate("yy-mm-dd", datetime) | |||
var time_str = $.datepicker.formatTime("HH:mm:ss", { | |||
hour: datetime.getHours(), | |||
minute: datetime.getMinutes(), | |||
second: datetime.getSeconds() | |||
}) | |||
return date_str + " " + time_str; | |||
}; | |||
website.datetimepicker.format_datetime = function(datetime) { | |||
if (typeof(datetime)==="string") { | |||
datetime = website.datetimepicker.str_to_obj(datetime); | |||
} | |||
var date_str = $.datepicker.formatDate("DD, d MM, yy", datetime) | |||
var time_str = $.datepicker.formatTime("hh:mm tt", { | |||
hour: datetime.getHours(), | |||
minute: datetime.getMinutes(), | |||
second: datetime.getSeconds() | |||
}) | |||
return date_str + " " + time_str; | |||
} | |||
}, | |||
setup_settings: function() { | |||
// autosuggest | |||
website.setup_autosuggest({ | |||
$control: $(".add-user-control"), | |||
select: function(value) { | |||
website.add_sitemap_permission(value); | |||
}, | |||
method: "frappe.templates.website_group.settings.suggest_user" | |||
}); | |||
// trigger for change permission | |||
$(".permission-editor-area").on("click", ".sitemap-permission [type='checkbox']", | |||
website.update_permission); | |||
$(".permission-editor-area").find(".btn-add-group").on("click", website.add_group); | |||
$(".btn-settings").parent().addClass("active"); | |||
// disabled public_write if not public_read | |||
var control_public_read = $(".control-add-group-public_read").click(function() { | |||
if(!$(this).prop("checked")) { | |||
$(".control-add-group-public_write").prop("checked", false).prop("disabled", true); | |||
} else { | |||
$(".control-add-group-public_write").prop("disabled", false); | |||
} | |||
}).trigger("click").trigger("click"); // hack | |||
}, | |||
add_group: function() { | |||
var $control = $(".control-add-group"), | |||
$btn = $(".btn-add-group"); | |||
if($control.val()) { | |||
$btn.prop("disabled", true); | |||
$.ajax({ | |||
url:"/", | |||
type:"POST", | |||
data: { | |||
cmd:"frappe.templates.website_group.settings.add_website_group", | |||
group: website.group, | |||
new_group: $control.val(), | |||
group_type: $(".control-add-group-type").val(), | |||
public_read: $(".control-add-group-public_read").is(":checked") ? 1 : 0, | |||
public_write: $(".control-add-group-public_write").is(":checked") ? 1 : 0 | |||
}, | |||
statusCode: { | |||
403: function() { | |||
frappe.msgprint(__("Name not permitted")); | |||
}, | |||
200: function(data) { | |||
if(data.exc) { | |||
console.log(data.exc); | |||
if(data._server_messages) frappe.msgprint(data._server_messages); | |||
} else { | |||
frappe.msgprint(__("Group Added, refreshing...")); | |||
setTimeout(function() { window.location.reload(); }, 1000) | |||
} | |||
} | |||
} | |||
}).always(function() { | |||
$btn.prop("disabled",false); | |||
$control.val(""); | |||
}) | |||
} | |||
}, | |||
update_permission: function() { | |||
var $chk = $(this); | |||
var $tr = $chk.parents("tr:first"); | |||
$chk.prop("disabled", true); | |||
$.ajax({ | |||
url: "/", | |||
type: "POST", | |||
data: { | |||
cmd: "frappe.templates.website_group.settings.update_permission", | |||
user: $tr.attr("data-user"), | |||
perm: $chk.attr("data-perm"), | |||
value: $chk.prop("checked") ? "1" : "0", | |||
group: website.group | |||
}, | |||
statusCode: { | |||
403: function() { | |||
frappe.msgprint(__("Not allowed")); | |||
}, | |||
200: function(data) { | |||
$chk.prop("disabled", false); | |||
if(data.exc) { | |||
$chk.prop("checked", !$chk.prop("checked")); | |||
console.log(data.exc); | |||
} else { | |||
if(!$tr.find(":checked").length) $tr.remove(); | |||
} | |||
} | |||
}, | |||
}); | |||
}, | |||
add_sitemap_permission: function(user) { | |||
$.ajax({ | |||
url: "/", | |||
type: "POST", | |||
data: { | |||
cmd: "frappe.templates.website_group.settings.add_sitemap_permission", | |||
user: user, | |||
group: website.group | |||
}, | |||
success: function(data) { | |||
$(".add-user-control").val(""); | |||
if(data.exc) { | |||
console.log(data.exc); | |||
} else { | |||
$(data.message).prependTo($(".permission-editor tbody")); | |||
} | |||
} | |||
}); | |||
}, | |||
update_group_description: function() { | |||
$(".btn-update-description").prop("disabled", true); | |||
$.ajax({ | |||
url: "/", | |||
type: "POST", | |||
data: { | |||
cmd: "frappe.templates.website_group.settings.update_description", | |||
description: $(".control-description").val() || "", | |||
group: website.group | |||
}, | |||
success: function(data) { | |||
window.location.reload(); | |||
} | |||
}).always(function() { $(".btn-update-description").prop("disabled", false); }); | |||
} | |||
}); | |||
$(document).on("apply_permissions", function() { | |||
website.toggle_permitted(); | |||
}); |
@@ -1,77 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def remove_empty_permissions(): | |||
permissions_cache_to_be_cleared = frappe.db.sql_list("""select distinct user | |||
from `tabWebsite Route Permission` | |||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""") | |||
frappe.db.sql("""delete from `tabWebsite Route Permission` | |||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""") | |||
clear_permissions(permissions_cache_to_be_cleared) | |||
def get_access(doc, pathname, user=None): | |||
user = user or frappe.session.user | |||
key = "website_route_permissions:{}".format(user) | |||
cache = frappe.cache() | |||
permissions = cache.get_value(key) or {} | |||
if not permissions.get(doc.name): | |||
permissions[doc.name] = _get_access(doc, pathname, user) | |||
cache.set_value(key, permissions) | |||
return permissions.get(doc.name) | |||
def _get_access(doc, pathname, user): | |||
read = write = admin = private_read = 0 | |||
if user == "Guest": | |||
return { "read": doc.public_read, "write": 0, "admin": 0 } | |||
if doc.public_write: | |||
read = write = 1 | |||
elif doc.public_read: | |||
read = 1 | |||
for perm in frappe.db.sql("""select | |||
`tabWebsite Route Permission`.`read`, | |||
`tabWebsite Route Permission`.`write`, | |||
`tabWebsite Route Permission`.`admin`, | |||
`tabWebsite Group`.lft, | |||
`tabWebsite Group`.rgt | |||
from | |||
`tabWebsite Route Permission`, `tabWebsite Group` | |||
where | |||
`tabWebsite Route Permission`.website_route = %s and | |||
`tabWebsite Route Permission`.user = %s and | |||
`tabWebsite Route Permission`.reference = `tabWebsite Group`.name | |||
order by `tabWebsite Group`.lft asc""", (user, pathname), as_dict=True): | |||
if perm.lft <= doc.lft and perm.rgt >= doc.rgt: | |||
if not (doc.public_read or private_read): | |||
private_read = perm.read | |||
if not read: read = perm.read | |||
if not write: write = perm.write | |||
if not admin: admin = perm.admin | |||
if write: read = write | |||
if read and write and admin: | |||
break | |||
else: | |||
read = write = admin = private_read = 1 | |||
return { "read": read, "write": write, "admin": admin, "private_read": private_read } | |||
def clear_permissions(users=None): | |||
if isinstance(users, basestring): | |||
users = [users] | |||
elif users is None: | |||
users = frappe.db.sql_list("""select name from `tabUser`""") | |||
cache = frappe.cache() | |||
for user in users: | |||
cache.delete_value("website_route_permissions:{}".format(user)) |
@@ -10,7 +10,6 @@ from werkzeug.wrappers import Response | |||
from frappe.website.context import get_context | |||
from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache, delete_page_cache | |||
from frappe.website.permissions import clear_permissions | |||
from frappe.website.router import clear_sitemap | |||
class PageNotFoundError(Exception): pass | |||
@@ -184,7 +183,6 @@ def clear_cache(path=None): | |||
clear_sitemap() | |||
frappe.clear_cache("Guest") | |||
frappe.cache().delete_value("_website_pages") | |||
clear_permissions() | |||
for method in frappe.get_hooks("website_clear_cache"): | |||
frappe.get_attr(method)(path) | |||