@@ -195,5 +195,4 @@ def get_badge_info(doctypes, filters): | |||
def run_onload(doc): | |||
doc.set("__onload", frappe._dict()) | |||
doc.set_onload('links', doc.meta.get_links_setup()) | |||
doc.run_method("onload") |
@@ -40,12 +40,13 @@ class FormMeta(Meta): | |||
self.load_print_formats() | |||
self.load_workflows() | |||
self.load_templates() | |||
self.load_dashboard() | |||
def as_dict(self, no_nulls=False): | |||
d = super(FormMeta, self).as_dict(no_nulls=no_nulls) | |||
for k in ("__js", "__css", "__list_js", "__calendar_js", "__map_js", | |||
"__linked_with", "__messages", "__print_formats", "__workflow_docs", | |||
"__form_grid_templates", "__listview_template", "__tree_js"): | |||
"__form_grid_templates", "__listview_template", "__tree_js", '__dashboard'): | |||
d[k] = self.get(k) | |||
for i, df in enumerate(d.get("fields")): | |||
@@ -164,6 +165,9 @@ class FormMeta(Meta): | |||
messages = make_dict_from_messages(messages) | |||
self.get("__messages").update(messages, as_value=True) | |||
def load_dashboard(self): | |||
self.set('__dashboard', self.get_dashboard_data()) | |||
def get_code_files_via_hooks(hook, name): | |||
code_files = [] | |||
for app_name in frappe.get_installed_apps(): | |||
@@ -180,7 +180,7 @@ def get_open_count(doctype, name): | |||
frappe.has_permission(doc=frappe.get_doc(doctype, name), throw=True) | |||
meta = frappe.get_meta(doctype) | |||
links = meta.get_links_setup() | |||
links = meta.get_dashboard_data() | |||
# compile all items in a list | |||
items = [] | |||
@@ -96,7 +96,6 @@ frappe.ui.form.on("Email Account", { | |||
frm.events.show_gmail_message_for_less_secure_apps(frm); | |||
}, | |||
show_gmail_message_for_less_secure_apps: function(frm) { | |||
frm.dashboard.reset(); | |||
if(frm.doc.service==="Gmail") { | |||
frm.dashboard.set_headline_alert('Gmail will only work if you allow access for less secure \ | |||
apps in Gmail settings. <a target="_blank" \ | |||
@@ -32,7 +32,6 @@ cur_frm.cscript.refresh = function(doc) { | |||
} | |||
cur_frm.cscript.setup_dashboard = function() { | |||
cur_frm.dashboard.reset(); | |||
if(!cur_frm.doc.__islocal && cint(cur_frm.doc.email_sent) && cur_frm.doc.__onload && cur_frm.doc.__onload.status_count) { | |||
var stat = cur_frm.doc.__onload.status_count; | |||
var total = frappe.utils.sum($.map(stat, function(v) { return v; })); | |||
@@ -263,17 +263,18 @@ class Meta(Document): | |||
return self.high_permlevel_fields | |||
def get_links_setup(self): | |||
'''Returns setup for documents related to this doctype. | |||
def get_dashboard_data(self): | |||
'''Returns dashboard setup related to this doctype. | |||
This method will return the `links_setup` property in the | |||
`[doctype]_links.py` file in the doctype folder''' | |||
This method will return the `data` property in the | |||
`[doctype]_dashboard.py` file in the doctype folder''' | |||
try: | |||
module = load_doctype_module(self.name, suffix='_links') | |||
return frappe._dict(module.links) | |||
module = load_doctype_module(self.name, suffix='_dashboard') | |||
data = frappe._dict(module.data) | |||
except ImportError: | |||
return frappe._dict() | |||
data = frappe._dict() | |||
return data | |||
doctype_table_fields = [ | |||
frappe._dict({"fieldname": "fields", "options": "DocField"}), | |||
@@ -25,7 +25,6 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
// clear links | |||
this.links_area.addClass('hidden'); | |||
this.transactions_area.empty(); | |||
// clear stats | |||
this.stats_area.empty().addClass('hidden'); | |||
@@ -112,25 +111,44 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
return progress_chart; | |||
}, | |||
// | |||
show_dashboard: function() { | |||
refresh: function() { | |||
this.reset(); | |||
if(this.frm.doc.__islocal) | |||
if(this.frm.doc.__islocal) { | |||
return; | |||
} | |||
if(!this.links) { | |||
this.links = this.frm.doc.__onload.links; | |||
if(!this.data) { | |||
this.data = this.frm.meta.__dashboard; | |||
this.filter_permissions(); | |||
} | |||
this.render_links(); | |||
this.set_open_count(); | |||
this.render_heatmap(); | |||
var show = false; | |||
if(this.data && (this.data.transactions || []).length) { | |||
if(this.data.docstatus && this.frm.doc.docstatus !== this.data.docstatus) { | |||
// limited docstatus | |||
return; | |||
} | |||
this.render_links(); | |||
this.set_open_count(); | |||
show = true; | |||
} | |||
if(this.data.heatmap) { | |||
this.render_heatmap(); | |||
show = true; | |||
} | |||
if(show) { | |||
this.show(); | |||
} | |||
}, | |||
filter_permissions: function() { | |||
// filter out transactions for which the user | |||
// does not have permission | |||
var transactions = []; | |||
(this.links.transactions || []).forEach(function(group) { | |||
(this.data.transactions || []).forEach(function(group) { | |||
var items = []; | |||
group.items.forEach(function(doctype) { | |||
if(frappe.model.can_read(doctype)) { | |||
@@ -145,12 +163,17 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
transactions.push(group); | |||
} | |||
}); | |||
this.links.transactions = transactions; | |||
this.data.transactions = transactions; | |||
}, | |||
render_links: function() { | |||
var me = this; | |||
this.links_area.removeClass('hidden'); | |||
if(this.data_rendered) { | |||
return; | |||
} | |||
$(frappe.render_template('form_links', | |||
{transactions: this.links.transactions})) | |||
{transactions: this.data.transactions})) | |||
.appendTo(this.transactions_area) | |||
// bind links | |||
@@ -163,8 +186,7 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
me.open_document_list($(this).parent().attr('data-doctype'), true); | |||
}); | |||
this.show(); | |||
this.links_area.removeClass('hidden'); | |||
this.data_rendered = true; | |||
}, | |||
open_document_list: function(doctype, show_open) { | |||
// show document list with filters | |||
@@ -179,22 +201,26 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
// return the default filter for the given document | |||
// like {"customer": frm.doc.name} | |||
var filter = {}; | |||
var fieldname = this.links.non_standard_fieldnames | |||
? (this.links.non_standard_fieldnames[doctype] || this.links.fieldname) | |||
: this.links.fieldname; | |||
var fieldname = this.data.non_standard_fieldnames | |||
? (this.data.non_standard_fieldnames[doctype] || this.data.fieldname) | |||
: this.data.fieldname; | |||
filter[fieldname] = this.frm.doc.name; | |||
return filter; | |||
}, | |||
set_open_count: function() { | |||
if(!this.data.transactions) { | |||
return; | |||
} | |||
// list all items from the transaction list | |||
var items = [], | |||
me = this; | |||
this.links.transactions.forEach(function(group) { | |||
this.data.transactions.forEach(function(group) { | |||
group.items.forEach(function(item) { items.push(item); }); | |||
}); | |||
method = this.links.method || 'frappe.desk.notifications.get_open_count'; | |||
method = this.data.method || 'frappe.desk.notifications.get_open_count'; | |||
frappe.call({ | |||
type: "GET", | |||
@@ -204,7 +230,9 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
name: this.frm.doc.name, | |||
}, | |||
callback: function(r) { | |||
me.heatmap && me.heatmap.update(r.message.timeline_data); | |||
if(r.message.timeline_data) { | |||
me.update_heatmap(r.message.timeline_data); | |||
} | |||
$.each(r.message.count, function(i, d) { | |||
me.frm.dashboard.set_badge_count(d.name, cint(d.open_count), cint(d.count)); | |||
}); | |||
@@ -231,9 +259,15 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
}, | |||
update_heatmap: function(data) { | |||
if(this.heatmap) { | |||
this.heatmap.update(data); | |||
} | |||
}, | |||
// heatmap | |||
render_heatmap: function() { | |||
if(this.show_heatmap && !this.heatmap) { | |||
if(!this.heatmap) { | |||
this.heatmap = new CalHeatMap(); | |||
this.heatmap.init({ | |||
itemSelector: "#heatmap-" + this.frm.doctype, | |||
@@ -257,8 +291,8 @@ frappe.ui.form.Dashboard = Class.extend({ | |||
// message | |||
var heatmap_message = this.heatmap_area.find('.heatmap-message'); | |||
if(this.heatmap_message) { | |||
heatmap_message.removeClass('hidden').html(this.heatmap_message); | |||
if(this.data.heatmap_message) { | |||
heatmap_message.removeClass('hidden').html(this.data.heatmap_message); | |||
} else { | |||
heatmap_message.addClass('hidden'); | |||
} | |||
@@ -346,7 +346,14 @@ _f.Frm.prototype.refresh_header = function(is_a_different_doc) { | |||
} | |||
this.document_flow.refresh(); | |||
this.dashboard.reset(); | |||
this.dashboard.refresh(); | |||
if(this.meta.is_submittable && | |||
! this.is_dirty() && | |||
! this.is_new() && | |||
this.doc.docstatus===0) { | |||
this.dashboard.add_comment(__('Submit this document to confirm'), true); | |||
} | |||
this.clear_custom_buttons(); | |||
@@ -827,11 +834,6 @@ _f.Frm.prototype.save_or_update = function() { | |||
} | |||
} | |||
_f.get_value = function(dt, dn, fn) { | |||
if(locals[dt] && locals[dt][dn]) | |||
return locals[dt][dn][fn]; | |||
} | |||
_f.Frm.prototype.dirty = function() { | |||
this.doc.__unsaved = 1; | |||
$(this.wrapper).trigger('dirty'); | |||
@@ -841,6 +843,15 @@ _f.Frm.prototype.get_docinfo = function() { | |||
return frappe.model.docinfo[this.doctype][this.docname]; | |||
} | |||
_f.Frm.prototype.is_dirty = function() { | |||
return this.doc.__unsaved; | |||
} | |||
_f.Frm.prototype.is_new = function() { | |||
return this.doc.__islocal; | |||
} | |||
_f.Frm.prototype.reload_docinfo = function(callback) { | |||
var me = this; | |||
frappe.call({ | |||
@@ -42,6 +42,10 @@ _p.preview = function(html) { | |||
return w | |||
} | |||
_f.get_value = function(dt, dn, fn) { | |||
if(locals[dt] && locals[dt][dn]) | |||
return locals[dt][dn][fn]; | |||
} | |||
// _p can be referenced as this inside $.extend | |||
$.extend(_p, { | |||