add drag and drop on sao
This commit is contained in:
parent
b02beb28f4
commit
46edb19083
|
@ -0,0 +1,509 @@
|
|||
diff -r 02a9082b44d1 bower.json
|
||||
--- a/public_data/sao/bower.json Mon Jun 03 15:45:06 2019 +0200
|
||||
+++ b/public_data/sao/bower.json Tue Jun 04 12:04:17 2019 +0200
|
||||
@@ -24,7 +24,8 @@
|
||||
"papaparse": "^4.1",
|
||||
"fullcalendar": "^3.0",
|
||||
"mousetrap": "^1.6",
|
||||
- "bootstrap-rtl-ondemand": "^3.3.4-ondemand"
|
||||
+ "bootstrap-rtl-ondemand": "^3.3.4-ondemand",
|
||||
+ "Sortable": "sortablejs#^1.8.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"qunit": "^1.18"
|
||||
diff -r 02a9082b44d1 index.html
|
||||
--- a/public_data/sao/index.html Mon Jun 03 15:45:06 2019 +0200
|
||||
+++ b/public_data/sao/index.html Tue Jun 04 12:04:17 2019 +0200
|
||||
@@ -21,6 +21,7 @@
|
||||
<script type="text/javascript" src="bower_components/fullcalendar/dist/fullcalendar.min.js"></script>
|
||||
<script type="text/javascript" src="bower_components/fullcalendar/dist/locale-all.js"></script>
|
||||
<script type="text/javascript" src="bower_components/mousetrap/mousetrap.min.js"></script>
|
||||
+ <script type="text/javascript" src="bower_components/Sortable/Sortable.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="bower_components/bootstrap-rtl-ondemand/dist/css/bootstrap-rtl-ondemand.min.css">
|
||||
diff -r 02a9082b44d1 src/model.js
|
||||
--- a/public_data/sao/src/model.js Mon Jun 03 15:45:06 2019 +0200
|
||||
+++ b/public_data/sao/src/model.js Tue Jun 04 12:04:17 2019 +0200
|
||||
@@ -473,6 +473,48 @@
|
||||
};
|
||||
return jQuery.when().then(browse_child);
|
||||
};
|
||||
+ array.set_sequence = function(field) {
|
||||
+ var changed = false;
|
||||
+ var prev = null;
|
||||
+ var record, index, update, value;
|
||||
+ for (var i=0; i < this.length; i++) {
|
||||
+ record = this[i];
|
||||
+ if (record.get_loaded([field]) || changed || record.id < 0) {
|
||||
+ if (prev) {
|
||||
+ index = prev.field_get(field);
|
||||
+ } else {
|
||||
+ index = null;
|
||||
+ }
|
||||
+ update = false;
|
||||
+ value = record.field_get(field);
|
||||
+ if (value === null) {
|
||||
+ if (index) {
|
||||
+ update = true;
|
||||
+ } else if (prev && (record.id >= 0)) {
|
||||
+ update = record.id < prev.id;
|
||||
+ }
|
||||
+ } else if (value === index) {
|
||||
+ if (prev && (record.id >= 0)) {
|
||||
+ update = record.id < prev.id;
|
||||
+ }
|
||||
+ } else if (value <= (index || 0)) {
|
||||
+ update = true;
|
||||
+ }
|
||||
+ if (update) {
|
||||
+ if (index === null) {
|
||||
+ index = 0;
|
||||
+ }
|
||||
+ index += 1;
|
||||
+ record.field_set_client(field, index);
|
||||
+ changed = record;
|
||||
+ }
|
||||
+ }
|
||||
+ prev = record;
|
||||
+ }
|
||||
+ if (changed) {
|
||||
+ this.changed();
|
||||
+ }
|
||||
+ };
|
||||
return array;
|
||||
};
|
||||
|
||||
@@ -1265,6 +1307,33 @@
|
||||
path.reverse();
|
||||
return path;
|
||||
},
|
||||
+ children_group: function(field_name) {
|
||||
+ var group_prm = jQuery.Deferred();
|
||||
+ if (!field_name) {
|
||||
+ group_prm.resolve([]);
|
||||
+ return group_prm;
|
||||
+ }
|
||||
+ var load_prm = this._check_load([field_name]);
|
||||
+ load_prm.done(function() {
|
||||
+ var group = this._values[field_name];
|
||||
+ if (group === undefined) {
|
||||
+ group_prm.resolve(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (group.model.fields !== this.group.model.fields) {
|
||||
+ jQuery.extend(this.group.model.fields, group.model.fields);
|
||||
+ group.model.fields = this.group.model.fields;
|
||||
+ }
|
||||
+ group.on_write = this.group.on_write;
|
||||
+ group.readonly = this.group.readonly;
|
||||
+ jQuery.extend(group._context, this.group._context);
|
||||
+
|
||||
+ group_prm.resolve(group);
|
||||
+ return;
|
||||
+ }.bind(this));
|
||||
+ return group_prm;
|
||||
+ },
|
||||
get deleted() {
|
||||
return Boolean(~this.group.record_deleted.indexOf(this));
|
||||
},
|
||||
diff -r 02a9082b44d1 src/sao.less
|
||||
--- a/public_data/sao/src/sao.less Mon Jun 03 15:45:06 2019 +0200
|
||||
+++ b/public_data/sao/src/sao.less Tue Jun 04 12:04:17 2019 +0200
|
||||
@@ -207,10 +207,13 @@
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
|
||||
- col.selection-state, col.favorite {
|
||||
+ col.selection-state, col.favorite, col.draggable-handle {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
+ td.draggable-handle {
|
||||
+ cursor: grab;
|
||||
+ }
|
||||
th.selection-state, td.selection-state {
|
||||
> input {
|
||||
.center-block();
|
||||
@@ -239,6 +242,13 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
+ > tbody > tr.dragged-row {
|
||||
+ background-color: @state-info-bg;
|
||||
+ }
|
||||
+ > tbody > tr.children-container {
|
||||
+ min-height: @line-height-base;
|
||||
+ border: 1px dashed @gray-light;
|
||||
+ }
|
||||
|
||||
td.prefix {
|
||||
padding-right: @table-cell-padding;
|
||||
diff -r 02a9082b44d1 src/view/tree.js
|
||||
--- a/public_data/sao/src/view/tree.js Mon Jun 03 15:45:06 2019 +0200
|
||||
+++ b/public_data/sao/src/view/tree.js Tue Jun 04 12:04:17 2019 +0200
|
||||
@@ -76,6 +76,7 @@
|
||||
Sao.View.Tree = Sao.class_(Sao.View, {
|
||||
view_type: 'tree',
|
||||
xml_parser: Sao.View.TreeXMLViewParser,
|
||||
+ draggable: false,
|
||||
init: function(view_id, screen, xml, children_field) {
|
||||
this.children_field = children_field;
|
||||
this.sum_widgets = {};
|
||||
@@ -99,10 +100,10 @@
|
||||
this.table.addClass('table-bordered');
|
||||
}
|
||||
this.el.append(this.table);
|
||||
- var colgroup = jQuery('<colgroup/>').appendTo(this.table);
|
||||
+ this.colgroup = jQuery('<colgroup/>').appendTo(this.table);
|
||||
var col = jQuery('<col/>', {
|
||||
'class': 'selection-state',
|
||||
- }).appendTo(colgroup);
|
||||
+ }).appendTo(this.colgroup);
|
||||
if (this.selection_mode == Sao.common.SELECTION_NONE) {
|
||||
col.css('width', 0);
|
||||
}
|
||||
@@ -132,7 +133,7 @@
|
||||
this.columns.forEach(function(column) {
|
||||
col = jQuery('<col/>', {
|
||||
'class': column.attributes.widget,
|
||||
- }).appendTo(colgroup);
|
||||
+ }).appendTo(this.colgroup);
|
||||
th = jQuery('<th/>', {
|
||||
'class': column.attributes.widget,
|
||||
});
|
||||
@@ -183,6 +184,8 @@
|
||||
this.tbody = jQuery('<tbody/>');
|
||||
this.table.append(this.tbody);
|
||||
|
||||
+ this.set_drag_and_drop();
|
||||
+
|
||||
this.display_size = Sao.config.display_size;
|
||||
},
|
||||
get editable() {
|
||||
@@ -278,6 +281,195 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
+ _add_drag_n_drop: function() {
|
||||
+ Sortable.create(this.tbody[0], {
|
||||
+ animation: 150,
|
||||
+ handle: '.draggable-handle',
|
||||
+ ghostClass: 'dragged-row'
|
||||
+ });
|
||||
+ this.tbody.on('dragstart', this.drag_data_get.bind(this));
|
||||
+ this.tbody.on('drop', this.drag_data_received.bind(this));
|
||||
+ },
|
||||
+ set_drag_and_drop: function() {
|
||||
+ var dnd = false;
|
||||
+ var children, parent_name;
|
||||
+ if (this.children_field) {
|
||||
+ children = this.screen.model.fields[this.children_field];
|
||||
+ if (children) {
|
||||
+ parent_name = children.description.relation_field;
|
||||
+ dnd = Boolean(this.widgets[parent_name]);
|
||||
+ }
|
||||
+ } else if (this.attributes.sequence) {
|
||||
+ dnd = true;
|
||||
+ }
|
||||
+ if (this.screen.readonly) {
|
||||
+ dnd = false;
|
||||
+ }
|
||||
+
|
||||
+ this.draggable = dnd;
|
||||
+ if (dnd) {
|
||||
+ this.colgroup.prepend(jQuery('<col/>', {
|
||||
+ 'class': 'draggable-handle',
|
||||
+ }));
|
||||
+ this.thead.children().prepend(jQuery('<th/>', {
|
||||
+ 'class': 'draggable-handle',
|
||||
+ }));
|
||||
+ this._add_drag_n_drop();
|
||||
+ }
|
||||
+ },
|
||||
+ drag_data_get: function(evt) {
|
||||
+ var row_position = 0;
|
||||
+ var row_leaves = [];
|
||||
+ var set_dragged_row = function(row) {
|
||||
+ if (row.el[0] === evt.target) {
|
||||
+ evt.originalEvent.dataTransfer.setData('path', row.path);
|
||||
+ evt.originalEvent.dataTransfer.setData(
|
||||
+ 'position', row_position);
|
||||
+ }
|
||||
+ if (row.rows.length === 0) {
|
||||
+ row_leaves.push(row);
|
||||
+ }
|
||||
+ row_position += 1;
|
||||
+ row.rows.forEach(set_dragged_row.bind(this));
|
||||
+ };
|
||||
+ this.rows.forEach(set_dragged_row.bind(this));
|
||||
+
|
||||
+ if (this.children_field) {
|
||||
+ var child_row;
|
||||
+ for (var i = 0; i < row_leaves.length; i++) {
|
||||
+ child_row = jQuery('<tr/>', {
|
||||
+ 'class': 'children-container',
|
||||
+ }).append(jQuery('<td/>', {
|
||||
+ colspan: this.columns.length,
|
||||
+ }));
|
||||
+ row_leaves[i].el.after(child_row);
|
||||
+ }
|
||||
+ }
|
||||
+ },
|
||||
+ drag_data_received: function(evt) {
|
||||
+ var dataTransfer = evt.originalEvent.dataTransfer;
|
||||
+ var origin_path = dataTransfer.getData('path').split('.');
|
||||
+ if (origin_path.length === 0) {
|
||||
+ return ;
|
||||
+ }
|
||||
+
|
||||
+ var row = this;
|
||||
+ while (origin_path.length > 0) {
|
||||
+ row = row.rows[origin_path[0]];
|
||||
+ origin_path = origin_path.slice(1);
|
||||
+ }
|
||||
+
|
||||
+ var parent_row = null;
|
||||
+ var parent_tr;
|
||||
+ var next_sibling_row;
|
||||
+ var next_sibling_tr = row.el.next();
|
||||
+ if (next_sibling_tr.length === 0) {
|
||||
+ next_sibling_row = null;
|
||||
+ parent_row = null;
|
||||
+ } else if (next_sibling_tr.hasClass('children-container')) {
|
||||
+ parent_tr = row.el.prev();
|
||||
+ parent_row = this._find_row(parent_tr);
|
||||
+ next_sibling_row = null;
|
||||
+ } else {
|
||||
+ next_sibling_row = this._find_row(next_sibling_tr);
|
||||
+ parent_row = next_sibling_row.parent_;
|
||||
+ }
|
||||
+ this.tbody.find('tr.children-container').remove();
|
||||
+
|
||||
+ var current_row = parent_row;
|
||||
+ while (current_row && (current_row != row)) {
|
||||
+ current_row = current_row.parent_;
|
||||
+ }
|
||||
+ if (current_row) {
|
||||
+ // There is a recursion cancel the drop
|
||||
+ // by moving the row at its previous place
|
||||
+ var original_position = dataTransfer.getData('position');
|
||||
+ var successor = jQuery(
|
||||
+ this.tbody.children()[original_position]);
|
||||
+ successor.before(row.el);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ var previous_row = row;
|
||||
+ var move_child = function(child_row) {
|
||||
+ previous_row.el.after(child_row.el);
|
||||
+ previous_row = child_row;
|
||||
+ child_row.rows.forEach(move_child);
|
||||
+ };
|
||||
+ row.rows.forEach(move_child);
|
||||
+
|
||||
+ var dest_position, dest_group_prm;
|
||||
+ var origin_group, origin_position;
|
||||
+ origin_group = row.record.group;
|
||||
+ origin_position = row.group_position;
|
||||
+ if (parent_row) {
|
||||
+ if (next_sibling_row) {
|
||||
+ dest_position = parent_row.rows.indexOf(next_sibling_row);
|
||||
+ } else {
|
||||
+ dest_position = parent_row.rows.length;
|
||||
+ }
|
||||
+
|
||||
+ dest_group_prm = parent_row.record.children_group(
|
||||
+ this.children_field);
|
||||
+ } else {
|
||||
+ dest_group_prm = jQuery.Deferred().resolve(this.group);
|
||||
+ if (next_sibling_row) {
|
||||
+ dest_position = next_sibling_row.group_position;
|
||||
+ } else {
|
||||
+ dest_position = this.group.length;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dest_group_prm.then(function(dest_group) {
|
||||
+ var origin_rows, dest_rows;
|
||||
+ if (row.parent_) {
|
||||
+ origin_rows = row.parent_.rows;
|
||||
+ } else {
|
||||
+ origin_rows = this.rows;
|
||||
+ }
|
||||
+ if (parent_row) {
|
||||
+ dest_rows = parent_row.rows;
|
||||
+ } else {
|
||||
+ dest_rows = this.rows;
|
||||
+ }
|
||||
+
|
||||
+ if (origin_group === dest_group) {
|
||||
+ if (origin_position < dest_position) {
|
||||
+ dest_position -= 1;
|
||||
+ }
|
||||
+ origin_group.splice(origin_position, 1);
|
||||
+ origin_group.splice(dest_position, 0, row.record);
|
||||
+ origin_group.changed();
|
||||
+ } else {
|
||||
+ origin_group.remove(row.record, true, true, true);
|
||||
+ dest_group.add(row.record, dest_position);
|
||||
+ }
|
||||
+ dest_rows.splice(dest_position, 0, row);
|
||||
+ origin_rows.splice(origin_position, 1);
|
||||
+
|
||||
+ row.parent_ = parent_row;
|
||||
+ row.record.group = dest_group;
|
||||
+ dest_rows.slice(dest_position).forEach(function(r) {
|
||||
+ r.reset_path();
|
||||
+ });
|
||||
+ origin_rows.slice(origin_position).forEach(function(r) {
|
||||
+ r.reset_path();
|
||||
+ });
|
||||
+
|
||||
+ var selected = this.get_selected_paths();
|
||||
+ var expanded = this.expanded;
|
||||
+ row.redraw(selected, expanded);
|
||||
+ var child_redraw = function(child_row) {
|
||||
+ child_row.redraw(selected, expanded);
|
||||
+ child_row.rows.forEach(child_redraw);
|
||||
+ };
|
||||
+ row.rows.forEach(child_redraw);
|
||||
+
|
||||
+ if (this.attributes.sequence) {
|
||||
+ row.record.group.set_sequence(this.attributes.sequence);
|
||||
+ }
|
||||
+ }.bind(this));
|
||||
+ },
|
||||
get_fields: function() {
|
||||
return Object.keys(this.widgets);
|
||||
},
|
||||
@@ -396,7 +588,8 @@
|
||||
if (column.header.hasClass('invisible')) {
|
||||
column.col.css('width', 0);
|
||||
column.col.hide();
|
||||
- } else if (!column.col.hasClass('selection-state') &&
|
||||
+ } else if (!column.col.hasClass('draggable-handle') &&
|
||||
+ !column.col.hasClass('selection-state') &&
|
||||
!column.col.hasClass('favorite')) {
|
||||
var width = {
|
||||
'integer': 6,
|
||||
@@ -442,6 +635,9 @@
|
||||
if (!extend) {
|
||||
this.rows = [];
|
||||
this.tbody = jQuery('<tbody/>');
|
||||
+ if (this.draggable) {
|
||||
+ this._add_drag_n_drop();
|
||||
+ }
|
||||
this.edited_row = null;
|
||||
} else {
|
||||
this.tbody.find('tr.more-row').remove();
|
||||
@@ -802,6 +998,18 @@
|
||||
row.set_editable();
|
||||
}
|
||||
this.edited_row = row;
|
||||
+ },
|
||||
+ _find_row: function(tr) {
|
||||
+ var row = null;
|
||||
+ var find_row = function(r) {
|
||||
+ if (r.el[0] == tr[0]) {
|
||||
+ row = r;
|
||||
+ return;
|
||||
+ }
|
||||
+ r.rows.forEach(find_row);
|
||||
+ };
|
||||
+ this.rows.forEach(find_row);
|
||||
+ return row;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -837,15 +1045,37 @@
|
||||
this.parent_ = parent;
|
||||
this.children_field = tree.children_field;
|
||||
this.expander = null;
|
||||
- var path = [];
|
||||
- if (parent) {
|
||||
- path = jQuery.extend([], parent.path.split('.'));
|
||||
- }
|
||||
- path.push(pos);
|
||||
- this.path = path.join('.');
|
||||
+ this._group_position = null;
|
||||
+ this._path = null;
|
||||
this.el = jQuery('<tr/>');
|
||||
this.el.on('click', this.select_row.bind(this));
|
||||
},
|
||||
+ get group_position() {
|
||||
+ if (this._group_position === null) {
|
||||
+ this._group_position = this.record.group.indexOf(this.record);
|
||||
+ }
|
||||
+ return this._group_position;
|
||||
+ },
|
||||
+ get path() {
|
||||
+ if (!this._path) {
|
||||
+ var path, position;
|
||||
+ if (this.parent_) {
|
||||
+ path = jQuery.extend([], this.parent_.path.split('.'));
|
||||
+ } else {
|
||||
+ path = [];
|
||||
+ }
|
||||
+ path.push(this.group_position);
|
||||
+ this._path = path.join('.');
|
||||
+ }
|
||||
+ return this._path;
|
||||
+ },
|
||||
+ reset_path: function() {
|
||||
+ this._group_position = null;
|
||||
+ this._path = null;
|
||||
+ for (var i=0; i < this.rows.length; i++) {
|
||||
+ this.rows[i].reset_path();
|
||||
+ }
|
||||
+ },
|
||||
is_expanded: function() {
|
||||
return (this.path in this.tree.expanded);
|
||||
},
|
||||
@@ -875,8 +1105,15 @@
|
||||
el_node.removeChild(el_node.firstChild);
|
||||
}
|
||||
|
||||
- var td;
|
||||
+ var td, drag_img;
|
||||
this.tree.el.uniqueId();
|
||||
+ if (this.tree.draggable) {
|
||||
+ td = jQuery('<td/>', {
|
||||
+ 'class': 'draggable-handle'
|
||||
+ });
|
||||
+ td.append(Sao.common.ICONFACTORY.get_icon_img('tryton-drag'));
|
||||
+ this.el.append(td);
|
||||
+ }
|
||||
td = jQuery('<td/>', {
|
||||
'class': 'selection-state',
|
||||
}).click(function(event_) {
|
||||
@@ -971,7 +1208,11 @@
|
||||
},
|
||||
_get_column_td: function(column_index, row) {
|
||||
row = row || this.el;
|
||||
- return jQuery(row.children()[column_index + 1]);
|
||||
+ var offset = 1; // take into account the selection column
|
||||
+ if (this.tree.draggable) {
|
||||
+ offset += 1;
|
||||
+ }
|
||||
+ return jQuery(row.children()[column_index + offset]);
|
||||
},
|
||||
redraw: function(selected, expanded) {
|
||||
selected = selected || [];
|
||||
@@ -993,6 +1234,15 @@
|
||||
}
|
||||
|
||||
|
||||
+ if (this.children_field) {
|
||||
+ var depth = this.path.split('.').length;
|
||||
+ var margin = 'margin-left';
|
||||
+ if (Sao.i18n.rtl) {
|
||||
+ margin = 'margin-right';
|
||||
+ }
|
||||
+ this.expander.css(margin, (depth - 1) + 'em');
|
||||
+ }
|
||||
+
|
||||
for (var i = 0; i < this.tree.columns.length; i++) {
|
||||
var column = this.tree.columns[i];
|
||||
var td = this._get_column_td(i);
|
4
series
4
series
|
@ -25,3 +25,7 @@ issue10467.diff # [stock_lot] add lot to grouping when assign try if lot it's re
|
|||
party_identifier_migration.diff # [Party] avoid errors on upgrades
|
||||
|
||||
# TODO: improve_performance_on_try_assign.diff # [stock] change browse of product to get default_uom to pysql
|
||||
|
||||
# Sao
|
||||
|
||||
issue8240.diff # Add drag and drop support to sao
|
||||
|
|
Loading…
Reference in New Issue