[grid] added feature for bluk edit

This commit is contained in:
Rushabh Mehta 2015-02-17 16:09:52 +05:30
parent 1884c98fba
commit d7f7382ec0
14 changed files with 216 additions and 44 deletions

View file

@ -132,6 +132,7 @@
"public/js/frappe/form/save.js",
"public/js/frappe/form/script_manager.js",
"public/js/frappe/form/grid_form.html",
"public/js/frappe/form/grid_body.html",
"public/js/frappe/form/grid.js",
"public/js/frappe/form/linked_with.js",
"public/js/frappe/form/workflow.js",

View file

@ -77,6 +77,9 @@
font-size: 120%;
border-bottom: 1px solid #d1d8dd;
}
.grid-footer {
background-color: #fff;
}
.grid-footer-toolbar {
padding: 10px 15px;
border-top: 1px solid #d1d8dd;

View file

@ -735,7 +735,7 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({
this.frm.attachments.update_attachment(attachment);
} else {
this.set_input(this.fileobj.filename, this.dataurl);
this.refresh();
//this.refresh();
}
},
});

View file

@ -20,29 +20,16 @@ frappe.ui.form.Grid = Class.extend({
make: function() {
var me = this;
this.wrapper = $('<div>\
<div class="form-grid">\
<div class="grid-heading-row"></div>\
<div class="grid-body">\
<div class="rows"></div>\
<div class="grid-empty text-center hide">'+__("No Data")+'</div>\
<div class="small form-clickable-section grid-footer text-center">\
<a href="#" class="grid-add-row h6 text-muted" style="margin-left: 10px;">+ '
+__("Add new row")+'.</a>\
<a href="#" class="grid-add-multiple-rows h6 text-muted hide" style="margin-left: 10px;">+ '
+__("Add multiple rows")+'.</a>\
<div class="clearfix"></div>\
</div>\
</div>\
</div>\
</div>')
this.wrapper = $(frappe.render_template("grid_body", {}))
.appendTo(this.parent)
.attr("data-fieldname", this.df.fieldname);
$(this.wrapper).find(".grid-add-row").click(function() {
me.add_new_row(null, null, true);
return false;
})
});
this.setup_allow_bulk_edit();
},
make_head: function() {
@ -144,21 +131,6 @@ frappe.ui.form.Grid = Class.extend({
me.frm.dirty();
}
});
// $rows.sortable({
// handle: ".data-row, .grid-form-heading",
// helper: 'clone',
// update: function(event, ui) {
// me.frm.doc[me.df.fieldname] = [];
// $rows.find(".grid-row").each(function(i, item) {
// var doc = $(item).data("doc");
// doc.idx = i + 1;
// $(this).find(".row-index").html(i + 1);
// me.frm.doc[me.df.fieldname].push(doc);
// });
// me.frm.dirty();
// }
// });
},
get_data: function() {
var data = this.frm.doc[this.df.fieldname] || [];
@ -231,6 +203,68 @@ frappe.ui.form.Grid = Class.extend({
return false;
});
this.multiple_set = true;
},
setup_allow_bulk_edit: function() {
var me = this;
if(this.frm.get_docfield(this.df.fieldname).allow_bulk_edit) {
// download
me.setup_download();
// upload
$(this.wrapper).find(".grid-upload").removeClass("hide").on("click", function() {
frappe.prompt({fieldtype:"Attach", label:"Upload File"},
function(data) {
var data = frappe.utils.csv_to_array(frappe.upload.get_string(data.upload_file));
// row #2 contains fieldnames;
var fieldnames = data[2];
me.frm.clear_table(me.df.fieldname);
$.each(data, function(i, row) {
if(i > 4) {
var d = me.frm.add_child(me.df.fieldname);
$.each(row, function(ci, value) {
d[fieldnames[ci]] = value;
});
}
});
me.frm.refresh_field(me.df.fieldname);
}, __("Edit via Upload"), __("Update"));
return false;
});
}
},
setup_download: function() {
var me = this;
$(this.wrapper).find(".grid-download").removeClass("hide").on("click", function() {
var data = [];
data.push([__("Bulk Edit {0}", [me.df.label])]);
data.push([]);
data.push([]);
data.push([]);
data.push(["------"]);
$.each(frappe.get_meta(me.df.options).fields, function(i, df) {
if(frappe.model.is_value_type(me.df.fieldtype)) {
data[1].push(df.label);
data[2].push(df.fieldname);
data[3].push(df.description);
}
});
// add data
$.each(me.frm.doc[me.df.fieldname] || [], function(i, d) {
row = [];
$.each(data[2], function(i, fieldname) {
row.push(d[fieldname] || "");
});
data.push(row);
});
frappe.tools.downloadify(data, null, me.df.label);
return false;
});
}
});

View file

@ -0,0 +1,28 @@
<div>
<div class="form-grid">
<div class="grid-heading-row"></div>
<div class="grid-body">
<div class="rows"></div>
<div class="grid-empty text-center hide">{%= __("No Data") %}</div>
<div class="small form-clickable-section grid-footer">
<div class="row">
<div class="col-sm-6">
<a href="#" class="btn btn-xs btn-default grid-add-row">
{%= __("Add new row") %}</a>
<a href="#" class="grid-add-multiple-rows btn btn-xs btn-default hide"
style="margin-left: 10px;">
{%= __("Add multiple rows") %}</a>
</div>
<div class="col-sm-6 text-right">
<a href="#" class="grid-download btn btn-xs btn-default hide"
style="margin-left: 10px;">
{%= __("Download") %}</a>
<a href="#" class="grid-upload btn btn-xs btn-default hide"
style="margin-left: 10px;">
{%= __("Upload") %}</a>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -3,7 +3,7 @@
frappe.provide("frappe.tools");
frappe.tools.downloadify = function(data, roles, me) {
frappe.tools.downloadify = function(data, roles, title) {
if(roles && roles.length && !has_common(roles, user_roles)) {
msgprint(__("Export not allowed. You need {0} role to export.", [frappe.utils.comma_or(roles)]));
return;
@ -14,7 +14,7 @@ frappe.tools.downloadify = function(data, roles, me) {
var download_from_server = function() {
open_url_post("/", {
args: { data: data, filename: me.title },
args: { data: data, filename: title },
cmd: "frappe.utils.csvutils.send_csv_to_client"
}, true);
}
@ -33,7 +33,7 @@ frappe.tools.downloadify = function(data, roles, me) {
Downloadify.create(id ,{
filename: function(){
return me.title + '.csv';
return title + '.csv';
},
data: _get_data,
swf: 'assets/frappe/js/lib/downloadify/downloadify.swf',

View file

@ -320,4 +320,87 @@ frappe.utils = {
setTimeout(function() { callback(dataURL); }, 10 );
}
},
csv_to_array: function (strData, strDelimiter) {
// Check to see if the delimiter is defined. If not,
// then default to comma.
strDelimiter = (strDelimiter || ",");
// Create a regular expression to parse the CSV values.
var objPattern = new RegExp(
(
// Delimiters.
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
// Quoted fields.
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
// Standard fields.
"([^\"\\" + strDelimiter + "\\r\\n]*))"
),
"gi"
);
// Create an array to hold our data. Give the array
// a default empty first row.
var arrData = [[]];
// Create an array to hold our individual pattern
// matching groups.
var arrMatches = null;
// Keep looping over the regular expression matches
// until we can no longer find a match.
while (arrMatches = objPattern.exec( strData )){
// Get the delimiter that was found.
var strMatchedDelimiter = arrMatches[ 1 ];
// Check to see if the given delimiter has a length
// (is not the start of string) and if it matches
// field delimiter. If id does not, then we know
// that this delimiter is a row delimiter.
if (
strMatchedDelimiter.length &&
strMatchedDelimiter !== strDelimiter
){
// Since we have reached a new row of data,
// add an empty row to our data array.
arrData.push( [] );
}
var strMatchedValue;
// Now that we have our delimiter out of the way,
// let's check to see which kind of value we
// captured (quoted or unquoted).
if (arrMatches[ 2 ]){
// We found a quoted value. When we capture
// this value, unescape any double quotes.
strMatchedValue = arrMatches[ 2 ].replace(
new RegExp( "\"\"", "g" ),
"\""
);
} else {
// We found a non-quoted value.
strMatchedValue = arrMatches[ 3 ];
}
// Now that we have our value string, let's add
// it to the data array.
arrData[ arrData.length - 1 ].push( strMatchedValue );
}
// Return the parsed data.
return( arrData );
}
};

View file

@ -34,6 +34,10 @@ $.extend(frappe.model, {
new_names: {},
events: {},
is_value_type: function(fieldtype) {
return frappe.model.no_value_type.indexOf(fieldtype)!==-1;
},
get_std_field: function(fieldname) {
var docfield = $.map([].concat(frappe.model.std_fields).concat(frappe.model.std_fields_table),
function(d) {

View file

@ -34,13 +34,13 @@ frappe.confirm = function(message, ifyes, ifno) {
return d;
}
frappe.prompt = function(fields, callback) {
frappe.prompt = function(fields, callback, title, primary_label) {
if(!$.isArray(fields)) fields = [fields];
var d = new frappe.ui.Dialog({
fields: fields,
title: __("Enter Value"),
title: title || __("Enter Value"),
})
d.set_primary_action(__("Submit"), function() {
d.set_primary_action(primary_label || __("Submit"), function() {
var values = d.get_values();
if(!values) {
return;

View file

@ -116,5 +116,16 @@ frappe.upload = {
freader.readAsDataURL(fileobj);
}
},
get_string: function(dataURI) {
// remove filename
var parts = dataURI.split(',');
if(parts[0].indexOf(":")===-1) {
var a = parts[2];
} else {
var a = parts[1];
}
return atob(a);
}
}

View file

@ -444,7 +444,7 @@ frappe.views.GridReport = Class.extend({
},
export: function() {
frappe.tools.downloadify(frappe.slickgrid_tools.get_view_data(this.columns, this.dataView),
["Report Manager", "System Manager"], this);
["Report Manager", "System Manager"], this.title);
return false;
},
apply_filters: function(item) {
@ -915,7 +915,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
return false;
});
frappe.tools.downloadify(data, ["Report Manager", "System Manager"], me);
frappe.tools.downloadify(data, ["Report Manager", "System Manager"], me.title);
return false;
})

View file

@ -622,7 +622,7 @@ frappe.views.QueryReport = Class.extend({
return [row.splice(1)];
});
this.title = this.report_name;
frappe.tools.downloadify(result, null, this);
frappe.tools.downloadify(result, null, this.title);
return false;
}
})

View file

@ -146,11 +146,15 @@ _f.Frm.prototype.field_map = function(fnames, fn) {
}
}
_f.Frm.prototype.get_docfield = function(fieldname) {
return frappe.meta.get_docfield(this.doctype, fieldname, this.docname);
}
_f.Frm.prototype.set_df_property = function(fieldname, property, value) {
var field = frappe.meta.get_docfield(cur_frm.doctype, fieldname, cur_frm.docname)
var field = this.get_docfield(fieldname);
if(field) {
field[property] = value;
cur_frm.refresh_field(fieldname);
this.refresh_field(fieldname);
};
}

View file

@ -91,6 +91,10 @@
border-bottom: 1px solid @border-color;
}
.grid-footer {
background-color: #fff;
}
.grid-footer-toolbar {
padding: 10px 15px;
border-top: 1px solid @border-color;