Преглед на файлове

[cleaup] direct editing on grids

version-14
Rushabh Mehta преди 9 години
родител
ревизия
657fbc91de
променени са 6 файла, в които са добавени 277 реда и са изтрити 152 реда
  1. +10
    -5
      frappe/public/css/form_grid.css
  2. +17
    -0
      frappe/public/js/frappe/dom.js
  3. +27
    -12
      frappe/public/js/frappe/form/control.js
  4. +198
    -124
      frappe/public/js/frappe/form/grid.js
  5. +8
    -4
      frappe/public/js/frappe/model/meta.js
  6. +17
    -7
      frappe/public/less/form_grid.less

+ 10
- 5
frappe/public/css/form_grid.css Целия файл

@@ -52,21 +52,26 @@
text-align: right; text-align: right;
width: 30px; width: 30px;
margin-left: -15px; margin-left: -15px;
margin-top: 1px;
float: left; float: left;
} }
.editable-row { .editable-row {
margin-right: 15px !important; margin-right: 15px !important;
} }
.editable-row .row-index {
.editable-row .col {
padding: 0px 7.5px;
}
.grid-body .btn-open-row {
margin-top: -3px;
}
.grid-body .editable-row .row-index {
margin-top: 7px; margin-top: 7px;
} }
.editable-row .close {
.grid-body .editable-row .btn-open-row {
margin-top: 0px;
padding: 3px 7px; padding: 3px 7px;
margin-right: -20px; margin-right: -20px;
} }
.editable-row .col {
padding: 0px 7.5px;
}
.row-data > .row { .row-data > .row {
margin-left: 15px; margin-left: 15px;
} }


+ 17
- 0
frappe/public/js/frappe/dom.js Целия файл

@@ -36,6 +36,23 @@ frappe.dom = {
}); });
return div.innerHTML; return div.innerHTML;
}, },
is_element_in_viewport: function (el) {

//special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}

var rect = el.getBoundingClientRect();

return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
},

set_style: function(txt, id) { set_style: function(txt, id) {
if(!txt) return; if(!txt) return;




+ 27
- 12
frappe/public/js/frappe/form/control.js Целия файл

@@ -248,6 +248,24 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
// mandatory style on refresh // mandatory style on refresh
setup_update_on_refresh: function() { setup_update_on_refresh: function() {
var me = this; var me = this;

var make_input = function() {
if(!me.has_input) {
me.make_input();
if(me.df.on_make) {
me.df.on_make(me);
}
}
}

var update_input = function() {
if(me.doctype && me.docname) {
me.set_input(me.value);
} else {
me.set_input(me.value || null);
}
}

this.$wrapper.on("refresh", function() { this.$wrapper.on("refresh", function() {
if(me.disp_status != "None") { if(me.disp_status != "None") {
// refresh value // refresh value
@@ -259,19 +277,16 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
me.disp_area && $(me.disp_area).toggle(false); me.disp_area && $(me.disp_area).toggle(false);
$(me.input_area).toggle(true); $(me.input_area).toggle(true);
$(me.input_area).find("input").prop("disabled", false); $(me.input_area).find("input").prop("disabled", false);
if(!me.has_input) {
me.make_input();
if(me.df.on_make) {
me.df.on_make(me);
}
};
if(me.doctype && me.docname) {
me.set_input(me.value);
} else {
me.set_input(me.value || null);
}
make_input();
update_input();
} else { } else {
$(me.input_area).toggle(false);
if(me.only_input) {
// show disabled input if only_input is true
// since there is no disp_area
make_input();
update_input();
}
$(me.input_area).toggle(me.only_input ? true : false);
$(me.input_area).find("input").prop("disabled", true); $(me.input_area).find("input").prop("disabled", true);
if (me.disp_area) { if (me.disp_area) {
me.set_disp_area(); me.set_disp_area();


+ 198
- 124
frappe/public/js/frappe/form/grid.js Целия файл

@@ -13,10 +13,12 @@ frappe.ui.form.close_grid_form = function() {


frappe.ui.form.Grid = Class.extend({ frappe.ui.form.Grid = Class.extend({
init: function(opts) { init: function(opts) {
var me = this;
$.extend(this, opts); $.extend(this, opts);
this.fieldinfo = {}; this.fieldinfo = {};
this.doctype = this.df.options; this.doctype = this.df.options;
this.meta = frappe.get_meta(this.doctype); this.meta = frappe.get_meta(this.doctype);
this.fields_map = {};
this.template = null; this.template = null;
this.multiple_set = false; this.multiple_set = false;
if(this.frm.meta.__form_grid_templates if(this.frm.meta.__form_grid_templates
@@ -28,10 +30,21 @@ frappe.ui.form.Grid = Class.extend({
if(this.meta.fields.length < 4 && !has_common(['Text', 'Small Text', 'Image', if(this.meta.fields.length < 4 && !has_common(['Text', 'Small Text', 'Image',
'Text Editor', 'HTML', 'Section Break', 'Column Break'], 'Text Editor', 'HTML', 'Section Break', 'Column Break'],
$.map(this.meta.fields, function(f) { return f.fieldtype }))) { $.map(this.meta.fields, function(f) { return f.fieldtype }))) {
this.editable_rows = true;
this.on_grid_editing = true;
} }

this.is_grid = true; this.is_grid = true;
}, },

allow_on_grid_editing: function() {
if(frappe.utils.is_xs()) {
return false;
} else if(this.editable_fields) {
return true;
} else {
return this.on_grid_editing;
}
},
make: function() { make: function() {
var me = this; var me = this;


@@ -68,10 +81,6 @@ frappe.ui.form.Grid = Class.extend({
$rows = $(me.parent).find(".rows"), $rows = $(me.parent).find(".rows"),
data = this.get_data(); data = this.get_data();


if(frappe.utils.is_xs()) {
this.editable_rows = false;
}

if (this.frm && this.frm.docname) { if (this.frm && this.frm.docname) {
// use doc specific docfield object // use doc specific docfield object
this.df = frappe.meta.get_docfield(this.frm.doctype, this.df.fieldname, this.frm.docname); this.df = frappe.meta.get_docfield(this.frm.doctype, this.df.fieldname, this.frm.docname);
@@ -81,6 +90,11 @@ frappe.ui.form.Grid = Class.extend({
} }


this.docfields = frappe.meta.get_docfields(this.doctype, this.frm.docname); this.docfields = frappe.meta.get_docfields(this.doctype, this.frm.docname);

this.docfields.forEach(function(df) {
me.fields_map[df.fieldname] = df;
});

this.display_status = frappe.perm.get_field_display_status(this.df, this.frm.doc, this.display_status = frappe.perm.get_field_display_status(this.df, this.frm.doc,
this.perm); this.perm);


@@ -251,7 +265,7 @@ frappe.ui.form.Grid = Class.extend({
this.frm.script_manager.trigger(this.df.fieldname + "_add", d.doctype, d.name); this.frm.script_manager.trigger(this.df.fieldname + "_add", d.doctype, d.name);
this.refresh(); this.refresh();


if(show && !this.editable_rows) {
if(show && !this.allow_on_grid_editing()) {
if(idx) { if(idx) {
this.wrapper.find("[data-idx='"+idx+"']").data("grid_row") this.wrapper.find("[data-idx='"+idx+"']").data("grid_row")
.toggle_view(true, callback); .toggle_view(true, callback);
@@ -263,6 +277,81 @@ frappe.ui.form.Grid = Class.extend({
return d; return d;
} }
}, },

make_static_display_template: function() {
if(this.static_display_template) return;

var total_colsize = 1,
fields = this.editable_fields || this.docfields;

this.static_display_template = [];

for(var ci in fields) {
var _df = fields[ci];

// get docfield if from fieldname
df = this.fields_map[_df.fieldname];

if(!df) {
throw 'field not found: ' + _df.fieldname;
}

// map columns
if(_df.columns) {
df.colsize = _df.columns;
}

if(!df.hidden
&& (this.editable_fields || df.in_list_view)
&& this.frm.get_perm(df.permlevel, "read")
&& !in_list(frappe.model.layout_fields, df.fieldtype)) {
if(!df.colsize) {
var colsize = 2;
switch(df.fieldtype) {
case "Text":
case "Small Text":
colsize = 3;
break;
case "Check":
colsize = 1;
break;
}
df.colsize = colsize;
}

total_colsize += df.colsize
if(total_colsize > 12)
return false;
this.static_display_template.push([df, df.colsize]);
}
}

// redistribute if total-col size is less than 12
var passes = 0;
while(total_colsize < 12 && passes < 12) {
for(var i in this.static_display_template) {
var df = this.static_display_template[i][0];
var colsize = this.static_display_template[i][1];
if(colsize > 1 && colsize < 12
&& !in_list(frappe.model.std_fields_list, df.fieldname)) {

if (passes < 3 && ["Int", "Currency", "Float", "Check", "Percent"].indexOf(df.fieldtype)!==-1) {
// don't increase col size of these fields in first 3 passes
continue;
}

this.static_display_template[i][1] += 1;
total_colsize++;
}

if(total_colsize >= 12)
break;
}
passes++;
}
},


is_editable: function() { is_editable: function() {
return this.display_status=="Write" && !this.static_rows return this.display_status=="Write" && !this.static_rows
}, },
@@ -416,7 +505,9 @@ frappe.ui.form.GridRow = Class.extend({
this.wrapper = $('<div class="grid-row"></div>').appendTo(this.parent).data("grid_row", 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) this.row = $('<div class="data-row row sortable-handle"></div>').appendTo(this.wrapper)
.on("click", function() { .on("click", function() {
if(!me.grid.editable_rows) {
if(me.grid.allow_on_grid_editing() && me.grid.is_editable()) {
// pass
} else {
me.toggle_view(); me.toggle_view();
return false; return false;
} }
@@ -463,7 +554,7 @@ frappe.ui.form.GridRow = Class.extend({
this.doc = locals[this.doc.doctype][this.doc.name]; this.doc = locals[this.doc.doctype][this.doc.name];
} }
// re write columns // re write columns
this.grid.static_display_template = null;
this.static_display_template = null;
this.make_static_display(true); this.make_static_display(true);


// refersh form fields // refersh form fields
@@ -495,28 +586,32 @@ frappe.ui.form.GridRow = Class.extend({
this.add_visible_columns(); this.add_visible_columns();
} }


if(this.doc && this.grid.editable_rows) {
// remove row
if(!this.remove_row) {
this.row.addClass('editable-row');
this.remove_row = $('<a class="close pull-right">\
<span class="octicon octicon-chevron-down"</a>')
.appendTo(this.row)
.on('click', function() { me.toggle_view(); return false; });
if(this.grid.allow_on_grid_editing()) {
this.row.toggleClass('editable-row', this.grid.is_editable());
if(this.doc) {
// remove row
if(!this.remove_row) {
this.remove_row = $('<a class="close pull-right btn-open-row">\
<span class="octicon octicon-chevron-down"</a>')
.appendTo(this.row)
.on('click', function() { me.toggle_view(); return false; });
}
} }
} }



$(this.frm.wrapper).trigger("grid-row-render", [this]); $(this.frm.wrapper).trigger("grid-row-render", [this]);
}, },


add_visible_columns: function() { add_visible_columns: function() {
var me = this,
focus_set = false;
this.make_static_display_template();
for(var ci in this.static_display_template) {
var df = this.static_display_template[ci][0],
colsize = this.static_display_template[ci][1],
add_class = '',
var me = this;
this.focus_set = false;
this.grid.make_static_display_template();

for(var ci in this.grid.static_display_template) {

var df = this.grid.static_display_template[ci][0],
colsize = this.grid.static_display_template[ci][1],
txt = this.doc ? txt = this.doc ?
frappe.format(this.doc[df.fieldname], df, null, this.doc) : frappe.format(this.doc[df.fieldname], df, null, this.doc) :
__(df.label); __(df.label);
@@ -526,128 +621,105 @@ frappe.ui.form.GridRow = Class.extend({
} }


if(!this.columns[df.fieldname]) { if(!this.columns[df.fieldname]) {
if(!this.grid.editable_rows || !this.doc) {
add_class = ' grid-static-col ' +
((["Text", "Small Text"].indexOf(df.fieldtype)===-1) ?
" grid-overflow-ellipsis" : " grid-overflow-no-ellipsis");
}
add_class += (["Int", "Currency", "Float", "Percent"].indexOf(df.fieldtype)!==-1) ?
" text-right": "";

$col = $('<div class="col col-xs-'+colsize+add_class+'"></div>')
.html(txt)
.attr("data-fieldname", df.fieldname)
.data("df", df)
.appendTo(this.row)

this.columns[df.fieldname] = $col;

if(this.grid.editable_rows && this.doc) {
$col.empty();
var field = frappe.ui.form.make_control({
df: df,
parent: $col,
only_input: true,
doctype: this.doc.doctype,
docname: this.doc.name,
frm: this.grid.frm
});

// sync get_query
field.get_query = this.grid.get_field(df.fieldname).get_query;
field.refresh();
if(field.$input) {
field.$input.addClass('input-sm');
field.$input.attr('data-col-idx', ci);
field.$input.on('keydown', function(e) {
// TAB
if(e.which==9) {
// last row, last column
if(cint($(this).attr('data-col-idx')) === me.static_display_template.length-1 &&
me.doc.idx===me.frm.doc[me.grid.df.fieldname].length) {

setTimeout(function() {
me.grid.add_new_row(null, null, true);
}, 500);

}
}
});
if(!focus_set) {
field.$input.focus();
focus_set = true;
}
}
this.on_grid_fields_dict[df.fieldname] = field;
}
var column = this.make_column(df, colsize, txt, ci);
} else { } else {
var column = this.columns[df.fieldname]
// reset static value
column.static_area.html(txt);

// reset field value
if(this.on_grid_fields_dict[df.fieldname]) { if(this.on_grid_fields_dict[df.fieldname]) {
// reset
this.on_grid_fields_dict[df.fieldname].docname = this.doc.name; this.on_grid_fields_dict[df.fieldname].docname = this.doc.name;
this.on_grid_fields_dict[df.fieldname].refresh(); this.on_grid_fields_dict[df.fieldname].refresh();
} else {
// reset value
this.columns[df.fieldname].html(txt);
} }
} }


// show static for field based on
// whether grid is editable
if(this.grid.is_editable() && this.on_grid_fields_dict[df.fieldname] && this.doc) {
column.static_area.toggle(false);
column.field_area.toggle(true);
} else {
column.static_area.toggle(true);
column.field_area && column.field_area.toggle(false);
}
} }


}, },


make_static_display_template: function() {
if(this.static_display_template) return;
make_column: function(df, colsize, txt, ci) {
var me = this,
add_class = '';
if(!this.grid.allow_on_grid_editing() || !this.doc) {
add_class = ' grid-static-col ' +
((["Text", "Small Text"].indexOf(df.fieldtype)===-1) ?
" grid-overflow-ellipsis" : " grid-overflow-no-ellipsis");
}
add_class += (["Int", "Currency", "Float", "Percent"].indexOf(df.fieldtype)!==-1) ?
" text-right": "";


var total_colsize = 1;
this.static_display_template = [];
for(var ci in this.docfields) {
var df = this.docfields[ci];
if(!df.hidden && df.in_list_view && this.grid.frm.get_perm(df.permlevel, "read")
&& !in_list(frappe.model.layout_fields, df.fieldtype)) {
var colsize = 2;
switch(df.fieldtype) {
case "Text":
case "Small Text":
colsize = 3;
break;
case "Check":
colsize = 1;
break;
}
total_colsize += colsize
if(total_colsize > 12)
return false;
this.static_display_template.push([df, colsize]);
}
$col = $('<div class="col col-xs-'+colsize+add_class+'"></div>')
.attr("data-fieldname", df.fieldname)
.data("df", df)
.appendTo(this.row);

$col.field_area = $('<div class="field-area"></div>').appendTo($col).toggle(false);
$col.static_area = $('<div class="static-area"></div>').appendTo($col).html(txt);

this.columns[df.fieldname] = $col;

if(this.grid.allow_on_grid_editing() && this.doc) {
me.make_control($col.field_area, df, ci);
} }


// redistribute if total-col size is less than 12
var passes = 0;
while(total_colsize < 12 && passes < 12) {
for(var i in this.static_display_template) {
var df = this.static_display_template[i][0];
var colsize = this.static_display_template[i][1];
if(colsize > 1 && colsize < 12
&& !in_list(frappe.model.std_fields_list, df.fieldname)) {
return $col;
},


if (passes < 3 && ["Int", "Currency", "Float", "Check", "Percent"].indexOf(df.fieldtype)!==-1) {
// don't increase col size of these fields in first 3 passes
continue;
}
make_control: function(parent, df, ci) {
var me = this;
var field = frappe.ui.form.make_control({
df: df,
parent: parent,
only_input: true,
doctype: this.doc.doctype,
docname: this.doc.name,
frm: this.grid.frm
});


this.static_display_template[i][1] += 1;
total_colsize++;
// sync get_query
field.get_query = this.grid.get_field(df.fieldname).get_query;
field.refresh();
if(field.$input) {
field.$input.addClass('input-sm');
field.$input.attr('data-col-idx', ci).attr('placeholder', __(df.label));
field.$input.on('keydown', function(e) {
// TAB
if(e.which==9) {
// last row, last column
if(cint($(this).attr('data-col-idx')) === me.grid.static_display_template.length-1 &&
me.doc.idx===me.frm.doc[me.grid.df.fieldname].length) {

setTimeout(function() {
me.grid.add_new_row(null, null, true);
}, 500);
}
} }

if(total_colsize >= 12)
break;
});
if(!this.focus_set) {
setTimeout(function() {
field.$input.focus();
}, 500);
this.focus_set = true;
} }
passes++;
} }
this.on_grid_fields_dict[df.fieldname] = field;

}, },

get_open_form: function() { get_open_form: function() {
return frappe.ui.form.get_open_grid_form(); return frappe.ui.form.get_open_grid_form();
}, },

toggle_view: function(show, callback) { toggle_view: function(show, callback) {
if(!this.doc) { if(!this.doc) {
return this; return this;
@@ -693,7 +765,9 @@ frappe.ui.form.GridRow = Class.extend({
frappe.dom.freeze("", "dark"); frappe.dom.freeze("", "dark");
cur_frm.cur_grid = this; cur_frm.cur_grid = this;
this.wrapper.addClass("grid-row-open"); this.wrapper.addClass("grid-row-open");
frappe.utils.scroll_to(this.wrapper, true, 15);
if(!frappe.dom.is_element_in_viewport) {
frappe.utils.scroll_to(this.wrapper, true, 15);
}
this.frm.script_manager.trigger(this.doc.parentfield + "_on_form_rendered"); this.frm.script_manager.trigger(this.doc.parentfield + "_on_form_rendered");
this.frm.script_manager.trigger("form_render", this.doc.doctype, this.doc.name); this.frm.script_manager.trigger("form_render", this.doc.doctype, this.doc.name);
this.set_focus(); this.set_focus();
@@ -799,7 +873,7 @@ frappe.ui.form.GridRow = Class.extend({
}, },
refresh_field: function(fieldname) { refresh_field: function(fieldname) {
var $col = this.row.find("[data-fieldname='"+fieldname+"']"); var $col = this.row.find("[data-fieldname='"+fieldname+"']");
if($col.length && !this.grid.editable_rows) {
if($col.length && !this.grid.allow_on_grid_editing()) {
$col.html(frappe.format(this.doc[fieldname], this.grid.get_docfield(fieldname), $col.html(frappe.format(this.doc[fieldname], this.grid.get_docfield(fieldname),
null, this.frm.doc)); null, this.frm.doc));
} }


+ 8
- 4
frappe/public/js/frappe/model/meta.js Целия файл

@@ -52,12 +52,16 @@ $.extend(frappe.meta, {
} }
}, },


get_field: function(dt, fn, dn) {
return frappe.meta.get_docfield(dt, fn, dn);
get_field: function(doctype, fieldname, name) {
return frappe.meta.get_docfield(doctype, fieldname, name);
}, },


get_docfield: function(dt, fn, dn) {
return frappe.meta.get_docfield_copy(dt, dn)[fn];
get_docfield: function(doctype, fieldname, name) {
return frappe.meta.get_docfield_copy(doctype, name)[fieldname];
},

set_formatter: function(doctype, fieldname, name, formatter) {
frappe.meta.get_docfield(doctype, fieldname, name).formatter = formatter;
}, },


get_docfields: function(doctype, name, filters) { get_docfields: function(doctype, name, filters) {


+ 17
- 7
frappe/public/less/form_grid.less Целия файл

@@ -63,23 +63,33 @@
text-align: right; text-align: right;
width: 30px; width: 30px;
margin-left: -15px; margin-left: -15px;
margin-top: 1px;
float: left; float: left;
} }


.editable-row { .editable-row {
margin-right: 15px !important; margin-right: 15px !important;


.row-index {
margin-top: 7px;
.col {
padding: 0px 7.5px;
} }
}


.close {
padding: 3px 7px;
margin-right: -20px;
.grid-body {
.btn-open-row {
margin-top: -3px;
} }


.col {
padding: 0px 7.5px;
.editable-row {
.row-index {
margin-top: 7px;
}

.btn-open-row {
margin-top: 0px;
padding: 3px 7px;
margin-right: -20px;
}
} }
} }




Зареждане…
Отказ
Запис