frappe.templates['listing'] = '
{%= frappe.messages.get_waiting_message(__("Loading") + "..." ) %}
'; frappe.provide('frappe.ui'); frappe.ui.BaseList = Class.extend({ init: function init(opts) { this.opts = opts || {}; this.set_defaults(); if (opts) { this.make(); } }, set_defaults: function set_defaults() { this.page_length = 20; this.start = 0; this.data = []; }, make: function make(opts) { if (opts) { this.opts = opts; } this.prepare_opts(); $.extend(this, this.opts); this.wrapper = $(frappe.render_template('listing', this.opts)); this.parent.append(this.wrapper); this.set_events(); if (this.page) { this.wrapper.find('.list-toolbar-wrapper').hide(); } if (this.show_filters) { this.make_filters(); } }, prepare_opts: function prepare_opts() { if (this.opts.new_doctype) { if (!frappe.boot.user.can_create.includes(this.opts.new_doctype)) { this.opts.new_doctype = null; } } if (!this.opts.no_result_message) { this.opts.no_result_message = __('Nothing to show'); } if (!this.opts.page_length) { this.opts.page_length = this.user_settings && this.user_settings.limit || 20; } this.opts._more = __('More'); }, add_button: function add_button(label, click, icon) { if (this.page) { return this.page.add_menu_item(label, click, icon); } else { this.wrapper.find('.list-toolbar-wrapper').removeClass('hide'); return $('').appendTo(this.wrapper.find('.list-toolbar')).html((icon ? ' ' : '') + label).click(click); } }, set_events: function set_events() { var me = this; this.wrapper.find('.btn-more').click(function () { me.run(true); }); this.wrapper.find(".btn-group-paging").on('click', '.btn', function () { me.page_length = cint($(this).attr("data-value")); me.wrapper.find(".btn-group-paging .btn-info").removeClass("btn-info"); $(this).addClass("btn-info"); me.run(); }); if (this.opts.page_length !== 20) { this.wrapper.find(".btn-group-paging .btn-info").removeClass("btn-info"); this.wrapper.find(".btn-group-paging .btn[data-value='" + this.opts.page_length + "']").addClass('btn-info'); } if (this.title) { this.wrapper.find('h3').html(this.title).show(); } this.set_primary_action(); if (me.no_toolbar || me.hide_toolbar) { me.wrapper.find('.list-toolbar-wrapper').hide(); } }, set_primary_action: function set_primary_action() { var me = this; if (this.new_doctype) { this.page.set_primary_action(__("New"), me.make_new_doc.bind(me, me.new_doctype), "octicon octicon-plus"); } else { this.page.clear_primary_action(); } }, make_new_doc: function make_new_doc(doctype) { var me = this; frappe.model.with_doctype(doctype, function () { if (me.custom_new_doc) { me.custom_new_doc(doctype); } else { if (me.filter_list) { frappe.route_options = {}; me.filter_list.get_filters().forEach(function (f, i) { if (f[2] === "=" && !frappe.model.std_fields_list.includes(f[1])) { frappe.route_options[f[1]] = f[3]; } }); } frappe.new_doc(doctype, true); } }); }, make_filters: function make_filters() { this.make_standard_filters(); this.filter_list = new frappe.ui.FilterList({ base_list: this, parent: this.wrapper.find('.list-filters').show(), doctype: this.doctype, filter_fields: this.filter_fields, default_filters: this.default_filters || [] }); if (frappe.model.is_submittable(this.doctype)) { this.filter_list.add_filter(this.doctype, "docstatus", "!=", 2); } }, make_standard_filters: function make_standard_filters() { var me = this; if (this.standard_filters_added) { return; } if (this.meta) { this.page.add_field({ fieldtype: 'Data', label: 'ID', condition: 'like', fieldname: 'name', onchange: function onchange() { me.refresh(true); } }); this.meta.fields.forEach(function (df) { if (df.in_standard_filter && !frappe.model.no_value_type.includes(df.fieldtype)) { var options = df.options; var condition = '='; var fieldtype = df.fieldtype; if (['Text', 'Small Text', 'Text Editor', 'Data'].includes(fieldtype)) { fieldtype = 'Data', condition = 'like'; } if (df.fieldtype == "Select" && df.options) { options = df.options.split("\n"); if (options.length > 0 && options[0] != "") { options.unshift(""); options = options.join("\n"); } } me.page.add_field({ fieldtype: fieldtype, label: __(df.label), options: options, fieldname: df.fieldname, condition: condition, onchange: function onchange() { me.refresh(true); } }); } }); } this.standard_filters_added = true; }, update_standard_filters: function update_standard_filters(filters) { var me = this; for (var key in this.page.fields_dict) { var field = this.page.fields_dict[key]; var value = field.get_value(); if (value) { if (field.df.condition === 'like' && !value.includes('%')) { value = '%' + value + '%'; } filters.push([me.doctype, field.df.fieldname, field.df.condition || '=', value]); } } }, clear: function clear() { this.data = []; this.wrapper.find('.result-list').empty(); this.wrapper.find('.result').show(); this.wrapper.find('.no-result').hide(); this.start = 0; this.onreset && this.onreset(); }, set_filters_from_route_options: function set_filters_from_route_options() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$clear_filters = _ref.clear_filters, clear_filters = _ref$clear_filters === undefined ? true : _ref$clear_filters; var me = this; if (this.filter_list && clear_filters) { this.filter_list.clear_filters(); } for (var field in frappe.route_options) { var value = frappe.route_options[field]; var doctype = null; if (field.includes(".")) { doctype = field.split(".")[0]; field = field.split(".")[1]; } if (!doctype) { doctype = frappe.meta.get_doctype_for_field(me.doctype, field); } if (doctype && me.filter_list) { if ($.isArray(value)) { me.filter_list.add_filter(doctype, field, value[0], value[1]); } else { me.filter_list.add_filter(doctype, field, "=", value); } } } frappe.route_options = null; }, run: function run(more) { var _this = this; setTimeout(function () { return _this._run(more); }, 100); }, _run: function _run(more) { var me = this; if (!more) { this.start = 0; this.onreset && this.onreset(); } var args = this.get_call_args(); this.save_user_settings_locally(args); $.extend(args, { user_settings: frappe.model.user_settings[this.doctype] }); return frappe.call({ method: this.opts.method || 'frappe.desk.query_builder.runquery', type: "GET", freeze: this.opts.freeze !== undefined ? this.opts.freeze : true, args: args, callback: function callback(r) { me.dirty = false; me.render_results(r); }, no_spinner: this.opts.no_loading }); }, save_user_settings_locally: function save_user_settings_locally(args) { if (this.opts.save_user_settings && this.doctype && !this.docname) { var user_settings = frappe.model.user_settings[this.doctype]; var different = false; if (!user_settings) { return; } if (!frappe.utils.arrays_equal(args.filters, user_settings.filters)) { user_settings.filters = args.filters; different = true; } if (user_settings.order_by !== args.order_by) { user_settings.order_by = args.order_by; different = true; } if (user_settings.limit !== args.limit_page_length) { user_settings.limit = args.limit_page_length || 20; different = true; } if (args.save_user_settings_fields) { user_settings.fields = args.fields; } if (different) { user_settings.updated_on = moment().toString(); } } }, get_call_args: function get_call_args() { if (!this.method) { var query = this.get_query && this.get_query() || this.query; query = this.add_limits(query); var args = { query_max: this.query_max, as_dict: 1 }; args.simple_query = query; } else { var args = { start: this.start, page_length: this.page_length }; } if (this.args) $.extend(args, this.args); if (this.get_args) { $.extend(args, this.get_args()); } return args; }, render_results: function render_results(r) { if (this.start === 0) this.clear(); this.wrapper.find('.btn-more, .list-loading').hide(); var values = []; if (r.message) { values = this.get_values_from_response(r.message); } var show_results = true; if (this.show_no_result) { if ($.isFunction(this.show_no_result)) { show_results = !this.show_no_result(); } else { show_results = !this.show_no_result; } } if (values.length || show_results) { this.data = this.data.concat(values); this.render_view(values); this.update_paging(values); } else if (this.start === 0) { this.wrapper.find('.result').hide(); var msg = ''; var no_result_message = this.no_result_message; if (no_result_message && $.isFunction(no_result_message)) { msg = no_result_message(); } else if (typeof no_result_message === 'string') { msg = no_result_message; } else { msg = __('No Results'); } this.wrapper.find('.no-result').html(msg).show(); } this.wrapper.find('.list-paging-area').toggle(values.length > 0 || this.start > 0); if (this.onrun) this.onrun(); if (this.callback) this.callback(r); this.wrapper.trigger("render-complete"); }, get_values_from_response: function get_values_from_response(data) { if (data.keys && $.isArray(data.keys)) { return frappe.utils.dict(data.keys, data.values); } else { return data; } }, render_view: function render_view(values) {}, update_paging: function update_paging(values) { if (values.length >= this.page_length) { this.wrapper.find('.btn-more').show(); this.start += this.page_length; } }, refresh: function refresh() { this.run(); }, add_limits: function add_limits(query) { return query + ' LIMIT ' + this.start + ',' + (this.page_length + 1); }, set_filter: function set_filter(fieldname, label, no_run, no_duplicate) { var filter = this.filter_list.get_filter(fieldname); if (filter) { var value = cstr(filter.field.get_value()); if (value.includes(label)) { return false; } else if (no_duplicate) { filter.set_values(this.doctype, fieldname, "=", label); } else { if (fieldname == '_user_tags' || fieldname == "_liked_by") { this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label + '%'); } else { filter.set_values(this.doctype, fieldname, 'in', value + ', ' + label); } } } else { if (['_user_tags', '_comments', '_assign', '_liked_by'].includes(fieldname)) { this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label + '%'); } else { this.filter_list.add_filter(this.doctype, fieldname, '=', label); } } if (!no_run) this.run(); }, init_user_settings: function init_user_settings() { this.user_settings = frappe.model.user_settings[this.doctype] || {}; }, call_for_selected_items: function call_for_selected_items(method, args) { var me = this; args.names = this.get_checked_items().map(function (item) { return item.name; }); frappe.call({ method: method, args: args, freeze: true, callback: function callback(r) { if (!r.exc) { if (me.list_header) { me.list_header.find(".list-select-all").prop("checked", false); } me.refresh(); } } }); } }); frappe.has_indicator = function (doctype) { if (frappe.model.is_submittable(doctype)) { return true; } else if ((frappe.listview_settings[doctype] || {}).get_indicator || frappe.workflow.get_state_fieldname(doctype)) { return true; } else if (frappe.meta.has_field(doctype, 'enabled') || frappe.meta.has_field(doctype, 'disabled')) { return true; } return false; }; frappe.get_indicator = function (doc, doctype) { var without_workflow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; if (doc.__unsaved) { return [__("Not Saved"), "orange"]; } if (!doctype) doctype = doc.doctype; var settings = frappe.listview_settings[doctype] || {}; var is_submittable = frappe.model.is_submittable(doctype), workflow_fieldname = frappe.workflow.get_state_fieldname(doctype); if (workflow_fieldname && !without_workflow) { var value = doc[workflow_fieldname]; if (value) { var colour = ""; if (locals["Workflow State"][value] && locals["Workflow State"][value].style) { var colour = { "Success": "green", "Warning": "orange", "Danger": "red", "Primary": "blue" }[locals["Workflow State"][value].style]; } if (!colour) colour = "darkgrey"; return [__(value), colour, workflow_fieldname + ',=,' + value]; } } if (is_submittable && doc.docstatus == 0 && !settings.has_indicator_for_draft) { return [__("Draft"), "red", "docstatus,=,0"]; } if (is_submittable && doc.docstatus == 2) { return [__("Cancelled"), "red", "docstatus,=,2"]; } if (settings.get_indicator) { var indicator = settings.get_indicator(doc); if (indicator) return indicator; } if (is_submittable && doc.docstatus == 1) { return [__("Submitted"), "blue", "docstatus,=,1"]; } if (doc.status) { return [__(doc.status), frappe.utils.guess_colour(doc.status)]; } if (frappe.meta.has_field(doctype, 'enabled')) { if (doc.enabled) { return [__('Enabled'), 'blue', 'enabled,=,1']; } else { return [__('Disabled'), 'grey', 'enabled,=,0']; } } if (frappe.meta.has_field(doctype, 'disabled')) { if (doc.disabled) { return [__('Disabled'), 'grey', 'disabled,=,1']; } else { return [__('Enabled'), 'blue', 'disabled,=,0']; } } }; frappe.ui.FilterList = Class.extend({ init: function init(opts) { $.extend(this, opts); this.filters = []; this.wrapper = this.parent; this.stats = []; this.make(); this.set_events(); }, make: function make() { this.wrapper.find('.show_filters, .filter_area').remove(); this.wrapper.append('\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t' + __("Add Filter") + '\n\t\t\t\t
\n\t\t\t
\n\t\t\t
'); }, set_events: function set_events() { var me = this; this.wrapper.find('.new-filter').bind('click', function () { me.add_filter(); }); this.wrapper.find('.clear-filters').bind('click', function () { me.clear_filters(); $('.date-range-picker').val(''); me.base_list.run(); $(this).addClass("hide"); }); }, show_filters: function show_filters() { this.wrapper.find('.show_filters').toggle(); if (!this.filters.length) { this.add_filter(this.doctype, 'name'); this.filters[0].wrapper.find(".filter_field input").focus(); } }, clear_filters: function clear_filters() { $.each(this.filters, function (i, f) { f.remove(true); }); if (this.base_list.page.fields_dict) { $.each(this.base_list.page.fields_dict, function (key, value) { value.set_input(''); }); } this.filters = []; }, add_filter: function add_filter(doctype, fieldname, condition, value, hidden) { var base_filter = this.base_list.page.fields_dict[fieldname]; if (base_filter && (base_filter.df.condition == condition || condition === '=' && base_filter.df.condition === 'like')) { this.base_list.page.fields_dict[fieldname].set_input(value); return; } if (doctype && fieldname && !frappe.meta.has_field(doctype, fieldname) && !in_list(frappe.model.std_fields_list, fieldname)) { frappe.msgprint({ message: __('Filter {0} missing', [fieldname.bold()]), title: 'Invalid Filter', indicator: 'red' }); return; } this.wrapper.find('.show_filters').toggle(true); var is_new_filter = arguments.length === 0; if (is_new_filter && this.wrapper.find(".is-new-filter:visible").length) { return; } var filter = this.push_new_filter(doctype, fieldname, condition, value); if (!filter) return; if (this.wrapper.find('.clear-filters').hasClass("hide")) { this.wrapper.find('.clear-filters').removeClass("hide"); } if (filter && is_new_filter) { filter.wrapper.addClass("is-new-filter"); } else { filter.freeze(); } if (hidden) { filter.$btn_group.addClass("hide"); } return filter; }, push_new_filter: function push_new_filter(doctype, fieldname, condition, value) { if (this.filter_exists(doctype, fieldname, condition, value)) { return; } if (this.base_list.page.fields_dict[fieldname]) { this.base_list.page.fields_dict[fieldname].set_input(''); } var filter = new frappe.ui.Filter({ flist: this, _doctype: doctype, fieldname: fieldname, condition: condition, value: value }); this.filters.push(filter); return filter; }, filter_exists: function filter_exists(doctype, fieldname, condition, value) { var flag = false; for (var i in this.filters) { if (this.filters[i].field) { var f = this.filters[i].get_value(); if (f[0] == doctype && f[1] == fieldname && f[2] == condition && f[3] == value) { flag = true; } else if ($.isArray(value) && frappe.utils.arrays_equal(value, f[3])) { flag = true; } } } return flag; }, get_filters: function get_filters() { var values = []; $.each(this.filters, function (i, filter) { if (filter.field) { filter.freeze(); values.push(filter.get_value()); } }); this.base_list.update_standard_filters(values); return values; }, update_filters: function update_filters() { var fl = []; $.each(this.filters, function (i, f) { if (f.field) fl.push(f); }); this.filters = fl; if (this.filters.length === 0) { this.wrapper.find('.clear-filters').addClass("hide"); } }, get_filter: function get_filter(fieldname) { for (var i in this.filters) { if (this.filters[i].field && this.filters[i].field.df.fieldname == fieldname) return this.filters[i]; } } }); frappe.ui.Filter = Class.extend({ init: function init(opts) { $.extend(this, opts); this.doctype = this.flist.doctype; this.make(); this.make_select(); this.set_events(); }, make: function make() { this.wrapper = $(frappe.render_template("edit_filter", {})).appendTo(this.flist.wrapper.find('.filter_area')); }, make_select: function make_select() { var me = this; this.fieldselect = new frappe.ui.FieldSelect({ parent: this.wrapper.find('.fieldname_select_area'), doctype: this.doctype, filter_fields: this.filter_fields, select: function select(doctype, fieldname) { me.set_field(doctype, fieldname); } }); if (this.fieldname) { this.fieldselect.set_value(this._doctype || this.doctype, this.fieldname); } }, set_events: function set_events() { var me = this; this.wrapper.find("a.remove-filter").on("click", function () { me.remove(); }); this.wrapper.find(".set-filter-and-run").on("click", function () { me.wrapper.removeClass("is-new-filter"); me.flist.base_list.run(); }); me.wrapper.find('.condition').change(function () { if (!me.field) return; var condition = $(this).val(); if (in_list(["in", "like", "not in", "not like"], condition)) { me.set_field(me.field.df.parent, me.field.df.fieldname, 'Data', condition); if (!me.field.desc_area) { me.field.desc_area = $('
').appendTo(me.field.wrapper); } me.field.desc_area.html((in_list(["in", "not in"], condition) === "in" ? __("values separated by commas") : __("use % as wildcard")) + '
'); } else { me.set_field(me.field.df.parent, me.field.df.fieldname, null, condition); } }); if (me.fieldname) { return this.set_values(me._doctype, me.fieldname, me.condition, me.value); } else { me.set_field(me.doctype, 'name'); } }, remove: function remove(dont_run) { this.wrapper.remove(); this.$btn_group && this.$btn_group.remove(); this.field = null; this.flist.update_filters(); if (!dont_run) { this.flist.base_list.refresh(true); } }, set_values: function set_values(doctype, fieldname, condition, value) { this.set_field(doctype, fieldname); if (this.field.df.original_type === 'Check') { if (value == 0) value = 'No';else if (value == 1) value = 'Yes'; } if (condition) { this.wrapper.find('.condition').val(condition).change(); } if (value != null) { return this.field.set_value(value); } }, set_field: function set_field(doctype, fieldname, fieldtype, condition) { var me = this; var cur = me.field ? { fieldname: me.field.df.fieldname, fieldtype: me.field.df.fieldtype, parent: me.field.df.parent } : {}; var original_docfield = me.fieldselect.fields_by_name[doctype][fieldname]; if (!original_docfield) { frappe.msgprint(__("Field {0} is not selectable.", [fieldname])); return; } var df = copy_dict(me.fieldselect.fields_by_name[doctype][fieldname]); df.read_only = 0; df.hidden = 0; if (!condition) this.set_default_condition(df, fieldtype); this.set_fieldtype(df, fieldtype); if (me.field && cur.fieldname == fieldname && df.fieldtype == cur.fieldtype && df.parent == cur.parent) { return; } me.fieldselect.selected_doctype = doctype; me.fieldselect.selected_fieldname = fieldname; var old_text = null; if (me.field) { old_text = me.field.get_value(); } var field_area = me.wrapper.find('.filter_field').empty().get(0); var f = frappe.ui.form.make_control({ df: df, parent: field_area, only_input: true }); f.refresh(); me.field = f; if (old_text && me.field.df.fieldtype === cur.fieldtype) { me.field.set_value(old_text); } $(me.field.wrapper).find(':input').keydown(function (ev) { if (ev.which == 13) { me.flist.base_list.run(); } }); }, set_fieldtype: function set_fieldtype(df, fieldtype) { if (df.original_type) df.fieldtype = df.original_type;else df.original_type = df.fieldtype; df.description = '';df.reqd = 0; df.ignore_link_validation = true; if (fieldtype) { df.fieldtype = fieldtype; return; } if (df.fieldname == "docstatus") { df.fieldtype = "Select", df.options = [{ value: 0, label: __("Draft") }, { value: 1, label: __("Submitted") }, { value: 2, label: __("Cancelled") }]; } else if (df.fieldtype == 'Check') { df.fieldtype = 'Select'; df.options = 'No\nYes'; } else if (['Text', 'Small Text', 'Text Editor', 'Code', 'Tag', 'Comments', 'Dynamic Link', 'Read Only', 'Assign'].indexOf(df.fieldtype) != -1) { df.fieldtype = 'Data'; } else if (df.fieldtype == 'Link' && ['=', '!='].indexOf(this.wrapper.find('.condition').val()) == -1) { df.fieldtype = 'Data'; } if (df.fieldtype === "Data" && (df.options || "").toLowerCase() === "email") { df.options = null; } if (this.wrapper.find('.condition').val() == "Between" && (df.fieldtype == 'Date' || df.fieldtype == 'Datetime')) { df.fieldtype = 'DateRange'; } }, set_default_condition: function set_default_condition(df, fieldtype) { if (!fieldtype) { if (df.fieldtype == 'Data') { this.wrapper.find('.condition').val('like'); } else if (df.fieldtype == 'Date' || df.fieldtype == 'Datetime') { this.wrapper.find('.condition').val('Between'); } else { this.wrapper.find('.condition').val('='); } } }, get_value: function get_value() { return [this.fieldselect.selected_doctype, this.field.df.fieldname, this.get_condition(), this.get_selected_value()]; }, get_selected_value: function get_selected_value() { var val = this.field.get_value(); if (typeof val === 'string') { val = strip(val); } if (this.field.df.original_type == 'Check') { val = val == 'Yes' ? 1 : 0; } if (this.get_condition().indexOf('like', 'not like') !== -1) { if (val) { if (val.slice(0, 1) !== "%") { val = "%" + val; } if (val.slice(-1) !== "%") { val = val + "%"; } } } else if (in_list(["in", "not in"], this.get_condition())) { if (val) { val = $.map(val.split(","), function (v) { return strip(v); }); } }if (val === '%') { val = ""; } return val; }, get_condition: function get_condition() { return this.wrapper.find('.condition').val(); }, freeze: function freeze() { if (this.$btn_group) { this.set_filter_button_text(); this.wrapper.toggle(false); return; } var me = this; this.$btn_group = $('
\ \
').insertAfter(this.flist.wrapper.find(".set-filters .new-filter")); this.set_filter_button_text(); this.$btn_group.find(".remove-filter").on("click", function () { me.remove(); }); this.$btn_group.find(".toggle-filter").on("click", function () { $(this).closest('.show_filters').find('.filter_area').show(); me.wrapper.toggle(); }); this.wrapper.toggle(false); }, set_filter_button_text: function set_filter_button_text() { var value = this.get_selected_value(); if (this.field.df.fieldname === "docstatus") { value = { 0: "Draft", 1: "Submitted", 2: "Cancelled" }[value] || value; } else if (this.field.df.original_type === "Check") { value = { 0: "No", 1: "Yes" }[cint(value)]; } value = frappe.format(value, this.field.df, { only_value: 1 }); this.$btn_group.find(".toggle-filter").html(repl('%(label)s %(condition)s "%(value)s"', { label: __(this.field.df.label), condition: __(this.get_condition()), value: __(value) })); } }); frappe.ui.FieldSelect = Class.extend({ init: function init(opts) { var me = this; $.extend(this, opts); this.fields_by_name = {}; this.options = []; this.$select = $('').appendTo(this.parent).on("click", function () { $(this).select(); }); this.select_input = this.$select.get(0); this.awesomplete = new Awesomplete(this.select_input, { minChars: 0, maxItems: 99, autoFirst: true, list: me.options, item: function item(_item, input) { return $(repl('
  • %(label)s

  • ', _item)).data("item.autocomplete", _item).get(0); } }); this.$select.on("awesomplete-select", function (e) { var o = e.originalEvent; var value = o.text.value; var item = me.awesomplete.get_item(value); me.selected_doctype = item.doctype; me.selected_fieldname = item.fieldname; if (me.select) me.select(item.doctype, item.fieldname); }); this.$select.on("awesomplete-selectcomplete", function (e) { var o = e.originalEvent; var value = o.text.value; var item = me.awesomplete.get_item(value); me.$select.val(item.label); }); if (this.filter_fields) { for (var i in this.filter_fields) { this.add_field_option(this.filter_fields[i]); } } else { this.build_options(); } this.set_value(this.doctype, "name"); window.last_filter = this; }, get_value: function get_value() { return this.selected_doctype ? this.selected_doctype + "." + this.selected_fieldname : null; }, val: function val(value) { if (value === undefined) { return this.get_value(); } else { this.set_value(value); } }, clear: function clear() { this.selected_doctype = null; this.selected_fieldname = null; this.$select.val(""); }, set_value: function set_value(doctype, fieldname) { var me = this; this.clear(); if (!doctype) return; if (doctype.indexOf(".") !== -1) { var parts = doctype.split("."); doctype = parts[0]; fieldname = parts[1]; } $.each(this.options, function (i, v) { if (v.doctype === doctype && v.fieldname === fieldname) { me.selected_doctype = doctype; me.selected_fieldname = fieldname; me.$select.val(v.label); return false; } }); }, build_options: function build_options() { var me = this; me.table_fields = []; var std_filters = $.map(frappe.model.std_fields, function (d) { var opts = { parent: me.doctype }; if (d.fieldname == "name") opts.options = me.doctype; return $.extend(copy_dict(d), opts); }); var doctype_obj = locals['DocType'][me.doctype]; if (doctype_obj && cint(doctype_obj.istable)) { std_filters = std_filters.concat([{ fieldname: 'parent', fieldtype: 'Data', label: 'Parent', parent: me.doctype }]); } if (this.with_blank) { this.options.push({ label: "", value: "" }); } var main_table_fields = std_filters.concat(frappe.meta.docfield_list[me.doctype]); $.each(frappe.utils.sort(main_table_fields, "label", "string"), function (i, df) { if (frappe.perm.has_perm(me.doctype, df.permlevel, "read") && !df.report_hide) me.add_field_option(df); }); $.each(me.table_fields, function (i, table_df) { if (table_df.options) { var child_table_fields = [].concat(frappe.meta.docfield_list[table_df.options]); $.each(frappe.utils.sort(child_table_fields, "label", "string"), function (i, df) { if (frappe.perm.has_perm(me.doctype, df.permlevel, "read") && !df.report_hide) me.add_field_option(df); }); } }); }, add_field_option: function add_field_option(df) { var me = this; if (me.doctype && df.parent == me.doctype) { var label = __(df.label); var table = me.doctype; if (df.fieldtype == 'Table') me.table_fields.push(df); } else { var label = __(df.label) + ' (' + __(df.parent) + ')'; var table = df.parent; } if (frappe.model.no_value_type.indexOf(df.fieldtype) == -1 && !(me.fields_by_name[df.parent] && me.fields_by_name[df.parent][df.fieldname])) { this.options.push({ label: label, value: table + "." + df.fieldname, fieldname: df.fieldname, doctype: df.parent }); if (!me.fields_by_name[df.parent]) me.fields_by_name[df.parent] = {}; me.fields_by_name[df.parent][df.fieldname] = df; } } });frappe.templates['edit_filter'] = '
    '; frappe.ui.TagEditor = Class.extend({ init: function init(opts) { $.extend(this, opts); var me = this; this.wrapper = $('
    ').appendTo(this.parent); if (!this.wrapper.length) return; var id = frappe.dom.set_unique_id(this.wrapper); this.taggle = new Taggle(id, { placeholder: __('Add a tag') + "...", onTagAdd: function onTagAdd(e, tag) { if (me.initialized && !me.refreshing) { tag = toTitle(tag); return frappe.call({ method: 'frappe.desk.tags.add_tag', args: me.get_args(tag), callback: function callback(r) { var user_tags = me.user_tags.split(","); user_tags.push(tag); me.user_tags = user_tags.join(","); me.on_change && me.on_change(me.user_tags); } }); } }, onTagRemove: function onTagRemove(e, tag) { if (!me.refreshing) { return frappe.call({ method: 'frappe.desk.tags.remove_tag', args: me.get_args(tag), callback: function callback(r) { var user_tags = me.user_tags.split(","); user_tags.splice(user_tags.indexOf(tag), 1); me.user_tags = user_tags.join(","); me.on_change && me.on_change(me.user_tags); } }); } } }); if (!this.user_tags) { this.user_tags = ""; } this.initialized = true; this.refresh(this.user_tags); this.setup_awesomplete(); }, setup_awesomplete: function setup_awesomplete() { var me = this; var $input = this.wrapper.find("input.taggle_input"); var input = $input.get(0); this.awesomplete = new Awesomplete(input, { minChars: 0, maxItems: 99, list: [] }); $input.on("awesomplete-open", function (e) { $input.attr('state', 'open'); }); $input.on("awesomplete-close", function (e) { $input.attr('state', 'closed'); }); $input.on("input", function (e) { var value = e.target.value; frappe.call({ method: "frappe.desk.tags.get_tags", args: { doctype: me.frm.doctype, txt: value.toLowerCase(), cat_tags: JSON.stringify(me.list_sidebar.get_cat_tags()) }, callback: function callback(r) { me.awesomplete.list = r.message; } }); }); $input.on("focus", function (e) { if ($input.attr('state') != 'open') { $input.trigger("input"); } }); }, get_args: function get_args(tag) { return { tag: tag, dt: this.frm.doctype, dn: this.frm.docname }; }, refresh: function refresh(user_tags) { var me = this; if (!me.initialized || me.refreshing) return; me.refreshing = true; try { me.taggle.removeAll(); if (user_tags) { me.taggle.add(user_tags.split(',')); } } catch (e) { me.refreshing = false; setTimeout(function () { me.refresh(); }, 100); } me.refreshing = false; } }); frappe.ui.is_liked = function (doc) { var liked = frappe.ui.get_liked_by(doc); return liked.indexOf(frappe.session.user) === -1 ? false : true; }; frappe.ui.get_liked_by = function (doc) { var liked = doc._liked_by; if (liked) { liked = JSON.parse(liked); } return liked || []; }; frappe.ui.toggle_like = function ($btn, doctype, name, _callback) { var add = $btn.hasClass("not-liked") ? "Yes" : "No"; $btn.css('pointer-events', 'none'); frappe.call({ method: "frappe.desk.like.toggle_like", quiet: true, args: { doctype: doctype, name: name, add: add }, callback: function callback(r) { $btn.css('pointer-events', 'auto'); if (!r.exc) { var action_buttons = $('.like-action[data-name="' + name.replace(/"/g, '\"') + '"][data-doctype="' + doctype.replace(/"/g, '\"') + '"]'); if (add === "Yes") { action_buttons.removeClass("not-liked text-extra-muted"); } else { action_buttons.addClass("not-liked text-extra-muted"); } var doc = locals[doctype] && locals[doctype][name]; if (doc) { var liked_by = JSON.parse(doc._liked_by || "[]"), idx = liked_by.indexOf(frappe.session.user); if (add === "Yes") { if (idx === -1) liked_by.push(frappe.session.user); } else { if (idx !== -1) { liked_by = liked_by.slice(0, idx).concat(liked_by.slice(idx + 1)); } } doc._liked_by = JSON.stringify(liked_by); } if (_callback) { _callback(); } } } }); }; frappe.ui.click_toggle_like = function () { var $btn = $(this); var $count = $btn.siblings(".likes-count"); var not_liked = $btn.hasClass("not-liked"); var doctype = $btn.attr("data-doctype"); var name = $btn.attr("data-name"); frappe.ui.toggle_like($btn, doctype, name, function () { if (not_liked) { $count.text(cint($count.text()) + 1); } else { $count.text(cint($count.text()) - 1); } }); return false; }; frappe.ui.setup_like_popover = function ($parent, selector) { if (frappe.dom.is_touchscreen()) { return; } $parent.on("mouseover", selector, function () { var $wrapper = $(this); $wrapper.popover({ animation: true, placement: "right", content: function content() { var liked_by = JSON.parse($wrapper.attr('data-liked-by') || "[]"); var user = frappe.session.user; if ($wrapper.find(".not-liked").length) { if (liked_by.indexOf(user) !== -1) { liked_by.splice(liked_by.indexOf(user), 1); } } else { if (liked_by.indexOf(user) === -1) { liked_by.push(user); } } if (!liked_by.length) { return ""; } return frappe.render_template("liked_by", { "liked_by": liked_by }); }, html: true, container: 'body' }); $wrapper.popover('show'); }); $parent.on("mouseout", selector, function () { $(this).popover('destroy'); }); };frappe.templates['liked_by'] = ' '; frappe.templates['print_template'] = ' {{ title }} '; frappe.provide('frappe.views.list_view'); frappe.provide('frappe.views.list_renderers'); cur_list = null; frappe.views.ListFactory = frappe.views.Factory.extend({ make: function make(route) { var me = this; var doctype = route[1]; frappe.model.with_doctype(doctype, function () { if (locals['DocType'][doctype].issingle) { frappe.set_re_route('Form', doctype); } else { if (!frappe.views.list_view[doctype]) { frappe.views.list_view[doctype] = new frappe.views.ListView({ doctype: doctype, parent: me.make_page(true, 'List/' + doctype) }); } else { frappe.container.change_to(frappe.views.list_view[doctype].page_name); } me.set_cur_list(); } }); }, show: function show() { if (this.re_route_to_view()) { return; } this.set_module_breadcrumb(); this._super(); this.set_cur_list(); cur_list && cur_list.refresh(); }, re_route_to_view: function re_route_to_view() { var route = frappe.get_route(); var doctype = route[1]; var last_route = frappe.route_history.slice(-2)[0]; if (route[0] === 'List' && route.length === 2 && frappe.views.list_view[doctype]) { if (last_route && last_route[0] === 'List' && last_route[1] === doctype) { window.history.go(-1); } else { frappe.views.list_view[doctype].load_last_view(); } return true; } }, set_module_breadcrumb: function set_module_breadcrumb() { if (frappe.route_history.length > 1) { var prev_route = frappe.route_history[frappe.route_history.length - 2]; if (prev_route[0] === 'modules') { var doctype = frappe.get_route()[1], module = prev_route[1]; if (frappe.module_links[module] && frappe.module_links[module].includes(doctype)) { frappe.breadcrumbs.set_doctype_module(doctype, module); } } } }, set_cur_list: function set_cur_list() { var route = frappe.get_route(); cur_list = frappe.container.page && frappe.container.page.list_view; if (cur_list && cur_list.doctype !== route[1]) { cur_list = null; } } }); $(document).on('save', function (event, doc) { frappe.views.set_list_as_dirty(doc.doctype); }); frappe.views.set_list_as_dirty = function (doctype) { if (frappe.views.trees[doctype]) { frappe.views.trees[doctype].tree.refresh(); } var route = frappe.get_route(); var current_view = route[2] || 'List'; var list_renderer = frappe.views.list_renderers[doctype]; if (list_renderer && list_renderer[current_view] && list_renderer[current_view].no_realtime) { return; } var list_page = 'List/' + doctype; if (frappe.pages[list_page]) { if (frappe.pages[list_page].list_view) { if (frappe.pages[list_page].list_view.dirty) { return; } frappe.pages[list_page].list_view.dirty = true; } } if (route[0] === 'List' && route[1] === doctype) { setTimeout(function () { frappe.pages[list_page].list_view.refresh(); }, 100); } }; frappe.views.view_modes = ['List', 'Gantt', 'Kanban', 'Calendar', 'Image', 'Inbox']; frappe.views.ListView = frappe.ui.BaseList.extend({ init: function init(opts) { $.extend(this, opts); if (!frappe.boot.user.all_read.includes(this.doctype)) { frappe.show_not_permitted(frappe.get_route_str()); return; } this.page_name = 'List/' + this.doctype; this.dirty = true; this.tags_shown = false; this.page_title = __(this.doctype); this.page_title = this.page_title.toLowerCase().substr(-4) == 'list' && __(this.page_title) || __(this.page_title) + ' ' + __('List'); this.make_page(); this.setup(); this.refresh(); }, make_page: function make_page() { this.parent.list_view = this; this.page = this.parent.page; this.$page = $(this.parent).css({ 'min-height': '400px' }); $('
    ').appendTo(this.page.main); this.page.main.addClass('listview-main-section'); var module = locals.DocType[this.doctype].module; frappe.breadcrumbs.add(module, this.doctype); }, setup: function setup() { this.can_delete = frappe.model.can_delete(this.doctype); this.meta = frappe.get_meta(this.doctype); this.wrapper = this.$page.find('.frappe-list-area').empty(); this.allow_delete = true; this.load_last_view(); this.setup_view_variables(); this.setup_list_renderer(); this.init_base_list(false); this.list_renderer.set_wrapper(); this.list_renderer_onload(); this.show_match_help(); this.init_menu(); this.init_sort_selector(); this.init_filters(); this.set_title(); this.init_headers(); }, refresh_surroundings: function refresh_surroundings() { this.init_sort_selector(); this.init_filters(); this.set_title(); this.init_headers(); this.no_result_message = this.list_renderer.make_no_result(); }, setup_list_renderer: function setup_list_renderer() { frappe.provide('frappe.views.list_renderers.' + this.doctype); var list_renderer = frappe.views.list_renderers[this.doctype][this.current_view]; if (list_renderer) { this.list_renderer = list_renderer; this.list_renderer.init_settings(); return; } var opts = { doctype: this.doctype, list_view: this }; if (this.current_view === 'List') { this.list_renderer = new frappe.views.ListRenderer(opts); } else if (this.current_view === 'Gantt') { this.list_renderer = new frappe.views.GanttView(opts); } else if (this.current_view === 'Calendar') { this.list_renderer = new frappe.views.CalendarView(opts); } else if (this.current_view === 'Image') { this.list_renderer = new frappe.views.ImageView(opts); } else if (this.current_view === 'Kanban') { this.list_renderer = new frappe.views.KanbanView(opts); } else if (this.current_view === 'Inbox') { this.list_renderer = new frappe.views.InboxView(opts); } }, render_view: function render_view(values) { this.list_renderer.render_view(values); }, set_title: function set_title() { if (this.list_renderer.page_title) { this.page.set_title(this.list_renderer.page_title); } else { this.page.set_title(this.page_title); } }, load_last_view: function load_last_view() { var us = frappe.get_user_settings(this.doctype); var route = ['List', this.doctype]; if (us.last_view && frappe.views.view_modes.includes(us.last_view)) { route.push(us.last_view); if (us.last_view === 'Kanban') { route.push(us['Kanban'].last_kanban_board); } if (us.last_view === 'Inbox') { route.push(us['Inbox'].last_email_account); } } else { route.push('List'); } frappe.set_route(route); }, init_headers: function init_headers() { this.page.main.find('.list-headers > .list-item--head').hide(); this.list_header = this.page.main.find('.list-headers > ' + '.list-item--head[data-list-renderer="' + this.list_renderer.name + '"]'); if (this.list_header.length > 0) { this.list_header.show(); return; } var html = this.list_renderer.get_header_html(); if (!html) { this.list_header = $(); return; } this.list_header = $(html).appendTo(this.page.main.find('.list-headers')); this.setup_like(); this.setup_select_all(); this.setup_delete(); }, list_renderer_onload: function list_renderer_onload() { if (this.list_renderer.settings.onload) { this.list_renderer.settings.onload(this); } }, set_sidebar_height: function set_sidebar_height() { var h_main = this.page.sidebar.height(); var h_side = this.$page.find('.layout-side-section').height(); if (h_side > h_main) this.$page.find('.layout-main-section').css({ 'min-height': h_side }); }, init_filters: function init_filters() { this.make_standard_filters(); this.filter_list = new frappe.ui.FilterList({ base_list: this, parent: this.wrapper.find('.list-filters').show(), doctype: this.doctype, default_filters: [] }); this.set_filters(this.list_renderer.filters); }, set_filters: function set_filters(filters) { var me = this; $.each(filters, function (i, f) { var hidden = false; if (f.length === 3) { f = [me.doctype, f[0], f[1], f[2]]; } else if (f.length === 5) { hidden = f.pop(4) || false; } me.filter_list.add_filter(f[0], f[1], f[2], f[3], hidden); }); }, init_sort_selector: function init_sort_selector() { var me = this; var order_by = this.list_renderer.order_by; this.sort_selector = new frappe.ui.SortSelector({ parent: this.wrapper.find('.list-filters'), doctype: this.doctype, args: order_by, change: function change() { me.run(); } }); }, show_match_help: function show_match_help() { var me = this; var match_rules_list = frappe.perm.get_match_rules(this.doctype); var perm = frappe.perm.get_perm(this.doctype); if (match_rules_list.length) { this.footnote_area = frappe.utils.set_footnote(this.footnote_area, this.$page.find('.layout-main-section'), frappe.render_template('list_permission_footer', { condition_list: match_rules_list })); $(this.footnote_area).css({ 'margin-top': '0px' }); } }, setup_view_variables: function setup_view_variables() { var route = frappe.get_route(); this.last_view = this.current_view || ''; this.current_view = route[2] || 'List'; }, init_base_list: function init_base_list(auto_run) { var me = this; this.make({ method: 'frappe.desk.reportview.get', save_user_settings: true, get_args: this.get_args, parent: this.wrapper, freeze: true, start: 0, page_length: this.list_renderer.page_length, show_filters: false, new_doctype: this.doctype, no_result_message: this.list_renderer.make_no_result(), show_no_result: function show_no_result() { return me.list_renderer.show_no_result; } }); this.setup_make_new_doc(); if (auto_run !== false && auto_run !== 0) this.refresh(); }, setup_make_new_doc: function setup_make_new_doc() { var me = this; if (this.list_renderer.settings.list_view_doc) { this.list_renderer.settings.list_view_doc(this); } else { var doctype = this.list_renderer.no_result_doctype ? this.list_renderer.no_result_doctype : this.doctype; $(this.wrapper).on('click', 'button[list_view_doc=\'' + doctype + '\']', function () { if (me.list_renderer.make_new_doc) me.list_renderer.make_new_doc();else me.make_new_doc.apply(me, [me.doctype]); }); } }, refresh: function refresh(dirty) { var me = this; if (dirty !== undefined) this.dirty = dirty; this.refresh_sidebar(); this.setup_view_variables(); if (this.list_renderer.should_refresh()) { this.setup_list_renderer(); this.refresh_surroundings(); this.dirty = true; } if (this.list_renderer.settings.refresh) { this.list_renderer.settings.refresh(this); } this.set_filters_before_run(); this.execute_run(); }, execute_run: function execute_run() { if (this.dirty) { this.run(); } else { if (new Date() - (this.last_updated_on || 0) > 30000) { this.run(); } } }, save_user_settings_locally: function save_user_settings_locally(args) { frappe.provide('frappe.model.user_settings.' + this.doctype + '.' + this.list_renderer.name); var user_settings_common = frappe.model.user_settings[this.doctype]; var user_settings = frappe.model.user_settings[this.doctype][this.list_renderer.name]; if (!user_settings) return; var different = false; if (!frappe.utils.arrays_equal(args.filters, user_settings.filters)) { user_settings.filters = args.filters; different = true; } if (user_settings.order_by !== args.order_by) { user_settings.order_by = args.order_by; different = true; } if (args.save_user_settings_fields) { user_settings.fields = args.fields; } if (user_settings_common.last_view !== this.current_view && frappe.views.view_modes.includes(this.current_view)) { user_settings_common.last_view = this.current_view; different = true; } if (different) { user_settings_common.updated_on = moment().toString(); } }, set_filters_before_run: function set_filters_before_run() { var me = this; if (frappe.route_options) { this.set_filters_from_route_options(); this.dirty = true; } }, run: function run(more) { var me = this; if (this.fresh && !more) { return; } if (this.list_renderer.settings.before_run) { this.list_renderer.settings.before_run(this); } if (!this.list_renderer.settings.use_route) { var route = frappe.get_route(); if (route[2] && !frappe.views.view_modes.includes(route[2])) { $.each(frappe.utils.get_args_dict_from_url(route[2]), function (key, val) { me.set_filter(key, val, true); }); } } if (this.list_header) { this.list_header.find('.list-liked-by-me').toggleClass('text-extra-muted not-liked', !this.is_star_filtered()); } this.last_updated_on = new Date(); this.dirty = false; this.fresh = true; setTimeout(function () { me.fresh = false; }, 1000); this._super(more); if (this.list_renderer.settings.post_render) { this.list_renderer.settings.post_render(this); } this.wrapper.on('render-complete', function () { me.list_renderer.after_refresh(); }); }, get_args: function get_args() { var args = { doctype: this.doctype, fields: this.list_renderer.fields, filters: this.get_filters_args(), order_by: this.get_order_by_args(), with_comment_count: true }; return args; }, get_filters_args: function get_filters_args() { var filters = []; if (this.filter_list) { filters = this.filter_list.get_filters(); } else { filters = this.list_renderer.filters; } var uniq = filters.uniqBy(JSON.stringify); return uniq; }, get_order_by_args: function get_order_by_args() { var order_by = ''; if (this.sort_selector) { order_by = $.format('`tab{0}`.`{1}` {2}', [this.doctype, this.sort_selector.sort_by, this.sort_selector.sort_order]); } else { order_by = this.list_renderer.order_by; } return order_by; }, assigned_to_me: function assigned_to_me() { this.filter_list.add_filter(this.doctype, '_assign', 'like', '%' + frappe.session.user + '%'); this.run(); }, liked_by_me: function liked_by_me() { this.filter_list.add_filter(this.doctype, '_liked_by', 'like', '%' + frappe.session.user + '%'); this.run(); }, remove_liked_by_me: function remove_liked_by_me() { this.filter_list.get_filter('_liked_by').remove(); }, is_star_filtered: function is_star_filtered() { return this.filter_list.filter_exists(this.doctype, '_liked_by', 'like', '%' + frappe.session.user + '%'); }, init_menu: function init_menu() { var me = this; this.$page.on('click', '.list-tag-preview', function () { me.toggle_tags(); }); this.page.set_secondary_action(__('Refresh'), function () { me.refresh(true); }, 'octicon octicon-sync').addClass('hidden-xs'); this.page.add_menu_item(__('Refresh'), function () { me.refresh(true); }, 'octicon octicon-sync').addClass('visible-xs'); if (frappe.model.can_import(this.doctype)) { this.page.add_menu_item(__('Import'), function () { frappe.set_route('data-import-tool', { doctype: me.doctype }); }, true); } if (frappe.model.can_set_user_permissions(this.doctype)) { this.page.add_menu_item(__('User Permissions'), function () { frappe.set_route('List', 'User Permission', { allow: me.doctype }); }, true); } if (frappe.user_roles.includes('System Manager')) { this.page.add_menu_item(__('Role Permissions Manager'), function () { frappe.set_route('permission-manager', { doctype: me.doctype }); }, true); this.page.add_menu_item(__('Customize'), function () { frappe.set_route('Form', 'Customize Form', { doc_type: me.doctype }); }, true); } this.make_bulk_assignment(); this.make_bulk_printing(); this.page.add_menu_item(__('Add to Desktop'), function () { frappe.add_to_desktop(me.doctype, me.doctype); }, true); if (frappe.user_roles.includes('System Manager') && frappe.boot.developer_mode === 1) { this.page.add_menu_item(__('Edit DocType'), function () { frappe.set_route('Form', 'DocType', me.doctype); }, true); } }, make_bulk_assignment: function make_bulk_assignment() { var me = this; me.page.add_menu_item(__('Assign To'), function () { var docnames = me.get_checked_items().map(function (doc) { return doc.name; }); if (docnames.length >= 1) { me.dialog = new frappe.ui.form.AssignToDialog({ obj: me, method: 'frappe.desk.form.assign_to.add_multiple', doctype: me.doctype, docname: docnames, bulk_assign: true, re_assign: true, callback: function callback() { me.refresh(true); } }); me.dialog.clear(); me.dialog.show(); } else { frappe.msgprint(__('Select records for assignment')); } }, true); }, make_bulk_printing: function make_bulk_printing() { var me = this; var print_settings = frappe.model.get_doc(':Print Settings', 'Print Settings'); var allow_print_for_draft = cint(print_settings.allow_print_for_draft); var is_submittable = frappe.model.is_submittable(me.doctype); var allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled); me.page.add_menu_item(__('Print'), function () { var items = me.get_checked_items(); var valid_docs = items.filter(function (doc) { return !is_submittable || doc.docstatus === 1 || allow_print_for_cancelled && doc.docstatus == 2 || allow_print_for_draft && doc.docstatus == 0 || frappe.user_roles.includes('Administrator'); }).map(function (doc) { return doc.name; }); var invalid_docs = items.filter(function (doc) { return !valid_docs.includes(doc.name); }); if (invalid_docs.length >= 1) { frappe.msgprint(__('You selected Draft or Cancelled documents')); return; } if (valid_docs.length >= 1) { var dialog = new frappe.ui.Dialog({ title: 'Print Documents', fields: [{ 'fieldtype': 'Check', 'label': __('With Letterhead'), 'fieldname': 'with_letterhead' }, { 'fieldtype': 'Select', 'label': __('Print Format'), 'fieldname': 'print_sel' }] }); dialog.set_primary_action(__('Print'), function () { var args = dialog.get_values(); if (!args) return; var default_print_format = locals.DocType[me.doctype].default_print_format; var with_letterhead = args.with_letterhead ? 1 : 0; var print_format = args.print_sel ? args.print_sel : default_print_format; var json_string = JSON.stringify(valid_docs); var w = window.open('/api/method/frappe.utils.print_format.download_multi_pdf?' + 'doctype=' + encodeURIComponent(me.doctype) + '&name=' + encodeURIComponent(json_string) + '&format=' + encodeURIComponent(print_format) + '&no_letterhead=' + (with_letterhead ? '0' : '1')); if (!w) { frappe.msgprint(__('Please enable pop-ups'));return; } }); var print_formats = frappe.meta.get_print_formats(me.doctype); dialog.fields_dict.print_sel.$input.empty().add_options(print_formats); dialog.show(); } else { frappe.msgprint(__('Select atleast 1 record for printing')); } }, true); }, setup_like: function setup_like() { var me = this; this.$page.find('.result-list').on('click', '.like-action', frappe.ui.click_toggle_like); this.list_header.find('.list-liked-by-me').on('click', function () { if (me.is_star_filtered()) { me.remove_liked_by_me(); } else { me.liked_by_me(); } }); if (!frappe.dom.is_touchscreen()) { frappe.ui.setup_like_popover(this.$page.find('.result-list'), '.liked-by'); } }, setup_select_all: function setup_select_all() { var me = this; if (this.can_delete || this.list_renderer.settings.selectable) { this.list_header.find('.list-select-all').on('click', function () { me.$page.find('.list-row-checkbox').prop('checked', $(this).prop('checked')); }); this.$page.on('click', '.list-row-checkbox', function (event) { var $this = $(this); if (event.shiftKey && $this.prop('checked')) { var $end_row = $this.parents('.list-item-container'); var $start_row = $end_row.prevAll('.list-item-container').find('.list-row-checkbox:checked').last().parents('.list-item-container'); if ($start_row) { $start_row.nextUntil($end_row).find('.list-row-checkbox').prop('checked', true); } } }); } }, setup_delete: function setup_delete() { var me = this; if (!(this.can_delete || this.list_renderer.settings.selectable)) { return; } this.$page.on('change', '.list-row-checkbox, .list-select-all', function () { me.toggle_delete(); }); this.wrapper.on('render-complete', function () { me.toggle_delete(); }); }, toggle_delete: function toggle_delete() { var me = this; var checked_items = this.get_checked_items(); var checked_items_status = this.$page.find('.checked-items-status'); if (checked_items.length > 0) { this.page.set_primary_action(__('Delete'), function () { me.delete_items(); }, 'octicon octicon-trashcan').addClass('btn-danger'); checked_items_status.text(checked_items.length == 1 ? __('1 item selected') : __('{0} items selected', [checked_items.length])); checked_items_status.removeClass('hide'); } else { this.page.btn_primary.removeClass('btn-danger'); this.set_primary_action(); checked_items_status.addClass('hide'); } }, toggle_tags: function toggle_tags() { if (this.tags_shown) { $('.tag-row').addClass('hide'); this.tags_shown = false; } else { $('.tag-row').removeClass('hide'); this.tags_shown = true; } }, get_checked_items: function get_checked_items() { var names = this.$page.find('.list-row-checkbox:checked').map(function (i, item) { return cstr($(item).data().name); }).toArray(); return this.data.filter(function (doc) { return names.includes(doc.name); }); }, set_primary_action: function set_primary_action() { if (this.list_renderer.settings.set_primary_action) { this.list_renderer.settings.set_primary_action(this); } else { this._super(); } }, delete_items: function delete_items() { var me = this; var to_delete = this.get_checked_items(); if (!to_delete.length) return; var docnames = to_delete.map(function (doc) { return doc.name; }); frappe.confirm(__('Delete {0} items permanently?', [to_delete.length]), function () { return frappe.call({ method: 'frappe.desk.reportview.delete_items', freeze: true, args: { items: docnames, doctype: me.doctype }, callback: function callback() { me.$page.find('.list-select-all').prop('checked', false); frappe.utils.play_sound('delete'); me.refresh(true); } }); }); }, refresh_sidebar: function refresh_sidebar() { this.list_sidebar = new frappe.views.ListSidebar({ doctype: this.doctype, stats: this.list_renderer.stats, parent: this.$page.find('.layout-side-section'), set_filter: this.set_filter.bind(this), default_filters: this.list_renderer.filters, page: this.page, list_view: this }); } }); frappe.provide('frappe.views'); frappe.views.ListSidebar = Class.extend({ init: function init(opts) { $.extend(this, opts); this.make(); this.get_stats(); this.cat_tags = []; }, make: function make() { var sidebar_content = frappe.render_template("list_sidebar", { doctype: this.list_view.doctype }); this.sidebar = $('').html(sidebar_content).appendTo(this.page.sidebar.empty()); this.setup_reports(); this.setup_assigned_to_me(); this.setup_views(); this.setup_kanban_boards(); this.setup_email_inbox(); }, setup_views: function setup_views() { var show_list_link = false; if (frappe.views.calendar[this.doctype]) { this.sidebar.find('.list-link[data-view="Calendar"]').removeClass("hide"); this.sidebar.find('.list-link[data-view="Gantt"]').removeClass('hide'); show_list_link = true; } this.sidebar.find('.list-link[data-view="Kanban"]').removeClass('hide'); if (this.doctype === "Communication" && frappe.boot.email_accounts.length) { this.sidebar.find('.list-link[data-view="Inbox"]').removeClass('hide'); show_list_link = true; } if (frappe.treeview_settings[this.doctype]) { this.sidebar.find(".tree-link").removeClass("hide"); } this.current_view = 'List'; var route = frappe.get_route(); if (route.length > 2 && frappe.views.view_modes.includes(route[2])) { this.current_view = route[2]; if (this.current_view === 'Kanban') { this.kanban_board = route[3]; } else if (this.current_view === 'Inbox') { this.email_account = route[3]; } } this.sidebar.find('.list-link[data-view="' + this.current_view + '"] a').attr('disabled', 'disabled').addClass('disabled'); this.sidebar.find('.list-link[data-view="Kanban"] a, .list-link[data-view="Inbox"] a').attr('disabled', null).removeClass('disabled'); if (this.list_view.meta.image_field) { this.sidebar.find('.list-link[data-view="Image"]').removeClass('hide'); show_list_link = true; } if (show_list_link) { this.sidebar.find('.list-link[data-view="List"]').removeClass('hide'); } }, setup_reports: function setup_reports() { var me = this; var added = []; var dropdown = this.page.sidebar.find('.reports-dropdown'); var divider = false; var add_reports = function add_reports(reports) { $.each(reports, function (name, r) { if (!r.ref_doctype || r.ref_doctype == me.doctype) { var report_type = r.report_type === 'Report Builder' ? 'Report/' + r.ref_doctype : 'query-report'; var route = r.route || report_type + '/' + (r.title || r.name); if (added.indexOf(route) === -1) { added.push(route); if (!divider) { $('').appendTo(dropdown); divider = true; } $('
  • ' + __(r.title || r.name) + '
  • ').appendTo(dropdown); } } }); }; if (this.list_view.list_renderer.settings.reports) { add_reports(this.list_view.list_renderer.settings.reports); } add_reports(frappe.boot.user.all_reports || []); }, setup_kanban_boards: function setup_kanban_boards() { var me = this; var $dropdown = this.page.sidebar.find('.kanban-dropdown'); var divider = false; var meta = frappe.get_meta(this.doctype); var boards = meta && meta.__kanban_boards; if (!boards) return; boards.forEach(function (board) { var route = ["List", board.reference_doctype, "Kanban", board.name].join('/'); if (!divider) { $('').appendTo($dropdown); divider = true; } $('
  • \n\t\t\t\t' + __(board.name) + '\n\t\t\t\t' + (board.private ? '' : '') + '\n\t\t\t
  • ').appendTo($dropdown); }); $dropdown.find('.new-kanban-board').click(function () { var select_fields = frappe.get_meta(me.doctype).fields.filter(function (df) { return df.fieldtype === 'Select' && df.fieldname !== 'kanban_column'; }); var fields = [{ fieldtype: 'Data', fieldname: 'board_name', label: __('Kanban Board Name'), reqd: 1 }]; if (select_fields.length > 0) { fields = fields.concat([{ fieldtype: 'Select', fieldname: 'field_name', label: __('Columns based on'), options: select_fields.map(function (df) { return df.label; }).join('\n'), default: select_fields[0] }, { fieldtype: 'Check', fieldname: 'custom_column', label: __('Custom Column'), default: 0, onchange: function onchange(e) { var checked = d.get_value('custom_column'); if (checked) { $(d.body).find('.frappe-control[data-fieldname="field_name"]').hide(); } else { $(d.body).find('.frappe-control[data-fieldname="field_name"]').show(); } } }]); } if (me.doctype === 'Task') { fields[0].description = __('A new Project with this name will be created'); } if (['Note', 'ToDo'].includes(me.doctype)) { fields[0].description = __('This Kanban Board will be private'); } var d = new frappe.ui.Dialog({ title: __('New Kanban Board'), fields: fields, primary_action_label: __('Save'), primary_action: function primary_action(values) { var custom_column = values.custom_column !== undefined ? values.custom_column : 1; if (custom_column) { var field_name = 'kanban_column'; } else { var field_name = select_fields.find(function (df) { return df.label === values.field_name; }).fieldname; } me.add_custom_column_field(custom_column).then(function (custom_column) { return me.make_kanban_board(values.board_name, field_name); }).then(function () { d.hide(); }, function (err) { frappe.msgprint(err); }); } }); d.show(); }); }, add_custom_column_field: function add_custom_column_field(flag) { var me = this; return new Promise(function (resolve, reject) { if (!flag) resolve(false); frappe.call({ method: 'frappe.custom.doctype.custom_field.custom_field.add_custom_field', args: { doctype: me.doctype, df: { label: 'Kanban Column', fieldname: 'kanban_column', fieldtype: 'Select', hidden: 1 } } }).success(function () { resolve(true); }).error(function (err) { reject(err); }); }); }, make_kanban_board: function make_kanban_board(board_name, field_name) { var me = this; return frappe.call({ method: 'frappe.desk.doctype.kanban_board.kanban_board.quick_kanban_board', args: { doctype: me.doctype, board_name: board_name, field_name: field_name }, callback: function callback(r) { var kb = r.message; if (kb.filters) { frappe.provide('frappe.kanban_filters'); frappe.kanban_filters[kb.kanban_board_name] = kb.filters; } frappe.set_route('List', me.doctype, 'Kanban', kb.kanban_board_name); } }); }, setup_email_inbox: function setup_email_inbox() { if (this.doctype != "Communication") return; var $dropdown = this.page.sidebar.find('.email-account-dropdown'); var divider = false; if (has_common(frappe.user_roles, ["System Manager", "Administrator"])) { $('
  • ' + __("New Email Account") + '
  • ').appendTo($dropdown); } var accounts = frappe.boot.email_accounts; accounts.forEach(function (account) { var email_account = account.email_id == "All Accounts" ? "All Accounts" : account.email_account; var route = ["List", "Communication", "Inbox", email_account].join('/'); if (!divider) { $('').appendTo($dropdown); divider = true; } $('
  • ' + account.email_id + '
  • ').appendTo($dropdown); if (account.email_id === "Sent Mail") divider = false; }); $dropdown.find('.new-email-account').click(function () { frappe.new_doc("Email Account"); }); }, setup_assigned_to_me: function setup_assigned_to_me() { var me = this; this.page.sidebar.find(".assigned-to-me a").on("click", function () { me.list_view.assigned_to_me(); }); }, get_cat_tags: function get_cat_tags() { return this.cat_tags; }, get_stats: function get_stats() { var me = this; frappe.call({ method: 'frappe.desk.reportview.get_sidebar_stats', args: { stats: me.stats, doctype: me.doctype, filters: me.default_filters }, callback: function callback(r) { me.defined_category = r.message; if (r.message.defined_cat) { me.defined_category = r.message.defined_cat; me.cats = {}; for (var i in me.defined_category) { if (me.cats[me.defined_category[i].category] === undefined) { me.cats[me.defined_category[i].category] = [me.defined_category[i].tag]; } else { me.cats[me.defined_category[i].category].push(me.defined_category[i].tag); } me.cat_tags[i] = me.defined_category[i].tag; } me.tempstats = r.message.stats; var len = me.cats.length; $.each(me.cats, function (i, v) { me.render_stat(i, (me.tempstats || {})["_user_tags"], v); }); me.render_stat("_user_tags", (me.tempstats || {})["_user_tags"]); } else { me.render_stat("_user_tags", (r.message.stats || {})["_user_tags"]); } me.list_view.set_sidebar_height(); } }); }, render_stat: function render_stat(field, stat, tags) { var me = this; var sum = 0; var stats = []; var label = frappe.meta.docfield_map[this.doctype][field] ? frappe.meta.docfield_map[this.doctype][field].label : field; var show_tags = ''; stat = (stat || []).sort(function (a, b) { return b[1] - a[1]; }); $.each(stat, function (i, v) { sum = sum + v[1]; }); if (tags) { for (var t in tags) { var nfound = -1; for (var i in stat) { if (tags[t] === stat[i][0]) { stats.push(stat[i]); nfound = i; break; } } if (nfound < 0) { stats.push([tags[t], 0]); } else { me.tempstats["_user_tags"].splice(nfound, 1); } } field = "_user_tags"; } else { stats = stat; } var context = { field: field, stat: stats, sum: sum, label: field === '_user_tags' ? tags ? __(label) + show_tags : __("UnCategorised Tags") + show_tags : __(label) }; var sidebar_stat = $(frappe.render_template("list_sidebar_stat", context)).on("click", ".stat-link", function () { var fieldname = $(this).attr('data-field'); var label = $(this).attr('data-label'); if (label == "No Tags") { me.list_view.filter_list.add_filter(me.list_view.doctype, fieldname, 'not like', '%,%'); me.list_view.run(); } else { me.set_filter(fieldname, label); } }).insertBefore(this.sidebar.find(".close-sidebar-button")); }, set_fieldtype: function set_fieldtype(df, fieldtype) { if (df.fieldname == "docstatus") { df.fieldtype = "Select", df.options = [{ value: 0, label: "Draft" }, { value: 1, label: "Submitted" }, { value: 2, label: "Cancelled" }]; } else if (df.fieldtype == 'Check') { df.fieldtype = 'Select'; df.options = [{ value: 0, label: 'No' }, { value: 1, label: 'Yes' }]; } else if (['Text', 'Small Text', 'Text Editor', 'Code', 'Tag', 'Comments', 'Dynamic Link', 'Read Only', 'Assign'].indexOf(df.fieldtype) != -1) { df.fieldtype = 'Data'; } else if (df.fieldtype == 'Link' && this.$w.find('.condition').val() != "=") { df.fieldtype = 'Data'; } if (df.fieldtype === "Data" && (df.options || "").toLowerCase() === "email") { df.options = null; } }, reload_stats: function reload_stats() { this.sidebar.find(".sidebar-stat").remove(); this.get_stats(); } });frappe.templates['list_sidebar'] = ' '; frappe.templates['list_sidebar_stat'] = ' '; frappe.templates['list_item_main'] = '
    {% if (col.type==="Subject") { %} {%= subject %} {% } else if (col.type==="Indicator") { %} {%= indicator %} {% } else if (col.render) { %} {%= col.render(data) %} {% } else if (col.fieldtype==="Image") { %} {% if(data[col.df.options]) { %} {% } else { %}
    {% } %} {% } else if(col.fieldtype==="Select") { %} {%= __(value) %} {% } else if(col.fieldtype==="Link") { %} {%= value %} {% } else { %} {% if(formatters && formatters[col.fieldname]) { %} {{ formatters[col.fieldname](value, col.df, data) }} {% } else { %} {{ frappe.format(value, col.df, null, data) }} {% } %} {% } %}
    '; frappe.templates['list_item_row'] = '
    {%= main %} {% if (meta.title_field && !settings.hide_name_column) { var is_different = data.name !== data[meta.title_field]; %} {% } %} {% if (!data._hide_activity) { %}
    {%= indicator_dot %}
    {% } %}
    '; frappe.templates['list_item_main_head'] = '
    {% if (col.type==="Subject") { %} {%= frappe.render_template("header_select_all_like_filter", { _checkbox: _checkbox }) %} {% } %} {{ __(col.title) || __(col.label) || "" }}
    '; frappe.templates['list_item_row_head'] = '
    {%= main %} {% if(list.meta.title_field && !list.settings.hide_name_column) { %} {% } %}
    '; frappe.templates['list_item_subject'] = '{% if (_checkbox) { %} {% } %} {% if (!_hide_activity) { %} {% } %} {{ strip_html(_title) }} {% if (_workflow && !_without_workflow) { %} {%= _workflow.value %} {% } %} '; frappe.templates['list_permission_footer'] = '
    {% for(var i=0; i < condition_list.length; i++) { var conditions = condition_list[i]; %}
    {% if (i > 0) { %}{{ __("Or") }}{% } %} {% for(key in conditions) { %} {% if(conditions[key].length) { %} {{ key }} = {{ frappe.utils.comma_or(conditions[key]) }} {% } else { %} {{ __("{0} is not set", [key]) }} {% } %} {% } %}
    {% } %}
    '; frappe.provide('frappe.views'); frappe.views.ListRenderer = Class.extend({ name: 'List', init: function init(opts) { $.extend(this, opts); this.meta = frappe.get_meta(this.doctype); this.init_settings(); this.set_defaults(); this.set_fields(); this.set_columns(); this.setup_cache(); }, set_defaults: function set_defaults() { var me = this; this.page_title = __(this.doctype); this.set_wrapper(); this.setup_filterable(); this.prepare_render_view(); this.no_realtime = false; this.show_no_result = true; this.hide_sort_selector = false; this.order_by = this.order_by || 'modified desc'; this.filters = this.filters || []; this.page_length = this.page_length || 20; }, setup_cache: function setup_cache() { frappe.provide('frappe.views.list_renderers.' + this.doctype); frappe.views.list_renderers[this.doctype][this.list_view.current_view] = this; }, init_settings: function init_settings() { this.settings = frappe.listview_settings[this.doctype] || {}; this.init_user_settings(); this.order_by = this.user_settings.order_by || this.settings.order_by; this.filters = this.user_settings.filters || this.settings.filters; this.page_length = this.settings.page_length; if (frappe.model.is_submittable(this.doctype) && (!this.filters || !this.filters.length)) { this.filters = [[this.doctype, "docstatus", "!=", 2]]; } }, init_user_settings: function init_user_settings() { frappe.provide('frappe.model.user_settings.' + this.doctype + '.' + this.name); this.user_settings = frappe.get_user_settings(this.doctype)[this.name]; }, after_refresh: function after_refresh() {}, before_refresh: function before_refresh() {}, should_refresh: function should_refresh() { return this.list_view.current_view !== this.list_view.last_view; }, set_wrapper: function set_wrapper() { this.wrapper = this.list_view.wrapper && this.list_view.wrapper.find('.result-list'); }, set_fields: function set_fields() { var me = this; var tabDoctype = '`tab' + this.doctype + '`.'; this.fields = []; this.stats = ['_user_tags']; var add_field = function add_field(fieldname) { if (!fieldname.includes('`tab')) { fieldname = tabDoctype + '`' + fieldname + '`'; } if (!me.fields.includes(fieldname)) me.fields.push(fieldname); }; var defaults = ['name', 'owner', 'docstatus', '_user_tags', '_comments', 'modified', 'modified_by', '_assign', '_liked_by', '_seen']; defaults.map(add_field); if (this.meta.title_field) { this.title_field = this.meta.title_field; add_field(this.meta.title_field); } if (frappe.meta.has_field(this.doctype, 'enabled')) { add_field('enabled'); } if (frappe.meta.has_field(this.doctype, 'disabled')) { add_field('disabled'); } this.workflow_state_fieldname = frappe.workflow.get_state_fieldname(this.doctype); if (this.workflow_state_fieldname) { if (!frappe.workflow.workflows[this.doctype]['override_status']) { add_field(this.workflow_state_fieldname); } this.stats.push(this.workflow_state_fieldname); } this.meta.fields.forEach(function (df, i) { if (df.in_list_view && frappe.perm.has_perm(me.doctype, df.permlevel, 'read')) { if (df.fieldtype == 'Image' && df.options) { add_field(df.options); } else { add_field(df.fieldname); } if (df.fieldtype == 'Currency' && df.options) { if (df.options.includes(':')) { add_field(df.options.split(':')[1]); } else { add_field(df.options); } } } }); if (this.settings.add_fields) { this.settings.add_fields.forEach(add_field); } if (me.meta.__kanban_column_fields) { me.meta.__kanban_column_fields.map(add_field); } }, set_columns: function set_columns() { var me = this; this.columns = []; var name_column = { colspan: this.settings.colwidths && this.settings.colwidths.subject || 6, type: 'Subject', title: 'Name' }; if (this.meta.title_field) { name_column.title = frappe.meta.get_docfield(this.doctype, this.meta.title_field).label; } this.columns.push(name_column); if (frappe.has_indicator(this.doctype)) { this.columns.push({ colspan: this.settings.colwidths && this.settings.colwidths.indicator || 3, type: 'Indicator', title: 'Status' }); } this.total_colspans = this.columns.reduce(function (total, curr) { return total + curr.colspan; }, 0); var overridden = (this.settings.add_columns || []).map(function (d) { return d.content; }); var docfields_in_list_view = frappe.get_children('DocType', this.doctype, 'fields', { 'in_list_view': 1 }).sort(function (a, b) { return a.idx - b.idx; }); docfields_in_list_view.forEach(function (d) { if (overridden.includes(d.fieldname) || d.fieldname === me.title_field) { return; } if (me.total_colspans < 12) { me.add_column(d); } }); if (this.settings.add_columns) { this.settings.add_columns.forEach(function (d) { if (me.total_colspans < 12) { if (typeof d === 'string') { me.add_column(frappe.meta.get_docfield(me.doctype, d)); } else { me.columns.push(d); me.total_colspans += parseInt(d.colspan); } } }); } var empty_cols = flt(12 - this.total_colspans); while (empty_cols > 0) { this.columns = this.columns.map(function (col) { if (empty_cols > 0) { col.colspan = cint(col.colspan) + 1; empty_cols = empty_cols - 1; } return col; }); } this.columns = this.columns.uniqBy(function (col) { return col.title; }); this.columns = this.columns.filter(function (col) { return col.fieldtype !== 'Text Editor'; }); this.columns = this.columns.slice(0, 4); }, add_column: function add_column(df) { var colspan = 3; if (in_list(['Int', 'Percent'], df.fieldtype)) { colspan = 2; } else if (in_list(['Check', 'Image'], df.fieldtype)) { colspan = 1; } else if (in_list(['name', 'subject', 'title'], df.fieldname)) { colspan = 4; } else if (df.fieldtype == 'Text Editor' || df.fieldtype == 'Text') { colspan = 4; } if (df.columns && df.columns > 0) { colspan = df.columns; } else if (this.settings.column_colspan && this.settings.column_colspan[df.fieldname]) { colspan = this.settings.column_colspan[df.fieldname]; } else { colspan = 2; } this.total_colspans += parseInt(colspan); var col = { colspan: colspan, content: df.fieldname, type: df.fieldtype, df: df, fieldtype: df.fieldtype, fieldname: df.fieldname, title: __(df.label) }; if (this.settings.column_render && this.settings.column_render[df.fieldname]) { col.render = this.settings.column_render[df.fieldname]; } this.columns.push(col); }, setup_filterable: function setup_filterable() { var me = this; this.list_view.wrapper && this.list_view.wrapper.on('click', '.result-list .filterable', function (e) { e.stopPropagation(); var filters = $(this).attr('data-filter').split('|'); var added = false; filters.forEach(function (f) { f = f.split(','); if (f[2] === 'Today') { f[2] = frappe.datetime.get_today(); } else if (f[2] == 'User') { f[2] = frappe.session.user; } var new_filter = me.list_view.filter_list.add_filter(me.doctype, f[0], f[1], f.slice(2).join(',')); if (new_filter) { added = true; } }); if (added) { me.list_view.refresh(true); } }); this.list_view.wrapper && this.list_view.wrapper.on('click', '.list-item', function (e) { if ($(e.target).hasClass('filterable') || $(e.target).hasClass('octicon-heart') || $(e.target).is(':checkbox')) { return; } var link = $(this).parent().find('a.list-id').get(0); window.location.href = link.href; return false; }); }, render_view: function render_view(values) { var _this = this; var me = this; var $list_items = me.wrapper.find('.list-items'); if ($list_items.length === 0) { $list_items = $('\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t'); me.wrapper.append($list_items); } values.map(function (value) { var $item = $(_this.get_item_html(value)); var $item_container = $('
    ').append($item); $list_items.append($item_container); if (_this.settings.post_render_item) { _this.settings.post_render_item(_this, $item_container, value); } _this.render_tags($item_container, value); }); }, get_item_html: function get_item_html(data) { var _this2 = this; var main = this.columns.map(function (column) { return frappe.render_template('list_item_main', { data: data, col: column, value: data[column.fieldname], formatters: _this2.settings.formatters, subject: _this2.get_subject_html(data, true), indicator: _this2.get_indicator_html(data) }); }).join(""); return frappe.render_template('list_item_row', { data: data, main: main, settings: this.settings, meta: this.meta, indicator_dot: this.get_indicator_dot(data) }); }, get_header_html: function get_header_html() { var _this3 = this; var main = this.columns.map(function (column) { return frappe.render_template('list_item_main_head', { col: column, _checkbox: (frappe.model.can_delete(_this3.doctype) || _this3.settings.selectable) && !_this3.no_delete }); }).join(""); return frappe.render_template('list_item_row_head', { main: main, list: this }); }, render_tags: function render_tags(element, data) { var me = this; var tag_row = $('
    \n\t\t\t
    \n\t\t\t
    \n\t\t
    ').appendTo(element); if (!me.list_view.tags_shown) { tag_row.addClass('hide'); } var tag_editor = new frappe.ui.TagEditor({ parent: tag_row.find('.list-tag'), frm: { doctype: this.doctype, docname: data.name }, list_sidebar: me.list_view.list_sidebar, user_tags: data._user_tags, on_change: function on_change(user_tags) { data._user_tags = user_tags; } }); tag_editor.wrapper.on('click', '.tagit-label', function () { me.list_view.set_filter('_user_tags', $(this).text()); }); }, get_subject_html: function get_subject_html(data, without_workflow) { data._without_workflow = without_workflow; return frappe.render_template('list_item_subject', data); }, get_indicator_html: function get_indicator_html(doc) { var indicator = this.get_indicator_from_doc(doc); if (indicator) { return '\n\t\t\t\t' + __(indicator[0]) + '\n\t\t\t'; } return ''; }, get_indicator_dot: function get_indicator_dot(doc) { var indicator = this.get_indicator_from_doc(doc); if (!indicator) { return ''; } return ''; }, get_indicator_from_doc: function get_indicator_from_doc(doc) { var workflow = frappe.workflow.workflows[this.doctype]; return frappe.get_indicator(doc, this.doctype, workflow && workflow['override_status'] || true); }, prepare_data: function prepare_data(data) { if (data.modified) this.prepare_when(data, data.modified); for (var key in data) { if (data[key] == null) { data[key] = ''; } } data.doctype = this.doctype; data._liked_by = JSON.parse(data._liked_by || '[]'); data._checkbox = (frappe.model.can_delete(this.doctype) || this.settings.selectable) && !this.no_delete; data._doctype_encoded = encodeURIComponent(data.doctype); data._name = data.name.replace(/'/g, '\''); data._name_encoded = encodeURIComponent(data.name); data._submittable = frappe.model.is_submittable(this.doctype); var title_field = this.meta.title_field || 'name'; data._title = strip_html(data[title_field] || data.name); data._full_title = data._title; data._workflow = null; if (this.workflow_state_fieldname) { data._workflow = { fieldname: this.workflow_state_fieldname, value: data[this.workflow_state_fieldname], style: frappe.utils.guess_style(data[this.workflow_state_fieldname]) }; } data._user = frappe.session.user; if (!data._user_tags) data._user_tags = ""; data._tags = data._user_tags.split(',').filter(function (v) { return v; }); data.css_seen = ''; if (data._seen) { var seen = JSON.parse(data._seen); if (seen && in_list(seen, data._user)) { data.css_seen = 'seen'; } } data._hide_activity = 0; data._assign_list = JSON.parse(data._assign || '[]'); if (this.settings.prepare_data) this.settings.prepare_data(data); return data; }, prepare_when: function prepare_when(data, date_str) { if (!date_str) date_str = data.modified; data.when = frappe.datetime.str_to_user(date_str).split(' ')[0]; var diff = frappe.datetime.get_diff(frappe.datetime.get_today(), date_str.split(' ')[0]); if (diff === 0) { data.when = comment_when(date_str); } if (diff === 1) { data.when = __('Yesterday'); } if (diff === 2) { data.when = __('2 days ago'); } }, required_libs: null, prepare_render_view: function prepare_render_view() { var me = this; this._render_view = this.render_view; var lib_exists = typeof this.required_libs === 'string' && this.required_libs || $.isArray(this.required_libs) && this.required_libs.length; this.render_view = function (values) { values = values.map(me.prepare_data.bind(this)); values = values.uniqBy(function (value) { return value.name; }); if (lib_exists) { me.load_lib(function () { me._render_view(values); }); } else { me._render_view(values); } }.bind(this); }, load_lib: function load_lib(callback) { frappe.require(this.required_libs, callback); }, render_bar_graph: function render_bar_graph(parent, data, field, label) { var args = { percent: data[field], label: __(label) }; $(parent).append(' \t\t\t\t\t'); }, render_icon: function render_icon(parent, icon_class, label) { var icon_html = ''; $(parent).append(icon_html); }, make_no_result: function make_no_result() { var new_button = frappe.boot.user.can_create.includes(this.doctype) ? '

    ' : ''; var no_result_message = '
    \n\t\t\t\t

    ' + __('No {0} found', [__(this.doctype)]) + '

    \n\t\t\t\t' + new_button + '\n\t\t\t
    '; return no_result_message; } }); frappe.provide('frappe.views'); frappe.views.GanttView = frappe.views.ListRenderer.extend({ name: 'Gantt', prepare: function prepare(values) { this.items = values; this.prepare_tasks(); this.prepare_dom(); }, render_view: function render_view(values) { var me = this; this.prepare(values); this.render_gantt(); }, set_defaults: function set_defaults() { this._super(); this.no_realtime = true; this.page_title = this.page_title + ' ' + __('Gantt'); }, init_settings: function init_settings() { this._super(); this.field_map = frappe.views.calendar[this.doctype].field_map; this.order_by = this.order_by || this.field_map.start + ' asc'; }, prepare_dom: function prepare_dom() { this.wrapper.css('overflow', 'auto').append(''); }, render_gantt: function render_gantt(tasks) { var me = this; this.gantt_view_mode = this.user_settings.gantt_view_mode || 'Day'; var field_map = frappe.views.calendar[this.doctype].field_map; this.gantt = new Gantt(".gantt-container", this.tasks, { view_mode: this.gantt_view_mode, date_format: "YYYY-MM-DD", on_click: function on_click(task) { frappe.set_route('Form', task.doctype, task.id); }, on_date_change: function on_date_change(task, start, end) { if (!me.can_write()) return; me.update_gantt_task(task, start, end); }, on_progress_change: function on_progress_change(task, progress) { if (!me.can_write()) return; var progress_fieldname = 'progress'; if ($.isFunction(field_map.progress)) { progress_fieldname = null; } else if (field_map.progress) { progress_fieldname = field_map.progress; } if (progress_fieldname) { frappe.db.set_value(task.doctype, task.id, progress_fieldname, parseInt(progress)); } }, on_view_change: function on_view_change(mode) { frappe.model.user_settings.save(me.doctype, 'Gantt', { gantt_view_mode: mode }); }, custom_popup_html: function custom_popup_html(task) { var item = me.get_item(task.id); var html = '
    ' + task.name + '
    \n\t\t\t\t\t

    ' + task._start.format('MMM D') + ' - ' + task._end.format('MMM D') + '

    '; var custom = me.settings.gantt_custom_popup_html; if (custom && $.isFunction(custom)) { var ganttobj = task; html = custom(ganttobj, item); } return '
    ' + html + '
    '; } }); this.render_dropdown(); }, render_dropdown: function render_dropdown() { var me = this; var view_modes = this.gantt.config.view_modes || []; var dropdown = ""; var dropdown_list = ""; view_modes.forEach(function (view_mode) { dropdown_list += "
  • " + "" + __(view_mode) + "
  • "; }); var $dropdown = $(dropdown); $dropdown.find(".dropdown-menu").append(dropdown_list); me.list_view.$page.find('[data-list-renderer=\'Gantt\'] > .list-row-right').css("margin-right", "15px").html($dropdown); $dropdown.on("click", ".option", function () { var mode = $(this).data('value'); me.gantt.change_view_mode(mode); $dropdown.find(".dropdown-text").text(mode); }); }, prepare_tasks: function prepare_tasks() { var me = this; var meta = frappe.get_meta(this.doctype); var field_map = frappe.views.calendar[this.doctype].field_map; this.tasks = this.items.map(function (item) { var progress = 0; if (field_map.progress && $.isFunction(field_map.progress)) { progress = field_map.progress(item); } else if (field_map.progress) { progress = item[field_map.progress]; } if (meta.title_field) { var label = $.format("{0} ({1})", [item[meta.title_field], item.name]); } else { var label = item[field_map.title]; } var r = { start: item[field_map.start], end: item[field_map.end], name: label, id: item[field_map.id || 'name'], doctype: me.doctype, progress: progress, dependencies: item.depends_on_tasks || "" }; if (item.is_milestone) { r['custom_class'] = 'bar-milestone'; }; return r; }); }, get_item: function get_item(name) { return this.items.find(function (item) { return item.name === name; }); }, update_gantt_task: function update_gantt_task(task, start, end) { var me = this; if (me.gantt.updating_task) { setTimeout(me.update_gantt_task.bind(me, task, start, end), 200); return; } me.gantt.updating_task = true; var field_map = frappe.views.calendar[this.doctype].field_map; frappe.call({ method: 'frappe.desk.gantt.update_task', args: { args: { doctype: task.doctype, name: task.id, start: start.format('YYYY-MM-DD'), end: end.format('YYYY-MM-DD') }, field_map: field_map }, callback: function callback() { me.gantt.updating_task = false; frappe.show_alert({ message: __("Saved"), indicator: 'green' }, 1); } }); }, get_header_html: function get_header_html() { return frappe.render_template('list_item_row_head', { main: '', list: this }); }, refresh: function refresh(values) { this.prepare(values); this.render(); }, can_write: function can_write() { if (frappe.model.can_write(this.doctype)) { return true; } else { this.gantt.change_view_mode(this.gantt_view_mode); frappe.show_alert({ message: __("Not permitted"), indicator: 'red' }, 1); return false; } }, set_columns: function set_columns() {}, required_libs: ["assets/frappe/js/lib/snap.svg-min.js", "assets/frappe/js/lib/frappe-gantt/frappe-gantt.js"] }); frappe.provide("frappe.views.calendar"); frappe.provide("frappe.views.calendars"); frappe.views.CalendarView = frappe.views.ListRenderer.extend({ name: 'Calendar', render_view: function render_view() { var me = this; var options = { doctype: this.doctype, parent: this.wrapper, page: this.list_view.page, list_view: this.list_view }; $.extend(options, frappe.views.calendar[this.doctype]); this.calendar = new frappe.views.Calendar(options); }, set_defaults: function set_defaults() { this._super(); this.page_title = this.page_title + ' ' + __('Calendar'); this.no_realtime = true; this.show_no_result = false; this.hide_sort_selector = true; }, get_header_html: function get_header_html() { return null; }, required_libs: ['assets/frappe/js/lib/fullcalendar/fullcalendar.min.css', 'assets/frappe/js/lib/fullcalendar/fullcalendar.min.js', 'assets/frappe/js/lib/fullcalendar/locale-all.js'] }); frappe.views.Calendar = Class.extend({ init: function init(options) { $.extend(this, options); this.make_page(); this.setup_options(); this.make(); }, make_page: function make_page() { var me = this; me.page.clear_user_actions(); $.each(frappe.boot.calendars, function (i, doctype) { if (frappe.model.can_read(doctype)) { me.page.add_menu_item(__(doctype), function () { frappe.set_route("List", doctype, "Calendar"); }); } }); $(this.parent).on("show", function () { me.$cal.fullCalendar("refetchEvents"); }); }, make: function make() { var me = this; this.$wrapper = this.parent; this.$cal = $("
    ").appendTo(this.$wrapper); this.footnote_area = frappe.utils.set_footnote(this.footnote_area, this.$wrapper, __("Select or drag across time slots to create a new event.")); this.footnote_area.css({ "border-top": "0px" }); this.$cal.fullCalendar(this.cal_options); this.set_css(); }, set_css: function set_css() { this.$wrapper.find("button.fc-state-default").removeClass("fc-state-default").addClass("btn btn-default"); this.$wrapper.find(".fc-button-group").addClass("btn-group"); this.$wrapper.find('.fc-prev-button span').attr('class', '').addClass('fa fa-chevron-left'); this.$wrapper.find('.fc-next-button span').attr('class', '').addClass('fa fa-chevron-right'); var btn_group = this.$wrapper.find(".fc-button-group"); btn_group.find(".fc-state-active").addClass("active"); btn_group.find(".btn").on("click", function () { btn_group.find(".btn").removeClass("active"); $(this).addClass("active"); }); }, field_map: { "id": "name", "start": "start", "end": "end", "allDay": "all_day" }, color_map: { "danger": "red", "success": "green", "warning": "orange" }, get_system_datetime: function get_system_datetime(date) { date._offset = moment.user_utc_offset; return frappe.datetime.convert_to_system_tz(date); }, setup_options: function setup_options() { var me = this; this.cal_options = { locale: frappe.boot.user.language || "en", header: { left: 'title', center: '', right: 'prev,next month,agendaWeek,agendaDay' }, editable: true, selectable: true, selectHelper: true, forceEventDuration: true, events: function events(start, end, timezone, _callback) { return frappe.call({ method: me.get_events_method || "frappe.desk.calendar.get_events", type: "GET", args: me.get_args(start, end), callback: function callback(r) { var events = r.message; events = me.prepare_events(events); _callback(events); } }); }, eventRender: function eventRender(event, element) { element.attr('title', event.tooltip); }, eventClick: function eventClick(event, jsEvent, view) { var doctype = event.doctype || me.doctype; if (frappe.model.can_read(doctype)) { frappe.set_route("Form", doctype, event.name); } }, eventDrop: function eventDrop(event, delta, revertFunc, jsEvent, ui, view) { me.update_event(event, revertFunc); }, eventResize: function eventResize(event, delta, revertFunc, jsEvent, ui, view) { me.update_event(event, revertFunc); }, select: function select(startDate, endDate, jsEvent, view) { if (view.name === "month" && endDate - startDate === 86400000) { return; } var event = frappe.model.get_new_doc(me.doctype); event[me.field_map.start] = me.get_system_datetime(startDate); if (me.field_map.end) event[me.field_map.end] = me.get_system_datetime(endDate); if (me.field_map.allDay) { var all_day = startDate._ambigTime && endDate._ambigTime ? 1 : 0; event[me.field_map.allDay] = all_day; if (all_day) event[me.field_map.end] = me.get_system_datetime(moment(endDate).subtract(1, "s")); } frappe.set_route("Form", me.doctype, event.name); }, dayClick: function dayClick(date, jsEvent, view) { if (view.name === 'month') { var $date_cell = $('td[data-date=' + date.format('YYYY-MM-DD') + "]"); if ($date_cell.hasClass('date-clicked')) { me.$cal.fullCalendar('changeView', 'agendaDay'); me.$cal.fullCalendar('gotoDate', date); me.$wrapper.find('.date-clicked').removeClass('date-clicked'); me.$wrapper.find('.fc-month-button').removeClass('active'); me.$wrapper.find('.fc-agendaDay-button').addClass('active'); } me.$wrapper.find('.date-clicked').removeClass('date-clicked'); $date_cell.addClass('date-clicked'); } return false; } }; if (this.options) { $.extend(this.cal_options, this.options); } }, get_args: function get_args(start, end) { var args = { doctype: this.doctype, start: this.get_system_datetime(start), end: this.get_system_datetime(end), filters: this.list_view.filter_list.get_filters() }; return args; }, refresh: function refresh() { this.$cal.fullCalendar('refetchEvents'); }, prepare_events: function prepare_events(events) { var me = this; return (events || []).map(function (d) { d.id = d.name; d.editable = frappe.model.can_write(d.doctype || me.doctype); if (d.docstatus && d.docstatus > 0) { d.editable = false; } $.each(me.field_map, function (target, source) { d[target] = d[source]; }); if (!me.field_map.allDay) d.allDay = 1; d.start = frappe.datetime.convert_to_user_tz(d.start); d.end = frappe.datetime.convert_to_user_tz(d.end); me.fix_end_date_for_event_render(d); var color = void 0; if (me.get_css_class) { color = me.color_map[me.get_css_class(d)]; if (!Object.values(me.color_map).includes(color)) { color = "blue"; } } else { color = d.color; } if (!color) color = "blue"; d.className = "fc-bg-" + color; return d; }); }, update_event: function update_event(event, revertFunc) { var me = this; frappe.model.remove_from_locals(me.doctype, event.name); return frappe.call({ method: me.update_event_method || "frappe.desk.calendar.update_event", args: me.get_update_args(event), callback: function callback(r) { if (r.exc) { frappe.show_alert(__("Unable to update event")); revertFunc(); } }, error: function error() { revertFunc(); } }); }, get_update_args: function get_update_args(event) { var me = this; var args = { name: event[this.field_map.id] }; args[this.field_map.start] = me.get_system_datetime(event.start); if (this.field_map.allDay) args[this.field_map.allDay] = event.start._ambigTime && event.end._ambigTime ? 1 : 0; if (this.field_map.end) { if (!event.end) { event.end = event.start.add(1, "hour"); } args[this.field_map.end] = me.get_system_datetime(event.end); if (args[this.field_map.allDay]) { args[this.field_map.end] = me.get_system_datetime(moment(event.end).subtract(1, "s")); } } args.doctype = event.doctype || this.doctype; return { args: args, field_map: this.field_map }; }, fix_end_date_for_event_render: function fix_end_date_for_event_render(event) { if (event.allDay) { event.start = event.start ? $.fullCalendar.moment(event.start).stripTime() : null; event.end = event.end ? $.fullCalendar.moment(event.end).add(1, "day").stripTime() : null; } } }); frappe.provide("frappe.views"); frappe.views.ImageView = frappe.views.ListRenderer.extend({ name: 'Image', render_view: function render_view(values) { this.items = values; this.render_image_view(); this.setup_gallery(); }, set_defaults: function set_defaults() { this._super(); this.page_title = this.page_title + ' ' + __('Images'); }, render_image_view: function render_image_view() { var html = this.items.map(this.render_item.bind(this)).join(""); this.container = $('
    ').addClass('image-view-container').appendTo(this.wrapper); this.container.append(html); }, render_item: function render_item(item) { var image_url = this.get_image_url(item); var indicator = this.get_indicator_html(item); return frappe.render_template("image_view_item_row", { data: item, indicator: indicator, subject: this.get_subject_html(item, true), additional_columns: this.additional_columns, item_image: image_url, color: frappe.get_palette(item.item_name) }); }, get_image_url: function get_image_url(item) { var url; url = item.image ? item.image : item[this.meta.image_field]; if (window.cordova && !frappe.utils.is_url(url)) { url = frappe.base_url + url; } if (url) { return url; } return null; }, get_header_html: function get_header_html() { var main = frappe.render_template('list_item_main_head', { col: { type: "Subject" }, _checkbox: (frappe.model.can_delete(this.doctype) || this.settings.selectable) && !this.no_delete }); return frappe.render_template('list_item_row_head', { main: main, list: this }); }, setup_gallery: function setup_gallery() { var me = this; var gallery = new frappe.views.GalleryView({ doctype: this.doctype, items: this.items, wrapper: this.container }); this.container.on('click', '.btn.zoom-view', function (e) { e.preventDefault(); e.stopPropagation(); var name = $(this).data().name; gallery.show(name); return false; }); } }); frappe.views.GalleryView = Class.extend({ init: function init(opts) { $.extend(this, opts); var me = this; this.ready = false; this.load_lib(function () { me.prepare(); me.ready = true; }); }, prepare: function prepare() { this.pswp_root = $('body > .pswp'); if (this.pswp_root.length === 0) { var pswp = frappe.render_template('photoswipe_dom'); this.pswp_root = $(pswp).appendTo('body'); } }, show: function show(docname) { var me = this; if (!this.ready) { setTimeout(this.show.bind(this), 200); return; } var items = this.items.map(function (i) { var query = 'img[data-name="' + i.name + '"]'; var el = me.wrapper.find(query).get(0); if (el) { var width = el.naturalWidth; var height = el.naturalHeight; } if (!el) { el = me.wrapper.find('.image-field[data-name="' + i.name + '"]').get(0); width = el.getBoundingClientRect().width; height = el.getBoundingClientRect().height; } return { src: i.image, msrc: i.image, name: i.name, w: width, h: height, el: el }; }); var index; items.map(function (item, i) { if (item.name === docname) index = i; }); var options = { index: index, getThumbBoundsFn: function getThumbBoundsFn(index) { var thumbnail = items[index].el, pageYScroll = window.pageYOffset || document.documentElement.scrollTop, rect = thumbnail.getBoundingClientRect(); return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; }, history: false, shareEl: false }; var pswp = new PhotoSwipe(this.pswp_root.get(0), PhotoSwipeUI_Default, items, options); pswp.init(); }, get_image_urls: function get_image_urls() { return frappe.call({ method: "frappe.client.get_list", args: { doctype: "File", order_by: "attached_to_name", fields: ["'image/*' as type", "ifnull(thumbnail_url, file_url) as thumbnail", "concat(attached_to_name, ' - ', file_name) as title", "file_url as src", "attached_to_name as name"], filters: [["File", "attached_to_doctype", "=", this.doctype], ["File", "attached_to_name", "in", this.docnames], ["File", "is_folder", "!=", 1]] }, freeze: true, freeze_message: __("Fetching Images..") }).then(function (r) { if (!r.message) { frappe.msgprint(__("No Images found")); } else { var images = r.message.filter(function (image) { return frappe.utils.is_image_file(image.title || image.href); }); } }); }, load_lib: function load_lib(callback) { var asset_dir = 'assets/frappe/js/lib/photoswipe/'; frappe.require([asset_dir + 'photoswipe.css', asset_dir + 'default-skin.css', asset_dir + 'photoswipe.js', asset_dir + 'photoswipe-ui-default.js'], callback); } }); frappe.provide('frappe.views'); frappe.views.KanbanView = frappe.views.ListRenderer.extend({ name: 'Kanban', render_view: function render_view(values) { var board_name = this.get_board_name(); if (this.kanban && board_name === this.kanban.board_name) { this.kanban.update(values); return; } this.kanban = new frappe.views.KanbanBoard({ doctype: this.doctype, board_name: board_name, cards: values, wrapper: this.wrapper, cur_list: this.list_view, user_settings: this.user_settings }); }, after_refresh: function after_refresh() { this.wrapper.find('.kanban').trigger('after-refresh'); frappe.kanban_filters[this.get_board_name()] = this.list_view.filter_list.get_filters(); }, should_refresh: function should_refresh() { var to_refresh = this._super(); if (!to_refresh) { this.last_kanban_board = this.current_kanban_board || ''; this.current_kanban_board = this.get_board_name(); this.page_title = __(this.get_board_name()); to_refresh = this.current_kanban_board !== this.last_kanban_board; } return to_refresh; }, init_settings: function init_settings() { this._super(); this.filters = this.get_kanban_filters(); }, get_kanban_filters: function get_kanban_filters() { frappe.provide('frappe.kanban_filters'); var board_name = this.get_board_name(); if (!frappe.kanban_filters[board_name]) { var kb = this.meta.__kanban_boards.find(function (board) { return board.name === board_name; }); frappe.kanban_filters[board_name] = JSON.parse(kb && kb.filters || '[]'); } if (typeof frappe.kanban_filters[board_name] === 'string') { frappe.kanban_filters[board_name] = JSON.parse(frappe.kanban_filters[board_name] || '[]'); } var filters = frappe.kanban_filters[board_name]; return filters; }, set_defaults: function set_defaults() { this._super(); this.no_realtime = true; this.show_no_result = false; this.page_title = __(this.get_board_name()); }, get_board_name: function get_board_name() { var route = frappe.get_route(); return route[3]; }, get_header_html: function get_header_html() { return frappe.render_template('list_item_row_head', { main: '', list: this }); }, required_libs: ['assets/frappe/js/lib/fluxify.min.js', 'assets/frappe/js/frappe/views/kanban/kanban_board.js'] }); frappe.provide("frappe.views"); frappe.views.InboxView = frappe.views.ListRenderer.extend({ name: 'Inbox', render_view: function render_view(values) { var me = this; this.emails = values; frappe.model.user_settings.save("Communication", 'Inbox', { last_email_account: this.current_email_account }); this.render_inbox_view(); }, render_inbox_view: function render_inbox_view() { var html = ""; var email_account = this.get_current_email_account(); if (email_account) html = this.emails.map(this.render_email_row.bind(this)).join("");else html = this.make_no_result(); this.container = $('
    ').addClass('inbox-container').appendTo(this.wrapper); this.container.append(html); }, render_email_row: function render_email_row(email) { if (!email.css_seen && email.seen) email.css_seen = "seen"; return frappe.render_template("inbox_view_item_row", { data: email, is_sent_emails: this.is_sent_emails }); }, set_defaults: function set_defaults() { this._super(); this.page_title = __("Email Inbox"); }, init_settings: function init_settings() { this._super(); this.filters = this.get_inbox_filters(); }, should_refresh: function should_refresh() { var to_refresh = this._super(); if (!to_refresh) { this.last_email_account = this.current_email_account || ''; this.current_email_account = this.get_current_email_account(); this.is_sent_emails = this.current_email_account === "Sent" ? true : false; to_refresh = this.current_email_account !== this.last_email_account; } if (to_refresh) { this.list_view.page.main.find(".list-headers").empty(); } return to_refresh; }, get_inbox_filters: function get_inbox_filters() { var email_account = this.get_current_email_account(); var default_filters = [["Communication", "communication_type", "=", "Communication", true], ["Communication", "communication_medium", "=", "Email", true]]; var filters = []; if (email_account === "Sent") { filters = default_filters.concat([["Communication", "sent_or_received", "=", "Sent", true], ["Communication", "email_status", "not in", "Spam,Trash", true]]); } else if (in_list(["Spam", "Trash"], email_account)) { filters = default_filters.concat([["Communication", "email_status", "=", email_account, true], ["Communication", "email_account", "in", frappe.boot.all_accounts, true]]); } else { var op = "="; if (email_account == "All Accounts") { op = "in"; email_account = frappe.boot.all_accounts; } filters = default_filters.concat([["Communication", "sent_or_received", "=", "Received", true], ["Communication", "email_account", op, email_account, true], ["Communication", "email_status", "not in", "Spam,Trash", true]]); } return filters; }, get_header_html: function get_header_html() { var header = ""; if (this.current_email_account) { header = frappe.render_template('inbox_view_item_main_head', { _checkbox: (frappe.model.can_delete(this.doctype) || this.settings.selectable) && !this.no_delete, is_sent_emails: this.is_sent_emails }); } return header; }, get_current_email_account: function get_current_email_account() { var route = frappe.get_route(); if (!route[3] && frappe.boot.email_accounts.length) { var email_account; if (frappe.boot.email_accounts[0].email_id == "All Accounts") { email_account = "All Accounts"; } else { email_account = frappe.boot.email_accounts[0].email_account; } frappe.set_route("List", "Communication", "Inbox", email_account); } else if (route[3] && route[3] != "All Accounts" && !frappe.boot.email_accounts.find(function (b) { return b.email_account === route[3]; })) { return ''; } return route[3]; }, make_no_result: function make_no_result() { var no_result_message = ""; var email_account = this.get_current_email_account(); var args; if (in_list(["Spam", "Trash"], email_account)) { return __("No {0} mail", [email_account]); } else if (!email_account && !frappe.boot.email_accounts.length) { this.no_result_doctype = "Email Account"; args = { doctype: "Email Account", msg: __("No Email Account"), label: __("New Email Account") }; } else { this.no_result_doctype = "Communication"; args = { doctype: "Communication", msg: __("No Emails"), label: __("Compose Email") }; } var no_result_message = frappe.render_template("inbox_no_result", args); return no_result_message; }, make_new_doc: function make_new_doc() { if (this.no_result_doctype == "Communication") { new frappe.views.CommunicationComposer({ doc: {} }); } else { frappe.route_options = { 'email_id': frappe.session.user_email }; frappe.new_doc(this.no_result_doctype); } } });frappe.templates['header_select_all_like_filter'] = '{% if (_checkbox) { %} {% } %} '; frappe.templates['item_assigned_to_comment_count'] = ' {%= comment_when(data.modified, true) %} {% if (data._assign_list.length) { %} {%= frappe.avatar(data._assign_list[data._assign_list.length - 1]) %} {% } else { %} {% } %} {%= (data._comment_count > 99 ? "99+" : data._comment_count) || 0 %} '; frappe.provide("frappe.treeview_settings"); frappe.provide('frappe.views.trees'); cur_tree = null; frappe.views.TreeFactory = frappe.views.Factory.extend({ make: function make(route) { frappe.model.with_doctype(route[1], function () { var options = { doctype: route[1], meta: frappe.get_meta(route[1]) }; if (!frappe.treeview_settings[route[1]] && !frappe.meta.get_docfield(route[1], "is_group")) { frappe.msgprint(__("Tree view not available for {0}", [route[1]])); return false; } $.extend(options, frappe.treeview_settings[route[1]] || {}); frappe.views.trees[options.doctype] = new frappe.views.TreeView(options); }); } }); frappe.views.TreeView = Class.extend({ init: function init(opts) { var me = this; this.opts = {}; this.opts.get_tree_root = true; $.extend(this.opts, opts); this.doctype = opts.doctype; this.args = { doctype: me.doctype }; this.page_name = frappe.get_route_str(); this.get_tree_nodes = me.opts.get_tree_nodes || "frappe.desk.treeview.get_children"; this.get_permissions(); this.make_page(); this.make_filters(); if (me.opts.get_tree_root) { this.get_root(); } this.set_menu_item(); this.set_primary_action(); }, get_permissions: function get_permissions() { this.can_read = frappe.model.can_read(this.doctype); this.can_create = frappe.boot.user.can_create.indexOf(this.doctype) !== -1 || frappe.boot.user.in_create.indexOf(this.doctype) !== -1; this.can_write = frappe.model.can_write(this.doctype); this.can_delete = frappe.model.can_delete(this.doctype); }, make_page: function make_page() { var me = this; this.parent = frappe.container.add_page(this.page_name); frappe.ui.make_app_page({ parent: this.parent, single_column: true }); this.page = this.parent.page; frappe.container.change_to(this.page_name); frappe.breadcrumbs.add(me.opts.breadcrumb || locals.DocType[me.doctype].module); this.page.set_title(me.opts.title || __('{0} Tree', [__(this.doctype)])); this.page.main.css({ "min-height": "300px", "padding-bottom": "25px" }); this.page.add_inner_button(__('Expand All'), function () { me.tree.rootnode.load_all(); }); if (this.opts.view_template) { var row = $('
    ').appendTo(this.page.main); this.body = $('
    ').appendTo(row); this.node_view = $('').appendTo(row); } else { this.body = this.page.main; } }, make_filters: function make_filters() { var me = this; frappe.treeview_settings.filters = []; $.each(this.opts.filters || [], function (i, filter) { if (frappe.route_options && frappe.route_options[filter.fieldname]) { filter.default = frappe.route_options[filter.fieldname]; } me.page.add_field(filter).$input.on('change', function () { var val = $(this).val(); if (val) { me.args[$(this).attr("data-fieldname")] = val; frappe.treeview_settings.filters = me.args; me.make_tree(); me.page.set_title(val); } }); if (filter.default) { $("[data-fieldname='" + filter.fieldname + "']").trigger("change"); } }); }, get_root: function get_root() { var me = this; frappe.call({ method: me.get_tree_nodes, args: me.args, callback: function callback(r) { if (r.message) { me.root = r.message[0]["value"]; me.make_tree(); } } }); }, make_tree: function make_tree() { var me = this; $(me.parent).find(".tree").remove(); this.tree = new frappe.ui.Tree({ parent: me.body, label: me.args[me.opts.root_label] || me.opts.root_label || me.root, args: me.args, method: me.get_tree_nodes, toolbar: me.get_toolbar(), get_label: me.opts.get_label, onrender: me.opts.onrender, onclick: function onclick(node) { me.select_node(node); } }); cur_tree = this.tree; }, select_node: function select_node(node) { var me = this; if (this.opts.click) { this.opts.click(node); } if (this.opts.view_template) { this.node_view.empty(); $(frappe.render_template(me.opts.view_template, { data: node.data, doctype: me.doctype })).appendTo(this.node_view); } }, get_toolbar: function get_toolbar() { var me = this; var toolbar = [{ toggle_btn: true }, { label: __(me.can_write ? "Edit" : "Details"), condition: function condition(node) { return !node.root && me.can_read; }, click: function click(node) { frappe.set_route("Form", me.doctype, node.label); } }, { label: __("Add Child"), condition: function condition(node) { return me.can_create && node.expandable; }, click: function click(node) { me.new_node(); }, btnClass: "hidden-xs" }, { label: __("Rename"), condition: function condition(node) { return !node.root && me.can_write; }, click: function click(node) { frappe.model.rename_doc(me.doctype, node.label, function (new_name) { node.tree_link.find('a').text(new_name); node.label = new_name; }); }, btnClass: "hidden-xs" }, { label: __("Delete"), condition: function condition(node) { return !node.root && me.can_delete; }, click: function click(node) { frappe.model.delete_doc(me.doctype, node.label, function () { node.parent.remove(); }); }, btnClass: "hidden-xs" }]; if (this.opts.toolbar && this.opts.extend_toolbar) { return toolbar.concat(this.opts.toolbar); } else if (this.opts.toolbar && !this.opts.extend_toolbar) { return this.opts.toolbar; } else { return toolbar; } }, new_node: function new_node() { var me = this; var node = me.tree.get_selected_node(); if (!(node && node.expandable)) { frappe.msgprint(__("Select a group node first.")); return; } this.prepare_fields(); var d = new frappe.ui.Dialog({ title: __('New {0}', [__(me.doctype)]), fields: me.fields }); var args = $.extend({}, me.args); args["parent_" + me.doctype.toLowerCase().replace(/ /g, '_')] = me.args["parent"]; d.set_value("is_group", 0); d.set_values(args); d.set_primary_action(__("Create New"), function () { var btn = this; var v = d.get_values(); if (!v) return; var node = me.tree.get_selected_node(); v.parent = node.label; v.doctype = me.doctype; if (node.root) { v.is_root = 1; v.parent_account = null; } else { v.is_root = 0; v.root_type = null; } $.extend(args, v); return frappe.call({ method: me.opts.add_tree_node || "frappe.desk.treeview.add_node", args: args, callback: function callback(r) { if (!r.exc) { d.hide(); if (node.expanded) { node.toggle_node(); } node.load_all(); } } }); }); d.show(); }, prepare_fields: function prepare_fields() { var me = this; this.fields = [{ fieldtype: 'Check', fieldname: 'is_group', label: __('Group Node'), description: __("Further nodes can be only created under 'Group' type nodes") }]; if (this.opts.fields) { this.fields = this.opts.fields; } this.ignore_fields = this.opts.ignore_fields || []; var mandatory_fields = $.map(me.opts.meta.fields, function (d) { return d.reqd || d.bold && !d.read_only ? d : null; }); var opts_field_names = this.fields.map(function (d) { return d.fieldname; }); mandatory_fields.map(function (d) { if ($.inArray(d.fieldname, me.ignore_fields) === -1 && $.inArray(d.fieldname, opts_field_names) === -1) { me.fields.push(d); } }); }, set_primary_action: function set_primary_action() { var me = this; if (!this.opts.disable_add_node && this.can_create) { me.page.set_primary_action(__("New"), function () { me.new_node(); }, "octicon octicon-plus"); } }, set_menu_item: function set_menu_item() { var me = this; this.menu_items = [{ label: __('View List'), action: function action() { frappe.set_route('List', me.doctype); } }, { label: __('Refresh'), action: function action() { me.make_tree(); } }]; if (me.opts.menu_items) { me.menu_items.push.apply(me.menu_items, me.opts.menu_items); } $.each(me.menu_items, function (i, menu_item) { var has_perm = true; if (menu_item["condition"]) { has_perm = eval(menu_item["condition"]); } if (has_perm) { me.page.add_menu_item(menu_item["label"], menu_item["action"]); } }); } });frappe.templates['image_view_item_row'] = '
    {{ subject }}
    '; frappe.templates['photoswipe_dom'] = ' '; frappe.templates['inbox_no_result'] = '
    {% if(!frappe.model.can_create(doctype) && doctype == "Email Account") { %}

    {{ __("No Email Accounts Assigned") }}

    {% } else { %}

    {{ msg }}

    {% } %}
    '; frappe.templates['inbox_view_item_row'] = '
    {% if (data._checkbox) { %} {% } %} {%= data.subject %}
    {% if(data.has_attachment) { %} {% } %}
    '; frappe.templates['inbox_view_item_main_head'] = '
    {% if (_checkbox) { %} {% } %} {%= __("Subject") %}
    '; frappe.templates['kanban_board'] = '
    '; frappe.templates['kanban_column'] = '
    {{ __(title) }}
    {{ __("Add " + doctype) }}
    '; frappe.templates['kanban_card'] = '
    {{ title }}
    ';