|
@@ -3,156 +3,162 @@ |
|
|
|
|
|
|
|
|
frappe.provide("frappe.ui.form"); |
|
|
frappe.provide("frappe.ui.form"); |
|
|
|
|
|
|
|
|
frappe.ui.form.LinkedWith = Class.extend({ |
|
|
|
|
|
init: function(opts) { |
|
|
|
|
|
var me = this; |
|
|
|
|
|
|
|
|
frappe.ui.form.LinkedWith = class LinkedWith { |
|
|
|
|
|
|
|
|
|
|
|
constructor(opts) { |
|
|
$.extend(this, opts); |
|
|
$.extend(this, opts); |
|
|
}, |
|
|
|
|
|
show: function() { |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
show() { |
|
|
if(!this.dialog) |
|
|
if(!this.dialog) |
|
|
this.make_dialog(); |
|
|
this.make_dialog(); |
|
|
|
|
|
|
|
|
this.dialog.fields_dict.list.$wrapper.html('<div class="text-muted text-center" style="padding: 30px 0px">' |
|
|
|
|
|
+ __("Loading") + '...</div>'); |
|
|
|
|
|
|
|
|
$(this.dialog.body).html( |
|
|
|
|
|
`<div class="text-muted text-center" style="padding: 30px 0px"> |
|
|
|
|
|
${__("Loading")}... |
|
|
|
|
|
</div>`); |
|
|
|
|
|
|
|
|
this.dialog.show(); |
|
|
this.dialog.show(); |
|
|
}, |
|
|
|
|
|
make_dialog: function() { |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
make_dialog() { |
|
|
var me = this; |
|
|
var me = this; |
|
|
|
|
|
|
|
|
this.dialog = new frappe.ui.Dialog({ |
|
|
this.dialog = new frappe.ui.Dialog({ |
|
|
hide_on_page_refresh: true, |
|
|
hide_on_page_refresh: true, |
|
|
title: __("Linked With"), |
|
|
|
|
|
fields: [ |
|
|
|
|
|
{ fieldtype: "HTML", label: "list" } |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
title: __("Linked With") |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.dialog.$wrapper.find(".modal-dialog").addClass("linked-with-dialog"); |
|
|
|
|
|
|
|
|
|
|
|
this.dialog.on_page_show = function() { |
|
|
|
|
|
|
|
|
this.dialog.on_page_show = () => { |
|
|
// execute ajax calls sequentially |
|
|
// execute ajax calls sequentially |
|
|
// 1. get linked doctypes |
|
|
// 1. get linked doctypes |
|
|
// 2. load all doctypes |
|
|
// 2. load all doctypes |
|
|
// 3. load linked docs |
|
|
// 3. load linked docs |
|
|
$.when(me.get_linked_doctypes()) |
|
|
|
|
|
.then(function() { return me.load_doctypes() }) |
|
|
|
|
|
.then(function() { |
|
|
|
|
|
if (me.links_not_permitted_or_missing()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return me.get_linked_docs(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.get_linked_doctypes() |
|
|
|
|
|
.then(() => this.load_doctypes()) |
|
|
|
|
|
.then(() => this.links_not_permitted_or_missing()) |
|
|
|
|
|
.then(() => this.get_linked_docs()) |
|
|
|
|
|
.then(() => this.make_html()) |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
load_doctypes: function() { |
|
|
|
|
|
var me = this; |
|
|
|
|
|
var already_loaded = Object.keys(locals.DocType); |
|
|
|
|
|
var doctypes_to_load = []; |
|
|
|
|
|
if (me.frm.__linked_doctypes) { |
|
|
|
|
|
$.each(Object.keys(me.frm.__linked_doctypes), function(i, v) { |
|
|
|
|
|
if (already_loaded.indexOf(v)===-1) { |
|
|
|
|
|
doctypes_to_load.push(v); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
make_html() { |
|
|
|
|
|
const linked_docs = this.frm.__linked_docs; |
|
|
|
|
|
|
|
|
|
|
|
let html; |
|
|
|
|
|
|
|
|
|
|
|
if(Object.keys(linked_docs).length === 0) { |
|
|
|
|
|
html = __("Not Linked to any record"); |
|
|
|
|
|
} else { |
|
|
|
|
|
html = Object.keys(linked_docs).map(dt => { |
|
|
|
|
|
return `<div class="list-item-table" style="margin-bottom: 15px"> |
|
|
|
|
|
${this.make_doc_head(dt)} |
|
|
|
|
|
${linked_docs[dt] |
|
|
|
|
|
.map(doc => this.make_doc_row(doc, dt)) |
|
|
|
|
|
.join("")} |
|
|
|
|
|
</div>`; |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
// load all doctypes sequentially using with_doctype |
|
|
|
|
|
return $.when.apply($, $.map(doctypes_to_load, function(dt) { |
|
|
|
|
|
return frappe.model.with_doctype(dt, function() { |
|
|
|
|
|
if (frappe.listview_settings[dt]) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$(this.dialog.body).html(html); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
load_doctypes() { |
|
|
|
|
|
const already_loaded = Object.keys(locals.DocType); |
|
|
|
|
|
let doctypes_to_load = []; |
|
|
|
|
|
|
|
|
|
|
|
if (this.frm.__linked_doctypes) { |
|
|
|
|
|
doctypes_to_load = |
|
|
|
|
|
Object.keys(this.frm.__linked_doctypes) |
|
|
|
|
|
.filter(doctype => !already_loaded.includes(doctype)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// load all doctypes asynchronously using with_doctype |
|
|
|
|
|
const promises = doctypes_to_load.map(dt => { |
|
|
|
|
|
return frappe.model.with_doctype(dt, () => { |
|
|
|
|
|
if(frappe.listview_settings[dt]) { |
|
|
// add additional fields to __linked_doctypes |
|
|
// add additional fields to __linked_doctypes |
|
|
me.frm.__linked_doctypes[dt].add_fields = frappe.listview_settings[dt].add_fields; |
|
|
|
|
|
|
|
|
this.frm.__linked_doctypes[dt].add_fields = |
|
|
|
|
|
frappe.listview_settings[dt].add_fields; |
|
|
} |
|
|
} |
|
|
}, /*async*/ false); |
|
|
|
|
|
})); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return Promise.all(promises); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
links_not_permitted_or_missing: function() { |
|
|
|
|
|
|
|
|
links_not_permitted_or_missing() { |
|
|
var me = this; |
|
|
var me = this; |
|
|
var links = []; |
|
|
|
|
|
$.each(me.frm.__linked_doctypes, function(doctype, tmp) { |
|
|
|
|
|
if(frappe.model.can_get_report(doctype)) { |
|
|
|
|
|
links.push({label: __(doctype), value: doctype}); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
let links = null; |
|
|
|
|
|
|
|
|
links = frappe.utils.sort(links, "label"); |
|
|
|
|
|
|
|
|
links = |
|
|
|
|
|
Object.keys(this.frm.__linked_doctypes) |
|
|
|
|
|
.filter(frappe.model.can_get_report); |
|
|
|
|
|
|
|
|
|
|
|
let flag; |
|
|
if(!links) { |
|
|
if(!links) { |
|
|
me.dialog.fields_dict.list.$wrapper.html("<div class='alert alert-warning'>" |
|
|
|
|
|
+ me.frm.doctype + ": " |
|
|
|
|
|
+ (me.frm.__linked_doctypes ? __("Not Linked to any record.") : __("Not enough permission to see links.")) |
|
|
|
|
|
+ "</div>") |
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
$(this.dialog.body).html( |
|
|
|
|
|
`${this.frm.__linked_doctypes |
|
|
|
|
|
? __("Not enough permission to see links") |
|
|
|
|
|
: __("Not Linked to any record")}`); |
|
|
|
|
|
flag = true; |
|
|
} |
|
|
} |
|
|
|
|
|
flag = false; |
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
get_linked_doctypes: function() { |
|
|
|
|
|
var me = this; |
|
|
|
|
|
if (this.frm.__linked_doctypes) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// reject Promise if not_permitted or missing |
|
|
|
|
|
return new Promise( |
|
|
|
|
|
(resolve, reject) => flag ? reject() : resolve() |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return frappe.call({ |
|
|
|
|
|
method: "frappe.desk.form.linked_with.get_linked_doctypes", |
|
|
|
|
|
args: { |
|
|
|
|
|
doctype: this.frm.doctype |
|
|
|
|
|
}, |
|
|
|
|
|
callback: function(r) { |
|
|
|
|
|
me.frm.__linked_doctypes = r.message; |
|
|
|
|
|
|
|
|
get_linked_doctypes() { |
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
|
if (this.frm.__linked_doctypes) { |
|
|
|
|
|
resolve(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
frappe.call({ |
|
|
|
|
|
method: "frappe.desk.form.linked_with.get_linked_doctypes", |
|
|
|
|
|
args: { |
|
|
|
|
|
doctype: this.frm.doctype |
|
|
|
|
|
}, |
|
|
|
|
|
callback: (r) => { |
|
|
|
|
|
this.frm.__linked_doctypes = r.message; |
|
|
|
|
|
resolve(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
get_linked_docs: function() { |
|
|
|
|
|
var me = this; |
|
|
|
|
|
|
|
|
get_linked_docs() { |
|
|
return frappe.call({ |
|
|
return frappe.call({ |
|
|
method:"frappe.desk.form.linked_with.get_linked_docs", |
|
|
|
|
|
|
|
|
method: "frappe.desk.form.linked_with.get_linked_docs", |
|
|
args: { |
|
|
args: { |
|
|
doctype: me.frm.doctype, |
|
|
|
|
|
name: me.frm.docname, |
|
|
|
|
|
linkinfo: me.frm.__linked_doctypes, |
|
|
|
|
|
for_doctype: me.for_doctype |
|
|
|
|
|
|
|
|
doctype: this.frm.doctype, |
|
|
|
|
|
name: this.frm.docname, |
|
|
|
|
|
linkinfo: this.frm.__linked_doctypes, |
|
|
|
|
|
for_doctype: this.for_doctype |
|
|
}, |
|
|
}, |
|
|
callback: function(r) { |
|
|
|
|
|
var parent = me.dialog.fields_dict.list.$wrapper.empty(); |
|
|
|
|
|
|
|
|
|
|
|
if(keys(r.message || {}).length) { |
|
|
|
|
|
$.each(keys(r.message).sort(), function(i, doctype) { |
|
|
|
|
|
|
|
|
|
|
|
if (Object.keys(locals.DocType).indexOf(doctype)=== -1) { |
|
|
|
|
|
frappe.model.with_doctype(doctype, function() { |
|
|
|
|
|
if (frappe.listview_settings[doctype]) { |
|
|
|
|
|
// add additional fields to __linked_doctypes |
|
|
|
|
|
me.frm.__linked_doctypes[doctype] = {} |
|
|
|
|
|
me.frm.__linked_doctypes[doctype].add_fields = frappe.listview_settings[doctype].add_fields; |
|
|
|
|
|
} |
|
|
|
|
|
}, /*async*/ false); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var listview = frappe.views.get_listview(doctype, me); |
|
|
|
|
|
listview.no_delete = true; |
|
|
|
|
|
me.current_view = "List" |
|
|
|
|
|
|
|
|
|
|
|
var wrapper = $('<div class="panel panel-default"><div>').appendTo(parent); |
|
|
|
|
|
$('<div class="panel-heading">').html(__(doctype).bold()).appendTo(wrapper); |
|
|
|
|
|
var body = $('<div class="panel-body">').appendTo(wrapper); |
|
|
|
|
|
|
|
|
|
|
|
$.each(r.message[doctype], function(i, d) { |
|
|
|
|
|
d.doctype = doctype; |
|
|
|
|
|
listview.render($('<div class="list-row"></div>') |
|
|
|
|
|
.appendTo(body), d, me); |
|
|
|
|
|
}) |
|
|
|
|
|
}) |
|
|
|
|
|
} else { |
|
|
|
|
|
parent.html(__("Not Linked to any record.")); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
callback: (r) => { |
|
|
|
|
|
this.frm.__linked_docs = r.message || {}; |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
make_doc_head(heading) { |
|
|
|
|
|
return `<div class="list-item list-item--head"> |
|
|
|
|
|
<div class="list-item__content"> |
|
|
|
|
|
${heading} |
|
|
|
|
|
</div></div>`; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
make_doc_row(doc, doctype) { |
|
|
|
|
|
return `<div class="list-item-container"> |
|
|
|
|
|
<div class="list-item"> |
|
|
|
|
|
<div class="list-item__content bold"> |
|
|
|
|
|
<a href="#Form/${doctype}/${doc.name}">${doc.name}</a> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div>`; |
|
|
|
|
|
} |
|
|
|
|
|
} |