Selaa lähdekoodia

[feature] checkboxes in grid #2451

version-14
Rushabh Mehta 8 vuotta sitten
vanhempi
commit
ac69247325
8 muutettua tiedostoa jossa 131 lisäystä ja 22 poistoa
  1. +23
    -0
      frappe/model/mapper.py
  2. +67
    -9
      frappe/public/js/frappe/form/grid.js
  3. +5
    -5
      frappe/public/js/frappe/form/link_selector.js
  4. +2
    -0
      frappe/public/js/frappe/form/templates/grid_body.html
  5. +4
    -2
      frappe/public/js/frappe/model/create_new.js
  6. +22
    -0
      frappe/public/js/legacy/clientscriptAPI.js
  7. +2
    -4
      frappe/tests/test_scheduler.py
  8. +6
    -2
      frappe/utils/scheduler.py

+ 23
- 0
frappe/model/mapper.py Näytä tiedosto

@@ -7,6 +7,22 @@ from frappe import _
from frappe.utils import cstr
from frappe.model import default_fields

@frappe.whitelist()
def make_mapped_doc(method, source_name, selected_children=None):
'''Returns the mapped document calling the given mapper method.
Sets selected_children as flags for the `get_mapped_doc` method.

Called from `open_mapped_doc` from create_new.js'''
method = frappe.get_attr(method)

if method not in frappe.whitelisted:
raise frappe.PermissionError

frappe.flags.selected_children = selected_children

return method(source_name)


def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None,
postprocess=None, ignore_permissions=False, ignore_child_tables=False):

@@ -51,6 +67,13 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None,
if not table_map["condition"](source_d):
continue

# if children are selected (checked from UI) for this table type,
# and this record is not in the selected children, then continue
if (frappe.flags.selected_children
and (df.fieldname in frappe.flags.selected_children)
and source_d.name not in frappe.flags.selected_children):
continue

target_child_doctype = table_map["doctype"]
target_parentfield = target_doc.get_parentfield_of_doctype(target_child_doctype)



+ 67
- 9
frappe/public/js/frappe/form/grid.js Näytä tiedosto

@@ -58,10 +58,45 @@ frappe.ui.form.Grid = Class.extend({

this.custom_buttons = {};
this.grid_buttons = this.wrapper.find('.grid-buttons');
this.remove_rows_button = this.grid_buttons.find('.grid-remove-rows')

this.setup_allow_bulk_edit();
this.setup_check();

},
setup_check: function() {
var me = this;
this.wrapper.on('click', '.grid-row-check', function(e) {
$check = $(this);
if($check.parents('.grid-heading-row:first').length!==0) {
$check.parents('.form-grid:first').find('.grid-row-check').prop('checked', $check.prop('checked'));
}
me.refresh_remove_rows_button();
});

this.remove_rows_button.on('click', function() {
me.get_selected().forEach(function(docname) {
me.grid_rows_by_docname[docname].remove();
});
setTimeout(function() { me.refresh_remove_rows_button(); }, 100);
});
},
refresh_remove_rows_button: function() {
this.remove_rows_button.toggleClass('hide',
this.wrapper.find('.grid-body .grid-row-check:checked:first').length ? false : true);
},
get_selected: function() {
var selected = [];
var me = this;
this.wrapper.find('.grid-body .grid-row-check:checked').each(function() {
selected.push($(this).parents('.grid-row:first').attr('data-name'));
});
return selected;
},
refresh_checks: function() {
var show = this.is_editable() || this.frm.has_mapper();
this.wrapper.find('.grid-row-check').toggle(show);
},
make_head: function() {
// labels
if(!this.header_row) {
@@ -132,6 +167,7 @@ frappe.ui.form.Grid = Class.extend({

// toolbar
this.setup_toolbar();
this.refresh_checks();

// sortable
if(this.is_sortable() && !this.sortable_setup_done) {
@@ -143,6 +179,8 @@ frappe.ui.form.Grid = Class.extend({
this.last_docname = this.frm.docname;
frappe.utils.scroll_to(_scroll_y);
}

this.refresh_remove_rows_button();
},
setup_toolbar: function() {
if(this.is_editable()) {
@@ -216,7 +254,6 @@ frappe.ui.form.Grid = Class.extend({
return;
}


new Sortable($rows.get(0), {
group: {name: 'row'},
handle: ".sortable-handle",
@@ -545,6 +582,7 @@ frappe.ui.form.GridRow = Class.extend({
init: function(opts) {
this.on_grid_fields_dict = {};
this.on_grid_fields = [];
this.row_check_html = '<input type="checkbox" class="grid-row-check pull-left">';
this.columns = {};
this.columns_list = [];
$.extend(this, opts);
@@ -552,9 +590,13 @@ frappe.ui.form.GridRow = Class.extend({
},
make: function() {
var me = this;

this.wrapper = $('<div class="grid-row"></div>').appendTo(this.parent).data("grid_row", this);
this.row = $('<div class="data-row row sortable-handle"></div>').appendTo(this.wrapper)
.on("click", function() {
.on("click", function(e) {
if($(e.target).hasClass('grid-row-check')) {
return;
}
if(me.grid.allow_on_grid_editing() && me.grid.is_editable()) {
// pass
} else {
@@ -563,6 +605,11 @@ frappe.ui.form.GridRow = Class.extend({
}
});

// no checkboxes if too small
if(this.is_too_small()) {
this.row_check_html = '';
}

if(this.grid.template && !this.grid.meta.editable_grid) {
this.render_template();
} else {
@@ -582,7 +629,7 @@ frappe.ui.form.GridRow = Class.extend({
this.wrapper
.attr('data-name', this.doc.name)
.attr("data-idx", this.doc.idx)
.find(".row-index, .grid-form-row-index").html(this.doc.idx)
.find(".row-index span, .grid-form-row-index").html(this.doc.idx)

}
},
@@ -638,9 +685,9 @@ frappe.ui.form.GridRow = Class.extend({
if(this.doc) {
if(!this.row_index) {
this.row_index = $('<div style="float: left; margin-left: 15px; margin-top: 8px; \
margin-right: -20px;"></div>').appendTo(this.row);
margin-right: -20px;">'+this.row_check_html+' <span></span></div>').appendTo(this.row);
}
this.row_index.html(this.doc.idx);
this.row_index.find('span').html(this.doc.idx);
}

this.row_display = $('<div class="row-data template-row">'+
@@ -657,11 +704,18 @@ frappe.ui.form.GridRow = Class.extend({

// index (1, 2, 3 etc)
if(!this.row_index) {
this.row_index = $('<div class="row-index col col-xs-1">' + (this.doc ? this.doc.idx : "&nbsp;")+ '</div>')
var txt = (this.doc ? this.doc.idx : "&nbsp;");
this.row_index = $('<div class="row-index col col-xs-1">' +
this.row_check_html +
' <span>' + txt + '</span></div>')
.appendTo(this.row)
.on('click', function() { me.toggle_view(); });
.on('click', function(e) {
if(!$(e.target).hasClass('grid-row-check')) {
me.toggle_view();
}
});
} else {
this.row_index.html(this.doc ? this.doc.idx : "&nbsp;");
this.row_index.find('span').html(txt);
}

this.setup_columns();
@@ -676,6 +730,10 @@ frappe.ui.form.GridRow = Class.extend({
this.row.toggleClass('editable-row', this.grid.is_editable());
},

is_too_small: function() {
return this.row.width() < 400;
},

add_open_form_button: function() {
var me = this;
if(this.doc) {
@@ -686,7 +744,7 @@ frappe.ui.form.GridRow = Class.extend({
.appendTo($('<div class="col col-xs-1"></div>').appendTo(this.row))
.on('click', function() { me.toggle_view(); return false; });

if(this.row.width() < 400) {
if(this.is_too_small()) {
// narrow
this.open_form_button.css({'margin-right': '-2px'});
}


+ 5
- 5
frappe/public/js/frappe/form/link_selector.js Näytä tiedosto

@@ -99,11 +99,11 @@ frappe.ui.form.LinkSelector = Class.extend({
})
})
} else {
$('<div class="alert alert-info">' + __("No Results")
+ (frappe.model.can_read(me.doctype) ?
('. <a class="new-doc">'
+ __("Make a new") + " " + __(me.doctype) + "</a>") : '')
+ '</div>').appendTo(parent).find(".new-doc").click(function() {
$('<p><br><span class="text-muted">' + __("No Results") + '</span>'
+ (frappe.model.can_create(me.doctype) ?
('<br><br><a class="new-doc btn btn-default btn-sm">'
+ __("Make a new {0}", [__(me.doctype)]) + "</a>") : '')
+ '</p>').appendTo(parent).find(".new-doc").click(function() {
me.target.new_doc();
});
}


+ 2
- 0
frappe/public/js/frappe/form/templates/grid_body.html Näytä tiedosto

@@ -7,6 +7,8 @@
<div class="small form-clickable-section grid-footer">
<div class="row">
<div class="col-sm-6 grid-buttons">
<button type="reset" class="btn btn-xs btn-danger grid-remove-rows hide">
{%= __("Delete") %}</button>
<button type="reset"
class="grid-add-multiple-rows btn btn-xs btn-default hide"
style="margin-right: 10px;">


+ 4
- 2
frappe/public/js/frappe/model/create_new.js Näytä tiedosto

@@ -275,9 +275,11 @@ $.extend(frappe.model, {

return frappe.call({
type: "POST",
method: opts.method,
method: 'frappe.model.mapper.make_mapped_doc',
args: {
"source_name": opts.source_name
method: opts.method,
source_name: opts.source_name,
selected_children: opts.frm.get_selected()
},
freeze: true,
callback: function(r) {


+ 22
- 0
frappe/public/js/legacy/clientscriptAPI.js Näytä tiedosto

@@ -398,6 +398,28 @@ _f.Frm.prototype.get_title = function() {
}
}

_f.Frm.prototype.get_selected = function() {
// returns list of children that are selected. returns [parentfield, name] for each
var selected = {}, me = this;
frappe.meta.get_table_fields(this.doctype).forEach(function(df) {
var _selected = me.fields_dict[df.fieldname].grid.get_selected();
if(_selected.length) {
selected[df.fieldname] = _selected;
}
});
return selected;
}

_f.Frm.prototype.has_mapper = function() {
// hackalert!
// if open_mapped_doc is mentioned in the custom script, then mapper exists
if(this._has_mapper === undefined) {
this._has_mapper = (this.meta.__js && this.meta.__js.search('open_mapped_doc')!==-1) ?
true: false;
}
return this._has_mapper;
}

_f.Frm.prototype.set_indicator_formatter = function(fieldname, get_color, get_text) {
// get doctype from parent
if(frappe.meta.docfield_map[this.doctype][fieldname]) {


+ 2
- 4
frappe/tests/test_scheduler.py Näytä tiedosto

@@ -26,8 +26,7 @@ class TestScheduler(TestCase):
self.assertTrue("all" in frappe.flags.ran_schedulers)

def test_enabled_events(self):
val = json.dumps(["hourly", "hourly_long", "daily", "daily_long", "weekly", "weekly_long", "monthly", "monthly_long"])
frappe.db.set_global('enabled_scheduler_events', val)
frappe.flags.enabled_events = ["hourly", "hourly_long", "daily", "daily_long", "weekly", "weekly_long", "monthly", "monthly_long"]

# maintain last_event and next_event on the same day
last_event = now_datetime().replace(hour=0, minute=0, second=0, microsecond=0)
@@ -44,8 +43,7 @@ class TestScheduler(TestCase):
self.assertTrue("all" in frappe.flags.ran_schedulers)
self.assertTrue("hourly" in frappe.flags.ran_schedulers)

frappe.db.set_global('enabled_scheduler_events', "")

del frappe.flags['enabled_events']

def test_enabled_events_day_change(self):
val = json.dumps(["daily", "daily_long", "weekly", "weekly_long", "monthly", "monthly_long"])


+ 6
- 2
frappe/utils/scheduler.py Näytä tiedosto

@@ -144,6 +144,9 @@ def trigger(site, event, queued_jobs=(), now=False):
if not queued_jobs and not now:
queued_jobs = get_jobs(site=site, queue=queue)

if frappe.flags.in_test:
frappe.flags.ran_schedulers.append(event)

events = get_scheduler_events(event)
if not events:
return
@@ -155,8 +158,6 @@ def trigger(site, event, queued_jobs=(), now=False):
else:
scheduler_task(site=site, event=event, handler=handler, now=True)

if frappe.flags.in_test:
frappe.flags.ran_schedulers.append(event)

def get_scheduler_events(event):
'''Get scheduler events from hooks and integrations'''
@@ -193,6 +194,9 @@ def log(method, message=None):
return message

def get_enabled_scheduler_events():
if 'enabled_events' in frappe.flags:
return frappe.flags.enabled_events

enabled_events = frappe.db.get_global("enabled_scheduler_events")
if enabled_events:
if isinstance(enabled_events, basestring):


Ladataan…
Peruuta
Tallenna