diff --git a/src/common.js b/src/common.js
index b0af48f51c..598903ed20 100644
--- a/src/common.js
+++ b/src/common.js
@@ -1684,4 +1684,60 @@
});
Sao.common.ICONFACTORY = new Sao.common.IconFactory();
+
+ Sao.common.UniqueDialog = Sao.class_(Object, {
+ init: function() {
+ this.running = false;
+ },
+ build_dialog: function() {
+ },
+ run: function() {
+ if (this.running) {
+ return;
+ }
+ var args = Array.slice(arguments);
+ var prm = jQuery.Deferred();
+ args.push(prm);
+ var dialog = this.build_dialog.apply(this, args);
+ this.running = true;
+ dialog.dialog('open');
+ return prm;
+ },
+ close: function(dialog) {
+ dialog.dialog('close');
+ this.running = false;
+ }
+ });
+
+ Sao.common.MessageDialog = Sao.class_(Sao.common.UniqueDialog, {
+ class_: 'message-dialog',
+ build_dialog: function(message, icon, prm) {
+ var dialog = jQuery('
', {
+ 'class': this.class_
+ });
+ dialog.append(jQuery('')
+ .text(message)
+ .prepend(jQuery('', {
+ 'class': 'dialog-icon'
+ }).append(jQuery('', {
+ 'class': 'ui-icon ' + icon
+ }))));
+ dialog.dialog({
+ modal: true,
+ autoOpen: false,
+ buttons: {
+ 'OK': function() {
+ this.close(dialog);
+ prm.resolve('ok');
+ }.bind(this)
+ }
+ });
+ return dialog;
+ },
+ run: function(message, icon) {
+ Sao.common.MessageDialog._super.run.call(
+ this, message, icon || 'ui-icon-info');
+ }
+ });
+ Sao.common.message = new Sao.common.MessageDialog();
}());
diff --git a/src/model.js b/src/model.js
index 2ac6691a0b..5787abc26c 100644
--- a/src/model.js
+++ b/src/model.js
@@ -57,6 +57,15 @@
});
// TODO reload ids
return this.execute('delete', [record_ids], context);
+ },
+ copy: function(records, context) {
+ if (jQuery.isEmptyObject(records)) {
+ return jQuery.when();
+ }
+ var record_ids = records.map(function(record) {
+ return record.id;
+ });
+ return this.execute('copy', [record_ids, {}], context);
}
});
diff --git a/src/sao.less b/src/sao.less
index ae0d6a2e02..54468831ea 100644
--- a/src/sao.less
+++ b/src/sao.less
@@ -31,6 +31,18 @@ body {
padding: @medium-padding @small-padding;
}
+.tab-title-bar {
+ padding: @medium-padding @medium-padding;
+}
+
+.tab-title .ui-button-text {
+ font-size: @large-font-size;
+}
+
+.tab-status, .tab-info {
+ float: right;
+}
+
.treeview {
& > table.tree {
width: 100%;
@@ -110,3 +122,13 @@ button {
background-size: 16px 16px;
}
}
+
+.message-dialog {
+ & .dialog-icon {
+ display: table-cell;
+ }
+ & p {
+ display: table;
+ white-space: pre;
+ }
+}
diff --git a/src/screen.js b/src/screen.js
index 448a4959e6..69f7294dfd 100644
--- a/src/screen.js
+++ b/src/screen.js
@@ -491,7 +491,6 @@
});
},
remove: function(delete_, remove, force_remove) {
- var result = jQuery.Deferred();
var records = null;
if ((this.current_view.view_type == 'form') &&
this.current_record) {
@@ -507,7 +506,7 @@
// TODO delete children before parent
prm = this.model.delete_(records);
}
- prm.done(function() {
+ return prm.then(function() {
records.forEach(function(record) {
record.group.remove(record, remove, true, force_remove);
});
@@ -531,12 +530,20 @@
// TODO set current_record
this.set_current_record(null);
// TODO set_cursor
- jQuery.when.apply(jQuery, prms).done(function() {
+ return jQuery.when.apply(jQuery, prms).then(function() {
this.display();
- result.resolve();
}.bind(this));
}.bind(this));
- return result;
+ },
+ copy: function() {
+ var records = this.current_view.selected_records();
+ return this.model.copy(records, this.context).then(function(new_ids) {
+ this.group.load(new_ids);
+ if (!jQuery.isEmptyObject(new_ids)) {
+ this.set_current_record(this.group.get(new_ids[0]));
+ }
+ this.display();
+ }.bind(this));
},
search_active: function(active) {
if (active && !this.group.parent) {
diff --git a/src/tab.js b/src/tab.js
index 3dffbb2dd1..ed4fd2ef1f 100644
--- a/src/tab.js
+++ b/src/tab.js
@@ -7,6 +7,78 @@
init: function() {
this.buttons = {};
},
+ create_tabcontent: function() {
+ this.el = jQuery('', {
+ 'class': this.class_
+ });
+
+ var title = this.make_title_bar();
+ this.el.append(title);
+
+ var toolbar = this.create_toolbar();
+ this.el.append(toolbar);
+ },
+ make_title_bar: function() {
+ var title = jQuery('', {
+ 'class': 'tab-title-bar ui-widget-header ui-corner-all'
+ });
+
+ var menu = this.set_menu();
+ title.append(menu);
+ title.append(jQuery('', {
+ 'class': 'tab-title'
+ }).button({
+ label: this.name,
+ text: true,
+ icons: {
+ primary: 'ui-icon-triangle-1-s'
+ }
+ }).click(function() {
+ menu.toggle().position({
+ my: 'left top',
+ at: 'left bottom',
+ of: jQuery(this)
+ });
+ // Bind hide after the processing of the current click
+ window.setTimeout(function() {
+ jQuery(document).one('click', function() {
+ menu.hide();
+ });
+ }, 0);
+ }));
+
+ this.status = jQuery('', {
+ 'class': 'tab-status'
+ });
+ title.append(this.status);
+
+ this.info = jQuery('', {
+ 'class': 'tab-info'
+ });
+ title.append(this.info);
+ return title;
+ },
+ set_menu: function() {
+ var menu = jQuery('');
+ this.menu_def.forEach(function(definition) {
+ var icon = definition[0];
+ var name = definition[1];
+ var func = definition[2];
+ var item = jQuery('').append(
+ jQuery('').append(jQuery('', {
+ 'class': 'ui-icon ' + icon
+ })).append(name));
+ menu.append(item);
+ item.click(function() {
+ this[func]();
+ }.bind(this));
+ }.bind(this));
+ menu.menu({}).hide().css({
+ position: 'absolute',
+ 'z-index': 100
+ });
+ return menu;
+ },
create_toolbar: function() {
var toolbar = jQuery('', {
'class': 'ui-widget-header ui-corner-all'
@@ -30,6 +102,14 @@
};
this.toolbar_def.forEach(add_button.bind(this));
return toolbar;
+ },
+ close: function() {
+ var tabs = jQuery('#tabs > div');
+ // TODO check modified
+ tabs.tabs('remove', this.id);
+ if (!tabs.find('> ul').children().length) {
+ tabs.remove();
+ }
}
});
@@ -63,11 +143,7 @@
jQuery(this).css('cursor', 'default');
})
.click(function() {
- // TODO check modified
- tabs.tabs('remove', tab.id);
- if (!tabs.find('> ul').children().length) {
- tabs.remove();
- }
+ tab.close();
}));
jQuery(tab.id).html(tab.el);
tabs.tabs('select', tab.id);
@@ -75,6 +151,7 @@
};
Sao.Tab.Form = Sao.class_(Sao.Tab, {
+ class_: 'tab-form',
init: function(model_name, attributes) {
Sao.Tab.Form._super.init.call(this);
var screen = new Sao.Screen(model_name, attributes);
@@ -82,12 +159,8 @@
this.screen = screen;
this.attributes = jQuery.extend({}, attributes);
this.name = attributes.name; // XXX use screen current view title
- var el = jQuery('', {
- 'class': 'tab-form'
- });
- // TODO title
- var toolbar = this.create_toolbar();
- el.append(toolbar);
+
+ this.create_tabcontent();
var access = Sao.common.MODELACCESS.get(model_name);
[['new', 'create'], ['save', 'write']].forEach(function(e) {
@@ -96,11 +169,10 @@
this.buttons[button].prop('disabled', !access[access_type]);
}.bind(this));
- this.el = el;
this.view_prm = this.screen.switch_view().done(function() {
- el.append(screen.screen_container.el);
+ this.el.append(screen.screen_container.el);
screen.search_filter();
- });
+ }.bind(this));
},
// TODO translate labels
toolbar_def: [
@@ -115,6 +187,23 @@
['attach', 'ui-icon-pin-w', 'Attachment',
'Add an attachment to the record', 'attach']
],
+ menu_def: [
+ ['ui-icon-document', 'New', 'new_'],
+ ['ui-icon-disk', 'Save', 'save'],
+ ['ui-icon-arrow-4-diag', 'Switch', 'switch_'],
+ ['ui-icon-refresh', 'Reload/Undo', 'reload'],
+ ['ui-icon-copy', 'Duplicate', 'copy'],
+ ['ui-icon-trash', 'Delete', 'delete_'],
+ ['ui-icon-arrowthick-1-w', 'Previous', 'previous'],
+ ['ui-icon-arrowthick-1-e', 'Next', 'next'],
+ ['ui-icon-search', 'Search', 'search'],
+ ['ui-icon-clock', 'View Logs', 'logs'],
+ ['ui-icon-circle-close', 'Close Tab', 'close'],
+ ['ui-icon-pin-w', 'Attachment', 'attach'],
+ ['ui-icon-gear', 'Action', 'action'],
+ ['ui-icon-arrowreturn-1-e', 'Relate', 'relate'],
+ ['ui-icon-print', 'Print', 'print']
+ ],
create_toolbar: function() {
var toolbar = Sao.Tab.Form._super.create_toolbar.call(this);
var screen = this.screen;
@@ -131,7 +220,7 @@
].forEach(function(menu_action) {
var button = jQuery('').button({
id: menu_action[0],
- text: menu_action[2],
+ text: true,
icons: {
primary: menu_action[1],
secondary: 'ui-icon-triangle-1-s'
@@ -140,19 +229,19 @@
});
buttons[menu_action[0]] = button;
toolbar.append(button);
- var menu = jQuery('').menu({}).hide().css({
- position: 'absolute'
- });
+ var menu = jQuery('');
button.click(function() {
menu.toggle().position({
my: 'left top',
at: 'left bottom',
of: button
});
- jQuery(document).one('click', function() {
- menu.hide();
- });
- return false;
+ // Bind hide after the processing of the current click
+ window.setTimeout(function() {
+ jQuery(document).one('click', function() {
+ menu.hide();
+ });
+ }, 0);
});
toolbars[menu_action[0]].forEach(function(action) {
@@ -173,6 +262,10 @@
screen.context);
});
});
+ menu.menu({}).hide().css({
+ position: 'absolute',
+ 'z-index': 100
+ });
toolbar.append(menu);
});
});
@@ -227,6 +320,25 @@
// TODO activate_save
}.bind(this));
},
+ copy: function() {
+ if (!Sao.common.MODELACCESS.get(this.screen.model_name).create) {
+ return;
+ }
+ if (!this.modified_save()) {
+ return;
+ }
+ this.screen.copy();
+ // TODO message
+ },
+ delete_: function() {
+ if (!Sao.common.MODELACCESS.get(this.screen.model_name)['delete']) {
+ return;
+ }
+ // TODO popup
+ this.screen.remove(true, false, true).done(function() {
+ // TODO message
+ });
+ },
previous: function() {
if (!this.modified_save()) {
return;
@@ -241,6 +353,53 @@
this.screen.display_next();
// TODO message and activate_save
},
+ search: function() {
+ var search_entry = this.screen.screen_container.search_entry;
+ if (search_entry.is(':visible')) {
+ window.setTimeout(function() {
+ search_entry.focus();
+ }, 0);
+ }
+ },
+ logs: function() {
+ var record = this.screen.current_record;
+ if ((!record) || (record.id < 0)) {
+ // TODO message
+ return;
+ }
+ // TODO translation
+ var fields = [
+ ['id', 'ID:'],
+ ['create_uid.rec_name', 'Creation User:'],
+ ['create_date', 'Creation Date:'],
+ ['write_uid.rec_name', 'Latest Modification by:'],
+ ['write_date', 'Latest Modification Date:']
+ ];
+
+ this.screen.model.execute('read', [[record.id],
+ fields.map(function(field) {
+ return field[0];
+ })], this.screen.context)
+ .then(function(result) {
+ result = result[0];
+ var message = '';
+ fields.forEach(function(field) {
+ var key = field[0];
+ var label = field[1];
+ var value = result[key] || '/';
+ if (result[key] &&
+ ~['create_date', 'write_date'].indexOf(key)) {
+ value = Sao.common.format_datetime(
+ Sao.common.date_format(),
+ '%H:%M:%S',
+ value);
+ }
+ message += label + ' ' + value + '\n';
+ });
+ message += 'Model: ' + this.screen.model.name;
+ Sao.common.message.run(message);
+ }.bind(this));
+ },
attach: function() {
var record = this.screen.current_record;
if (!record || (record.id < 0)) {
@@ -274,6 +433,15 @@
var record_id = this.screen.get_id();
this.buttons.attach.prop('disabled',
record_id < 0 || record_id === null);
+ },
+ action: function() {
+ this.buttons.action.click();
+ },
+ relate: function() {
+ this.buttons.relate.click();
+ },
+ print: function() {
+ this.buttons.print.click();
}
});
}());