@@ -446,7 +446,8 @@ def get_meta(doctype, cached=True): | |||||
import frappe.model.meta | import frappe.model.meta | ||||
return frappe.model.meta.get_meta(doctype, cached=cached) | return frappe.model.meta.get_meta(doctype, cached=cached) | ||||
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False): | |||||
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, | |||||
ignore_permissions=False, flags=None): | |||||
"""Delete a document. Calls `frappe.model.delete_doc.delete_doc`. | """Delete a document. Calls `frappe.model.delete_doc.delete_doc`. | ||||
:param doctype: DocType of document to be delete. | :param doctype: DocType of document to be delete. | ||||
@@ -456,7 +457,8 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa | |||||
:param for_reload: Call `before_reload` trigger before deleting. | :param for_reload: Call `before_reload` trigger before deleting. | ||||
:param ignore_permissions: Ignore user permissions.""" | :param ignore_permissions: Ignore user permissions.""" | ||||
import frappe.model.delete_doc | import frappe.model.delete_doc | ||||
frappe.model.delete_doc.delete_doc(doctype, name, force, ignore_doctypes, for_reload, ignore_permissions) | |||||
frappe.model.delete_doc.delete_doc(doctype, name, force, ignore_doctypes, for_reload, | |||||
ignore_permissions, flags) | |||||
def delete_doc_if_exists(doctype, name): | def delete_doc_if_exists(doctype, name): | ||||
"""Delete document if exists.""" | """Delete document if exists.""" | ||||
@@ -682,6 +684,10 @@ def call(fn, *args, **kwargs): | |||||
for a in fnargs: | for a in fnargs: | ||||
if a in kwargs: | if a in kwargs: | ||||
newargs[a] = kwargs.get(a) | newargs[a] = kwargs.get(a) | ||||
if "flags" in newargs: | |||||
del newargs["flags"] | |||||
return fn(*args, **newargs) | return fn(*args, **newargs) | ||||
def make_property_setter(args, ignore_validate=False, validate_fields_for_doctype=True): | def make_property_setter(args, ignore_validate=False, validate_fields_for_doctype=True): | ||||
@@ -70,10 +70,15 @@ def handle(): | |||||
if frappe.local.request.method=="PUT": | if frappe.local.request.method=="PUT": | ||||
data = json.loads(frappe.local.form_dict.data) | data = json.loads(frappe.local.form_dict.data) | ||||
doc = frappe.get_doc(doctype, name) | doc = frappe.get_doc(doctype, name) | ||||
if "flags" in data: | |||||
del data["flags"] | |||||
# Not checking permissions here because it's checked in doc.save | # Not checking permissions here because it's checked in doc.save | ||||
doc.update(data) | doc.update(data) | ||||
frappe.local.response.update({ | frappe.local.response.update({ | ||||
"data": doc.save().as_dict() | |||||
"data": doc.save().as_dict() | |||||
}) | }) | ||||
frappe.db.commit() | frappe.db.commit() | ||||
@@ -45,7 +45,7 @@ def get_bootinfo(): | |||||
tabDocType where ifnull(icon,'')!=''""")) | tabDocType where ifnull(icon,'')!=''""")) | ||||
bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType where ifnull(issingle,0)=1""") | bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType where ifnull(issingle,0)=1""") | ||||
add_home_page(bootinfo, doclist) | add_home_page(bootinfo, doclist) | ||||
add_allowed_pages(bootinfo) | |||||
bootinfo.page_info = get_allowed_pages() | |||||
load_translations(bootinfo) | load_translations(bootinfo) | ||||
add_timezone_info(bootinfo) | add_timezone_info(bootinfo) | ||||
load_conf_settings(bootinfo) | load_conf_settings(bootinfo) | ||||
@@ -65,6 +65,7 @@ def get_bootinfo(): | |||||
bootinfo.lang = unicode(bootinfo.lang) | bootinfo.lang = unicode(bootinfo.lang) | ||||
bootinfo.error_report_email = frappe.get_hooks("error_report_email") | bootinfo.error_report_email = frappe.get_hooks("error_report_email") | ||||
bootinfo.default_background_image = "/assets/frappe/images/ui/into-the-dawn.jpg" | |||||
return bootinfo | return bootinfo | ||||
@@ -73,9 +74,10 @@ def load_conf_settings(bootinfo): | |||||
for key in ['developer_mode']: | for key in ['developer_mode']: | ||||
if key in conf: bootinfo[key] = conf.get(key) | if key in conf: bootinfo[key] = conf.get(key) | ||||
def add_allowed_pages(bootinfo): | |||||
def get_allowed_pages(): | |||||
roles = frappe.get_roles() | roles = frappe.get_roles() | ||||
bootinfo.page_info = {} | |||||
page_info = {} | |||||
for p in frappe.db.sql("""select distinct | for p in frappe.db.sql("""select distinct | ||||
tabPage.name, tabPage.modified, tabPage.title | tabPage.name, tabPage.modified, tabPage.title | ||||
from `tabPage Role`, `tabPage` | from `tabPage Role`, `tabPage` | ||||
@@ -83,7 +85,7 @@ def add_allowed_pages(bootinfo): | |||||
and `tabPage Role`.parent = `tabPage`.name""" % ', '.join(['%s']*len(roles)), | and `tabPage Role`.parent = `tabPage`.name""" % ', '.join(['%s']*len(roles)), | ||||
roles, as_dict=True): | roles, as_dict=True): | ||||
bootinfo.page_info[p.name] = {"modified":p.modified, "title":p.title} | |||||
page_info[p.name] = {"modified":p.modified, "title":p.title} | |||||
# pages where role is not set are also allowed | # pages where role is not set are also allowed | ||||
for p in frappe.db.sql("""select name, modified, title | for p in frappe.db.sql("""select name, modified, title | ||||
@@ -91,7 +93,9 @@ def add_allowed_pages(bootinfo): | |||||
(select count(*) from `tabPage Role` | (select count(*) from `tabPage Role` | ||||
where `tabPage Role`.parent=tabPage.name) = 0""", as_dict=1): | where `tabPage Role`.parent=tabPage.name) = 0""", as_dict=1): | ||||
bootinfo.page_info[p.name] = {"modified":p.modified, "title":p.title} | |||||
page_info[p.name] = {"modified":p.modified, "title":p.title} | |||||
return page_info | |||||
def load_translations(bootinfo): | def load_translations(bootinfo): | ||||
if frappe.local.lang != 'en': | if frappe.local.lang != 'en': | ||||
@@ -105,6 +105,9 @@ class Comment(Document): | |||||
def on_trash(self): | def on_trash(self): | ||||
"""Removes from `_comments` in parent Document""" | """Removes from `_comments` in parent Document""" | ||||
if self.comment_doctype == "Message": | |||||
return | |||||
if (self.comment_type or "Comment") != "Comment": | if (self.comment_type or "Comment") != "Comment": | ||||
frappe.only_for("System Manager") | frappe.only_for("System Manager") | ||||
@@ -11,8 +11,9 @@ class DocShare(Document): | |||||
no_feed_on_delete = True | no_feed_on_delete = True | ||||
def validate(self): | def validate(self): | ||||
self.check_share_permssion() | |||||
self.check_share_permission() | |||||
self.cascade_permissions_downwards() | self.cascade_permissions_downwards() | ||||
self.get_doc().run_method("validate_share", self) | |||||
def cascade_permissions_downwards(self): | def cascade_permissions_downwards(self): | ||||
if self.share: | if self.share: | ||||
@@ -25,18 +26,22 @@ class DocShare(Document): | |||||
self._doc = frappe.get_doc(self.share_doctype, self.share_name) | self._doc = frappe.get_doc(self.share_doctype, self.share_name) | ||||
return self._doc | return self._doc | ||||
def check_share_permssion(self): | |||||
if not frappe.has_permission(self.share_doctype, "share", self.get_doc()): | |||||
raise frappe.PermissionError | |||||
def check_share_permission(self): | |||||
if (not self.flags.ignore_share_permission and | |||||
not frappe.has_permission(self.share_doctype, "share", self.get_doc())): | |||||
frappe.throw(_('You need to have "Share" permission'), frappe.PermissionError) | |||||
def after_insert(self): | def after_insert(self): | ||||
self.get_doc().add_comment(_("{0} shared this document with {0}").format(get_fullname(self.owner), | |||||
get_fullname(self.user))) | |||||
self.get_doc().add_comment("Shared", | |||||
_("{0} shared this document with {1}").format(get_fullname(self.owner), get_fullname(self.user))) | |||||
def on_trash(self): | def on_trash(self): | ||||
self.check_share_permssion() | |||||
self.get_doc().add_comment(_("{0} un-shared this document with {0}").format(get_fullname(self.owner), | |||||
get_fullname(self.user))) | |||||
if not self.flags.ignore_share_permission: | |||||
self.check_share_permission() | |||||
self.get_doc().add_comment("Unshared", | |||||
_("{0} un-shared this document with {1}").format(get_fullname(self.owner), get_fullname(self.user))) | |||||
def on_doctype_update(): | def on_doctype_update(): | ||||
"""Add index in `tabDocShare` for `(user, share_doctype)`""" | """Add index in `tabDocShare` for `(user, share_doctype)`""" | ||||
@@ -82,9 +82,19 @@ class User(Document): | |||||
def share_with_self(self): | def share_with_self(self): | ||||
if self.user_type=="System User": | if self.user_type=="System User": | ||||
frappe.share.add(self.doctype, self.name, self.name, share=1) | |||||
frappe.share.add(self.doctype, self.name, self.name, share=1, | |||||
flags={"ignore_share_permission": True}) | |||||
else: | else: | ||||
frappe.share.remove(self.doctype, self.name, self.name) | |||||
frappe.share.remove(self.doctype, self.name, self.name, | |||||
flags={"ignore_share_permission": True}) | |||||
def validate_share(self, docshare): | |||||
if docshare.user == self.name: | |||||
if self.user_type=="System User": | |||||
if docshare.share != 1: | |||||
frappe.throw(_("Sorry! User should have complete access to their own record.")) | |||||
else: | |||||
frappe.throw(_("Sorry! Sharing with Website User is prohibited.")) | |||||
def clear_new_password(self): | def clear_new_password(self): | ||||
new_password = self.new_password | new_password = self.new_password | ||||
@@ -4,6 +4,7 @@ frappe.pages['desktop'].on_page_load = function(wrapper) { | |||||
frappe.assets.views["Module"](); | frappe.assets.views["Module"](); | ||||
// load desktop | // load desktop | ||||
frappe.desktop.set_background(); | |||||
frappe.desktop.refresh(wrapper); | frappe.desktop.refresh(wrapper); | ||||
}; | }; | ||||
@@ -130,6 +131,11 @@ $.extend(frappe.desktop, { | |||||
}); | }); | ||||
}, | }, | ||||
set_background: function() { | |||||
frappe.ui.set_user_background(frappe.boot.user.background_image, null, | |||||
frappe.boot.user.background_style); | |||||
}, | |||||
all_applications: { | all_applications: { | ||||
show: function() { | show: function() { | ||||
if(!this.dialog) { | if(!this.dialog) { | ||||
@@ -4,6 +4,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
from frappe import _ | from frappe import _ | ||||
from frappe.boot import get_allowed_pages | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def get(module): | def get(module): | ||||
@@ -31,6 +32,7 @@ def get_data(module): | |||||
get_report_list(module)) | get_report_list(module)) | ||||
data = combine_common_sections(data) | data = combine_common_sections(data) | ||||
data = apply_permissions(data) | |||||
set_last_modified(data) | set_last_modified(data) | ||||
@@ -115,6 +117,37 @@ def combine_common_sections(data): | |||||
return sections | return sections | ||||
def apply_permissions(data): | |||||
default_country = frappe.db.get_default("country") | |||||
user = frappe.get_user(frappe.session.user) | |||||
user.build_permissions() | |||||
allowed_pages = get_allowed_pages() | |||||
new_data = [] | |||||
for section in data: | |||||
new_items = [] | |||||
for item in (section.get("items") or []): | |||||
item = frappe._dict(item) | |||||
if item.country and item.country!=default_country: | |||||
continue | |||||
if ((item.type=="doctype" and item.name in user.can_read) | |||||
or (item.type=="page" and item.name in allowed_pages) | |||||
or (item.type=="report" and item.doctype in user.can_get_report)): | |||||
new_items.append(item) | |||||
if new_items: | |||||
new_section = section.copy() | |||||
new_section["items"] = new_items | |||||
new_data.append(new_section) | |||||
return new_data | |||||
def get_config(app, module): | def get_config(app, module): | ||||
"""Load module info from `[app].config.[module]`.""" | """Load module info from `[app].config.[module]`.""" | ||||
config = frappe.get_module("{app}.config.{module}".format(app=app, module=module)) | config = frappe.get_module("{app}.config.{module}".format(app=app, module=module)) | ||||
@@ -7,10 +7,12 @@ | |||||
frappe.provide('frappe.desk.pages.messages'); | frappe.provide('frappe.desk.pages.messages'); | ||||
frappe.pages.messages.on_page_load = function(parent) { | frappe.pages.messages.on_page_load = function(parent) { | ||||
frappe.assets.views["Form"](); | |||||
var page = frappe.ui.make_app_page({ | var page = frappe.ui.make_app_page({ | ||||
parent: parent, | parent: parent, | ||||
}); | }); | ||||
page.set_title(__("Messages"), frappe.get_module("Messages").icon); | |||||
page.set_title(__("Messages")); | |||||
frappe.desk.pages.messages = new frappe.desk.pages.messages(parent); | frappe.desk.pages.messages = new frappe.desk.pages.messages(parent); | ||||
} | } | ||||
@@ -90,8 +90,7 @@ def post(txt, contact, parenttype=None, notify=False, subject=None): | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def delete(arg=None): | def delete(arg=None): | ||||
frappe.db.sql("""delete from `tabComment` where name=%s""", | |||||
frappe.form_dict['name']); | |||||
frappe.get_doc("Comment", frappe.form_dict['name']).delete() | |||||
def _notify(contact, txt, subject=None): | def _notify(contact, txt, subject=None): | ||||
from frappe.utils import get_fullname, get_url | from frappe.utils import get_fullname, get_url | ||||
@@ -18,7 +18,7 @@ | |||||
<div class="text-muted"> | <div class="text-muted"> | ||||
{%= comment_when(data.modified) %} | {%= comment_when(data.modified) %} | ||||
</div> | </div> | ||||
{% if (data.owner==user || data.comment.indexOf("assigned to")!=-1) { %} | |||||
{% if (data.owner==user /* && !data.comment_type && data.parenttype!="Assignment" */ ) { %} | |||||
<div> | <div> | ||||
<a class="delete text-extra-muted" data-name="{%= data.name %}" | <a class="delete text-extra-muted" data-name="{%= data.name %}" | ||||
onclick="frappe.desk.pages.messages.delete(this)">Delete</a> | onclick="frappe.desk.pages.messages.delete(this)">Delete</a> | ||||
@@ -1,4 +1,4 @@ | |||||
<ul class="nav nav-pills nav-stacked" style="margin-right: -15px;"> | |||||
<ul class="nav nav-pills nav-stacked"> | |||||
{% for (var i=0, l= data.length; i < l; i++) { var contact = data[i]; %} | {% for (var i=0, l= data.length; i < l; i++) { var contact = data[i]; %} | ||||
<li data-user="{%= contact.name %}" class="h6 module-sidebar-item"> | <li data-user="{%= contact.name %}" class="h6 module-sidebar-item"> | ||||
<a class="messages-sidebar-link text-ellipsis"> | <a class="messages-sidebar-link text-ellipsis"> | ||||
@@ -94,3 +94,5 @@ scheduler_events = { | |||||
"frappe.email.doctype.email_alert.email_alert.trigger_daily_alerts", | "frappe.email.doctype.email_alert.email_alert.trigger_daily_alerts", | ||||
] | ] | ||||
} | } | ||||
default_background = "/assets/frappe/images/ui/into-the-dawn.jpg" |
@@ -11,7 +11,8 @@ from frappe import _ | |||||
from rename_doc import dynamic_link_queries | from rename_doc import dynamic_link_queries | ||||
from frappe.model.naming import revert_series_if_last | from frappe.model.naming import revert_series_if_last | ||||
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False): | |||||
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, | |||||
ignore_permissions=False, flags=None): | |||||
""" | """ | ||||
Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record | Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record | ||||
""" | """ | ||||
@@ -58,7 +59,14 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa | |||||
doc = frappe.get_doc(doctype, name) | doc = frappe.get_doc(doctype, name) | ||||
if not for_reload: | if not for_reload: | ||||
check_permission_and_not_submitted(doc, ignore_permissions) | |||||
if ignore_permissions: | |||||
if not flags: flags = {} | |||||
flags["ignore_permissions"] = ignore_permissions | |||||
if flags: | |||||
doc.flags.update(flags) | |||||
check_permission_and_not_submitted(doc) | |||||
doc.run_method("on_trash") | doc.run_method("on_trash") | ||||
delete_linked_todos(doc) | delete_linked_todos(doc) | ||||
@@ -113,9 +121,9 @@ def delete_from_table(doctype, name, ignore_doctypes, doc): | |||||
if t not in ignore_doctypes: | if t not in ignore_doctypes: | ||||
frappe.db.sql("delete from `tab%s` where parenttype=%s and parent = %s" % (t, '%s', '%s'), (doctype, name)) | frappe.db.sql("delete from `tab%s` where parenttype=%s and parent = %s" % (t, '%s', '%s'), (doctype, name)) | ||||
def check_permission_and_not_submitted(doc, ignore_permissions=False): | |||||
def check_permission_and_not_submitted(doc): | |||||
# permission | # permission | ||||
if not ignore_permissions and frappe.session.user!="Administrator" and not doc.has_permission("delete"): | |||||
if frappe.session.user!="Administrator" and not doc.has_permission("delete"): | |||||
frappe.msgprint(_("User not allowed to delete {0}: {1}").format(doc.doctype, doc.name), raise_exception=True) | frappe.msgprint(_("User not allowed to delete {0}: {1}").format(doc.doctype, doc.name), raise_exception=True) | ||||
# check if submitted | # check if submitted | ||||
@@ -448,6 +448,9 @@ class Document(BaseDocument): | |||||
def run_method(self, method, *args, **kwargs): | def run_method(self, method, *args, **kwargs): | ||||
"""run standard triggers, plus those in hooks""" | """run standard triggers, plus those in hooks""" | ||||
if "flags" in kwargs: | |||||
del kwargs["flags"] | |||||
if hasattr(self, method) and hasattr(getattr(self, method), "__call__"): | if hasattr(self, method) and hasattr(getattr(self, method), "__call__"): | ||||
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs) | fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs) | ||||
else: | else: | ||||
@@ -476,7 +479,7 @@ class Document(BaseDocument): | |||||
def delete(self): | def delete(self): | ||||
"""Delete document.""" | """Delete document.""" | ||||
frappe.delete_doc(self.doctype, self.name) | |||||
frappe.delete_doc(self.doctype, self.name, flags=self.flags) | |||||
def run_before_save_methods(self): | def run_before_save_methods(self): | ||||
"""Run standard methods before `INSERT` or `UPDATE`. Standard Methods are: | """Run standard methods before `INSERT` or `UPDATE`. Standard Methods are: | ||||
@@ -117,7 +117,6 @@ def import_doc(docdict, force=False, data_import=False): | |||||
doc.flags.ignore_validate = True | doc.flags.ignore_validate = True | ||||
doc.flags.ignore_permissions = True | doc.flags.ignore_permissions = True | ||||
doc.flags.ignore_mandatory = True | doc.flags.ignore_mandatory = True | ||||
doc.flags.ignore_user_permissions = True | |||||
doc.insert() | doc.insert() | ||||
frappe.flags.in_import = False | frappe.flags.in_import = False |
@@ -306,13 +306,16 @@ kbd { | |||||
padding: 10px 15px; | padding: 10px 15px; | ||||
} | } | ||||
.message-row .indicator { | .message-row .indicator { | ||||
margin-left: -10px; | |||||
margin-left: -5px; | |||||
margin-right: -20px; | margin-right: -20px; | ||||
} | } | ||||
.message-box .indicator { | .message-box .indicator { | ||||
margin-right: 15px; | margin-right: 15px; | ||||
margin-top: 7px; | margin-top: 7px; | ||||
} | } | ||||
.message-box .timeline-head { | |||||
padding-top: 30px; | |||||
} | |||||
.page-only-label { | .page-only-label { | ||||
margin-top: 5px; | margin-top: 5px; | ||||
text-align: center; | text-align: center; | ||||
@@ -145,6 +145,16 @@ frappe.assets = { | |||||
"Module": function() { | "Module": function() { | ||||
frappe.require("assets/css/module.min.css"); | frappe.require("assets/css/module.min.css"); | ||||
frappe.require("assets/js/module.min.js"); | frappe.require("assets/js/module.min.js"); | ||||
} | |||||
}, | |||||
"Calendar": function() { | |||||
frappe.assets.views["Report"](); | |||||
frappe.require('assets/frappe/js/lib/fullcalendar/fullcalendar.css'); | |||||
frappe.require('assets/frappe/js/lib/fullcalendar/fullcalendar.js'); | |||||
}, | |||||
"Gantt": function() { | |||||
frappe.assets.views["Report"](); | |||||
frappe.require('assets/frappe/js/lib/jQuery.Gantt/css/style.css'); | |||||
frappe.require('assets/frappe/js/lib/jQuery.Gantt/js/jquery.fn.gantt.js'); | |||||
}, | |||||
} | } | ||||
}; | }; |
@@ -17,7 +17,6 @@ frappe.Application = Class.extend({ | |||||
}, | }, | ||||
startup: function() { | startup: function() { | ||||
this.load_bootinfo(); | this.load_bootinfo(); | ||||
this.set_user_display_settings(); | |||||
this.make_nav_bar(); | this.make_nav_bar(); | ||||
this.set_favicon(); | this.set_favicon(); | ||||
this.setup_keyboard_shortcuts(); | this.setup_keyboard_shortcuts(); | ||||
@@ -44,10 +43,6 @@ frappe.Application = Class.extend({ | |||||
$(document).trigger('app_ready'); | $(document).trigger('app_ready'); | ||||
}, | }, | ||||
set_user_display_settings: function() { | |||||
frappe.ui.set_user_background(frappe.boot.user.background_image, null, | |||||
frappe.boot.user.background_style); | |||||
}, | |||||
load_bootinfo: function() { | load_bootinfo: function() { | ||||
if(frappe.boot) { | if(frappe.boot) { | ||||
frappe.modules = frappe.boot.modules; | frappe.modules = frappe.boot.modules; | ||||
@@ -145,7 +145,9 @@ frappe.ui.form.Comments = Class.extend({ | |||||
"Workflow": "octicon octicon-git-branch", | "Workflow": "octicon octicon-git-branch", | ||||
"Label": "octicon octicon-tag", | "Label": "octicon octicon-tag", | ||||
"Attachment": "octicon octicon-cloud-upload", | "Attachment": "octicon octicon-cloud-upload", | ||||
"Attachment Removed": "octicon octicon-trashcan" | |||||
"Attachment Removed": "octicon octicon-trashcan", | |||||
"Shared": "octicon octicon-eye", | |||||
"Unshared": "octicon octicon-circle-slash" | |||||
}[c.comment_type] | }[c.comment_type] | ||||
c.color = { | c.color = { | ||||
@@ -25,7 +25,7 @@ | |||||
{%= data.comment_html %} | {%= data.comment_html %} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{% } else if(in_list(["Assignment Completed", "Assigned", "Shared"], data.comment_type)) { %} | |||||
{% } else if(in_list(["Assignment Completed", "Assigned", "Shared", "Unshared"], data.comment_type)) { %} | |||||
<h6> | <h6> | ||||
<i class="{%= data.icon %} icon-fixed-width"></i> | <i class="{%= data.icon %} icon-fixed-width"></i> | ||||
{%= data.comment %} | {%= data.comment %} | ||||
@@ -36,10 +36,7 @@ frappe.get_gravatar = function(email_id) { | |||||
frappe.ui.set_user_background = function(src, selector, style) { | frappe.ui.set_user_background = function(src, selector, style) { | ||||
if(!selector) selector = "#page-desktop"; | if(!selector) selector = "#page-desktop"; | ||||
if(!style) style = "Fill Screen"; | if(!style) style = "Fill Screen"; | ||||
if(!src) src = "assets/frappe/images/ui/wallpaper-5.jpg"; | |||||
// hack! load background image asap, before page is rendered | |||||
$('<img src="'+src+'" style="height: 1px; width: 1px; margin-bottom: -1px;">').appendTo("body"); | |||||
if(!src) src = frappe.boot.default_background_image; | |||||
frappe.dom.set_style(repl('%(selector)s { \ | frappe.dom.set_style(repl('%(selector)s { \ | ||||
background: url("%(src)s") center center;\ | background: url("%(src)s") center center;\ | ||||
@@ -22,10 +22,6 @@ frappe.views.CalendarFactory = frappe.views.Factory.extend({ | |||||
frappe.views.Calendar = Class.extend({ | frappe.views.Calendar = Class.extend({ | ||||
init: function(options) { | init: function(options) { | ||||
$.extend(this, options); | $.extend(this, options); | ||||
frappe.require('assets/frappe/js/lib/fullcalendar/fullcalendar.css'); | |||||
frappe.require('assets/frappe/js/lib/fullcalendar/fullcalendar.js'); | |||||
this.make_page(); | this.make_page(); | ||||
this.setup_options(); | this.setup_options(); | ||||
this.make(); | this.make(); | ||||
@@ -26,10 +26,6 @@ frappe.views.GanttFactory = frappe.views.Factory.extend({ | |||||
frappe.views.Gantt = Class.extend({ | frappe.views.Gantt = Class.extend({ | ||||
init: function(opts) { | init: function(opts) { | ||||
$.extend(this, opts); | $.extend(this, opts); | ||||
frappe.require('assets/frappe/js/lib/jQuery.Gantt/css/style.css'); | |||||
frappe.require('assets/frappe/js/lib/jQuery.Gantt/js/jquery.fn.gantt.js'); | |||||
this.make_page(); | this.make_page(); | ||||
frappe.route_options ? | frappe.route_options ? | ||||
this.set_filters_from_route_options() : | this.set_filters_from_route_options() : | ||||
@@ -353,13 +353,19 @@ kbd { | |||||
} | } | ||||
.message-row .indicator { | .message-row .indicator { | ||||
margin-left: -10px; | |||||
margin-left: -5px; | |||||
margin-right: -20px; | margin-right: -20px; | ||||
} | } | ||||
.message-box .indicator { | |||||
margin-right: 15px; | |||||
margin-top: 7px; | |||||
.message-box { | |||||
.indicator { | |||||
margin-right: 15px; | |||||
margin-top: 7px; | |||||
} | |||||
.timeline-head { | |||||
padding-top: 30px; | |||||
} | |||||
} | } | ||||
.page-only-label { | .page-only-label { | ||||
@@ -3,6 +3,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
from frappe.utils import cint | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def add(doctype, name, user=None, read=1, write=0, share=0, flags=None): | def add(doctype, name, user=None, read=1, write=0, share=0, flags=None): | ||||
@@ -14,19 +15,30 @@ def add(doctype, name, user=None, read=1, write=0, share=0, flags=None): | |||||
"share_doctype": doctype}) | "share_doctype": doctype}) | ||||
if share_name: | if share_name: | ||||
frappe.delete_doc("DocShare", share_name) | |||||
doc = frappe.get_doc("DocShare", share_name) | |||||
else: | |||||
doc = frappe.new_doc("DocShare") | |||||
doc.update({ | |||||
"user": user, | |||||
"share_doctype": doctype, | |||||
"share_name": name | |||||
}) | |||||
if flags: | |||||
doc.flags.update(flags) | |||||
doc.update({ | |||||
# always add read, since you are adding! | |||||
"read": 1, | |||||
"write": cint(write), | |||||
"share": cint(share) | |||||
}) | |||||
doc.save(ignore_permissions=True) | |||||
return doc | |||||
return frappe.get_doc({ | |||||
"doctype": "DocShare", | |||||
"user": user, | |||||
"share_doctype": doctype, | |||||
"share_name": name, | |||||
"read": read, | |||||
"write": write, | |||||
"share": share | |||||
}).insert(ignore_permissions=True) | |||||
def remove(doctype, name, user): | |||||
def remove(doctype, name, user, flags=None): | |||||
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name, | share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name, | ||||
"share_doctype": doctype}) | "share_doctype": doctype}) | ||||
@@ -48,6 +60,7 @@ def set_permission(doctype, name, user, permission_to, value=1): | |||||
pass | pass | ||||
else: | else: | ||||
share = frappe.get_doc("DocShare", share_name) | share = frappe.get_doc("DocShare", share_name) | ||||
share.flags.ignore_permissions = True | |||||
share.set(permission_to, value) | share.set(permission_to, value) | ||||
if not value: | if not value: | ||||
@@ -36,6 +36,9 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- hack! load background image asap, before desktop is rendered --> | |||||
<img src="{{ background_image }}" style="height: 1px; width: 1px; margin-bottom: -1px;"> | |||||
<script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script> | <script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script> | ||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
@@ -20,10 +20,13 @@ def get_context(context): | |||||
frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError) | frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError) | ||||
hooks = frappe.get_hooks() | hooks = frappe.get_hooks() | ||||
boot = frappe.sessions.get() | |||||
return { | return { | ||||
"build_version": str(os.path.getmtime(os.path.join(frappe.local.sites_path, "assets", "js", | "build_version": str(os.path.getmtime(os.path.join(frappe.local.sites_path, "assets", "js", | ||||
"frappe.min.js"))), | "frappe.min.js"))), | ||||
"include_js": hooks["app_include_js"], | "include_js": hooks["app_include_js"], | ||||
"include_css": hooks["app_include_css"], | "include_css": hooks["app_include_css"], | ||||
"boot": json.dumps(frappe.sessions.get(), default=json_handler, indent=1, sort_keys=True) | |||||
"boot": json.dumps(boot, default=json_handler, indent=1, sort_keys=True), | |||||
"background_image": boot.user.background_image or boot.default_background_image | |||||
} | } |