diff --git a/public/build.json b/public/build.json index af15a55f51..668619f335 100644 --- a/public/build.json +++ b/public/build.json @@ -143,6 +143,7 @@ "lib/public/js/legacy/wn/widgets/form/comments.js", "lib/public/js/legacy/wn/widgets/form/attachments.js", "lib/public/js/legacy/wn/widgets/form/assign_to.js", + "lib/public/js/wn/form/linked_with.js", 'lib/public/js/lib/jquery/jquery.ui.interactions.min.js', diff --git a/public/js/legacy/widgets/form/fields.js b/public/js/legacy/widgets/form/fields.js index fecf18fc48..89d134ac80 100644 --- a/public/js/legacy/widgets/form/fields.js +++ b/public/js/legacy/widgets/form/fields.js @@ -998,14 +998,17 @@ SelectField.prototype.make_input = function() { if(this.file_attach) this.set_attach_options(); - me.options_list = me.df.options?me.df.options.split('\n'):['']; + if(typeof me.df.options=="object") + me.options_list = me.df.options + else + me.options_list = me.df.options?me.df.options.split('\n'):['']; // add options - empty_select(this.input); if(me.in_filter && me.options_list[0]!='') { - me.options_list = add_lists([''], me.options_list); + me.options_list = add_lists([''], me.options_list); } - add_sel_options(this.input, me.options_list); + + $(this.input).empty().add_options(me.options_list); } // refresh options @@ -1197,7 +1200,7 @@ function makeinput_popup(me, iconsrc, iconsrc1, iconsrc2) { } if(iconsrc2) { - var c3 = tab.rows[0].insertCell(3); + var c3 = tab.rows[0].insertCell(tab.rows[0].cells.length); $y(c3,{width: '20px'}); me.btn2 = $a(c3, 'i', iconsrc2, icon_style) me.btn2.setAttribute('title','Create New'); diff --git a/public/js/legacy/wn/widgets/form/sidebar.js b/public/js/legacy/wn/widgets/form/sidebar.js index 25d60552c2..7fae9ef56c 100644 --- a/public/js/legacy/wn/widgets/form/sidebar.js +++ b/public/js/legacy/wn/widgets/form/sidebar.js @@ -37,24 +37,7 @@ wn.widgets.form.sidebar = { Sidebar: function(form) { }, onclick: function() { new_doc(me.form.doctype) } }, - - { - type: 'link', - label: 'List', - icon: 'icon-list', - display: function() { - return !me.form.meta.issingle && !me.form.meta.read_only; - }, - onclick: function() { window.location.href="#!List/" + me.form.doctype } - }, - { - type: 'link', - label: 'Refresh', - icon: 'icon-refresh', - onclick: function() { me.form.reload_doc() } - }, - { type: 'link', label: 'Print', @@ -104,6 +87,23 @@ wn.widgets.form.sidebar = { Sidebar: function(form) { }, icon: 'icon-retweet', onclick: function() { me.form.rename_doc() } + }, + + { + type: 'link', + label: 'Linked With', + display: function() { + return !me.form.doc.__islocal; + }, + icon: 'icon-random', + onclick: function() { + if(!me.form.linked_with) { + me.form.linked_with = new wn.ui.form.LinkedWith({ + frm: me.form + }); + } + me.form.linked_with.show(); + } } ], diff --git a/public/js/wn/form/formatters.js b/public/js/wn/form/formatters.js index 4113e8fcd3..be41e94d45 100644 --- a/public/js/wn/form/formatters.js +++ b/public/js/wn/form/formatters.js @@ -1,24 +1,4 @@ -// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) -// -// MIT License (MIT) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// for license information please see license.txt wn.provide("wn.form.formatters") wn.form.formatters = { diff --git a/public/js/wn/form/linked_with.js b/public/js/wn/form/linked_with.js new file mode 100644 index 0000000000..67f677ce5d --- /dev/null +++ b/public/js/wn/form/linked_with.js @@ -0,0 +1,106 @@ +// for license information please see license.txt + +wn.provide("wn.ui.form") + +wn.ui.form.LinkedWith = Class.extend({ + init: function(opts) { + var me = this; + $.extend(this, opts); + }, + show: function() { + if(!this.dialog) + this.make_dialog(); + + this.dialog.show(); + this.dialog.get_input("list_by").change(); + }, + make_dialog: function() { + var me = this; + this.linked_with = this.frm.meta.__linked_with; + var links = $.map(keys(this.linked_with), function(v) { + return in_list(wn.boot.profile.can_get_report, v) ? {value:v, label:wn._(v)} : null + }).sort(function(a, b) { return a.label > b.label ? 1 : -1 }); + + this.dialog = new wn.ui.Dialog({ + width: 640, + title: wn._("Linked With"), + fields: [ + { fieldtype: "HTML", label: "help", + options:"
" + wn._("List of records in which this document is linked") + +"
" }, + { fieldtype: "Select", options: links, + label: wn._("Type"), fieldname: "list_by" }, + { fieldtype: "HTML", label: "hr", options:"
" }, + { fieldtype: "HTML", label: "list" } + ] + }); + + this.dialog.get_input("list_by").val(links[0].value); + + if(!links) { + this.dialog.fields_dict.list.$wrapper.html("
" + + this.frm.doctype + ": " + + (this.linked_with ? wn._("Not Linked to any record.") : wn._("Not enough permission to see links.")) + + "
") + this.dialog.fields_dict.list_by.$wrapper.toggle(false); + this.dialog.fields_dict.help.$wrapper.toggle(false); + return; + } + + this.dialog.get_input("list_by").change(function() { + me.doctype = me.dialog.get_input("list_by").val(); + me.is_table = (!in_list(wn.boot.profile.can_read, me.doctype) && + in_list(wn.boot.profile.can_get_report, me.doctype)) + + wn.model.with_doctype(me.doctype, function(r) { + me.make_listing(); + me.lst.run(); + }) + }) + }, + make_listing: function() { + var me = this; + this.lst = new wn.ui.Listing({ + hide_refresh: true, + no_loading: true, + no_toolbar: true, + doctype: me.doctype, + show_filters: true, + parent: $(this.dialog.fields_dict.list.wrapper).empty().css("min-height", "300px") + .get(0), + method: 'webnotes.widgets.reportview.get', + get_args: function() { + return { + doctype: me.doctype, + fields: [ '`tab' + me.doctype + '`.name', + '`tab' + me.doctype + '`.modified', + '`tab' + me.doctype + '`.modified_by', + '`tab' + me.doctype + '`.docstatus'], + filters: me.lst.filter_list.get_filters(), + docstatus: ['0','1'] + } + }, + render_row: function(parent, data) { + $(parent).html(repl('%(avatar)s \ + \ + %(doctype)s: %(name)s\ + Last Updated: %(modified)s', { + avatar: wn.avatar(data.modified_by, null, + "Last Modified By: " + wn.user_info(data.modified_by).fullname), + doctype: me.is_table ? data.parenttype : me.doctype, + modified: dateutil.comment_when(data.modified), + name: me.is_table ? data.parent : data.name + })).find('.avatar img').centerImage(); + }, + get_no_result_message: function() { + return repl("
%(doctype)s: " + wn._("Not linked") + "
", { + name: me.frm.doc.name, + doctype: wn._(me.doctype) + }) + } + }); + me.lst.filter_list.show_filters(true); + me.lst.filter_list.clear_filters(); + me.lst.set_filter(me.linked_with[me.doctype], me.frm.doc.name); + } +}); \ No newline at end of file diff --git a/public/js/wn/misc/user.js b/public/js/wn/misc/user.js index cded9b8f88..952d4cd5e4 100644 --- a/public/js/wn/misc/user.js +++ b/public/js/wn/misc/user.js @@ -14,6 +14,20 @@ wn.user_info = function(uid) { return wn.boot.user_info[uid]; } +wn.avatar = function(user, large, title) { + var image = wn.user_info(user).image; + var to_size = large ? 72 : 30; + if(!title) title = wn.user_info(user).fullname; + + return repl('\ + ', { + image: image, + len: to_size + "px", + title: title + }); +} + wn.provide('wn.user'); $.extend(wn.user, { diff --git a/public/js/wn/ui/filters.js b/public/js/wn/ui/filters.js index dd00fb069c..35b971d48a 100644 --- a/public/js/wn/ui/filters.js +++ b/public/js/wn/ui/filters.js @@ -45,6 +45,11 @@ wn.ui.FilterList = Class.extend({ if(!this.filters.length) this.add_filter(); }, + + clear_filters: function() { + this.filters = []; + this.$w.find('.filter_area').empty(); + }, add_filter: function(tablename, fieldname, condition, value) { this.push_new_filter(tablename, fieldname, condition, value); diff --git a/public/js/wn/ui/listing.js b/public/js/wn/ui/listing.js index d691c02292..5e4071d068 100644 --- a/public/js/wn/ui/listing.js +++ b/public/js/wn/ui/listing.js @@ -279,7 +279,16 @@ wn.ui.Listing = Class.extend({ } else { if(this.start==0) { this.$w.find('.result').toggle(false); - this.$w.find('.no-result').toggle(true); + + var msg = this.get_no_result_message + ? this.get_no_result_message() + : (this.no_result_message + ? this.no_result_message + : wn._("Nothing to show")); + + this.$w.find('.no-result') + .html(msg) + .toggle(true); } } @@ -331,5 +340,35 @@ wn.ui.Listing = Class.extend({ add_limits: function(query) { query += ' LIMIT ' + this.start + ',' + (this.page_length+1); return query - } + }, + set_filter: function(fieldname, label) { + var filter = this.filter_list.get_filter(fieldname); + //this.filter_list.show_filters(true); + if(filter) { + var v = filter.field.get_value(); + if(v.indexOf(label)!=-1) { + // already set + return false; + } else { + // second filter set for this field + if(fieldname=='_user_tags') { + // and for tags + this.filter_list.add_filter(this.doctype, fieldname, + 'like', '%' + label); + } else { + // or for rest using "in" + filter.set_values(this.doctype, fieldname, 'in', v + ', ' + label); + } + } + } else { + // no filter for this item, + // setup one + if(fieldname=='_user_tags') { + this.filter_list.add_filter(this.doctype, fieldname, + 'like', '%' + label); + } else { + this.filter_list.add_filter(this.doctype, fieldname, '=', label); + } + } + } }); \ No newline at end of file diff --git a/public/js/wn/ui/search.js b/public/js/wn/ui/search.js index 40637a0548..338f85cdd6 100644 --- a/public/js/wn/ui/search.js +++ b/public/js/wn/ui/search.js @@ -37,7 +37,7 @@ wn.ui.Search = Class.extend({ fields: [ '`tab' + me.doctype + '`.name'], filters: me.list.filter_list.get_filters(), docstatus: ['0','1'] - } + } } }, render_row: function(parent, data) { diff --git a/webnotes/model/doctype.py b/webnotes/model/doctype.py index 10e0d5d0ef..f0fb8c64bd 100644 --- a/webnotes/model/doctype.py +++ b/webnotes/model/doctype.py @@ -65,7 +65,7 @@ def get(doctype, processed=False): expand_selects(doclist) add_print_formats(doclist) add_search_fields(doclist) - #add_linked_with(doclist) + add_linked_with(doclist) #add_workflows(doclist) #update_language(doclist)