').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 = $('').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'] = '
{% for (var i in liked_by) { var liked_by_user = liked_by[i]; %} {%= frappe.avatar(liked_by_user) %} {%= frappe.user.full_name(liked_by_user) %} {% } %} ';
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 (is_different) { %}
{%= data.name %} {% } %}
{% } %} {% if (!data._hide_activity) { %}
{%= frappe.render_template("item_assigned_to_comment_count", { data: data }) %}
{%= 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) { %}
{{ (_liked_by.length > 99 ? "99+" : _liked_by.length) || "" }} {% } %}
{{ 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 = $('
').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) ? '\n\t\t\t\t\t' + __('Make a new {0}', [__(this.doctype)]) + '\n\t\t\t\t
' : '';
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 { %}
{% } %} ';
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'] = '
';
frappe.templates['photoswipe_dom'] = '
';
frappe.templates['inbox_no_result'] = '
{% if(!frappe.model.can_create(doctype) && doctype == "Email Account") { %}
{{ __("No Email Accounts Assigned") }}
{% } else { %}
{{ msg }}
{{ label }}
{% } %}
';
frappe.templates['inbox_view_item_row'] = '
{%= is_sent_emails? data.recipients: data.sender %}
{% if(data.has_attachment) { %} {% } %}
{% if(data.reference_doctype && data.reference_name) { %} {% } %} {% if(data.has_attachment) { %} {% } %} {%= comment_when(data.modified, true) %} ';
frappe.templates['inbox_view_item_main_head'] = '
{%= __(is_sent_emails ? "To": "From") %}
';
frappe.templates['kanban_board'] = '
';
frappe.templates['kanban_column'] = '
{{ __("Add " + doctype) }}
';
frappe.templates['kanban_card'] = '
';