Instead of always calling save_current on the screen, it is better to call save when the record has been modified. This allows to get message information about failure or success but only if the record needed to be saved. issue7430 review38231002
1082 lines
42 KiB
JavaScript
1082 lines
42 KiB
JavaScript
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
this repository contains the full copyright notices and license terms. */
|
|
(function() {
|
|
'use strict';
|
|
|
|
Sao.Tab = Sao.class_(Object, {
|
|
init: function() {
|
|
Sao.Tab.tabs.push(this);
|
|
this.buttons = {};
|
|
this.menu_buttons = {};
|
|
this.id = 'tab-' + Sao.Tab.counter++;
|
|
this.name = '';
|
|
this.name_el = jQuery('<span/>');
|
|
this.view_prm = jQuery.when();
|
|
},
|
|
menu_def: function() {
|
|
return [
|
|
{
|
|
id: 'switch_',
|
|
icon: 'glyphicon-list-alt',
|
|
label: Sao.i18n.gettext('Switch'),
|
|
tooltip: Sao.i18n.gettext('Switch view'),
|
|
}, {
|
|
id: 'previous',
|
|
icon: 'glyphicon-chevron-left',
|
|
label: Sao.i18n.gettext('Previous'),
|
|
tooltip: Sao.i18n.gettext('Previous Record')
|
|
}, {
|
|
id: 'next',
|
|
icon: 'glyphicon-chevron-right',
|
|
label: Sao.i18n.gettext('Next'),
|
|
tooltip: Sao.i18n.gettext('Next Record'),
|
|
}, {
|
|
id: 'search',
|
|
icon: 'glyphicon-search',
|
|
label: Sao.i18n.gettext('Search'),
|
|
}, null, {
|
|
id: 'new_',
|
|
icon: 'glyphicon-edit',
|
|
label: Sao.i18n.gettext('New'),
|
|
tooltip: Sao.i18n.gettext('Create a new record'),
|
|
}, {
|
|
id: 'save',
|
|
icon: 'glyphicon-save',
|
|
label: Sao.i18n.gettext('Save'),
|
|
tooltip: Sao.i18n.gettext('Save this record'),
|
|
}, {
|
|
id: 'reload',
|
|
icon: 'glyphicon-refresh',
|
|
label: Sao.i18n.gettext('Reload/Undo'),
|
|
tooltip: Sao.i18n.gettext('Reload'),
|
|
}, {
|
|
id: 'copy',
|
|
icon: 'glyphicon-duplicate',
|
|
label: Sao.i18n.gettext('Duplicate'),
|
|
}, {
|
|
id: 'delete_',
|
|
icon: 'glyphicon-trash',
|
|
label: Sao.i18n.gettext('Delete'),
|
|
}, null, {
|
|
id: 'logs',
|
|
icon: 'glyphicon-time',
|
|
label: Sao.i18n.gettext('View Logs...'),
|
|
}, {
|
|
id: (this.screen &&
|
|
Sao.common.MODELHISTORY.contains(this.screen.model_name)) ?
|
|
'revision': null,
|
|
icon: 'glyphicon-time',
|
|
label: Sao.i18n.gettext('Show revisions...'),
|
|
}, null, {
|
|
id: 'attach',
|
|
icon: 'glyphicon-paperclip',
|
|
label: Sao.i18n.gettext('Attachment'),
|
|
tooltip: Sao.i18n.gettext('Add an attachment to the record'),
|
|
}, {
|
|
id: 'note',
|
|
icon: 'glyphicon-comment',
|
|
label: Sao.i18n.gettext('Note'),
|
|
tooltip: Sao.i18n.gettext('Add a note to the record'),
|
|
}, {
|
|
id: 'action',
|
|
icon: 'glyphicon-cog',
|
|
label: Sao.i18n.gettext('Action'),
|
|
}, null, {
|
|
id: 'relate',
|
|
icon: 'glyphicon-share-alt',
|
|
label: Sao.i18n.gettext('Relate'),
|
|
}, {
|
|
id: 'print',
|
|
icon: 'glyphicon-print',
|
|
label: Sao.i18n.gettext('Print'),
|
|
}, null, {
|
|
id: 'export',
|
|
icon: 'glyphicon-export',
|
|
label: Sao.i18n.gettext('Export'),
|
|
}, {
|
|
id: 'import',
|
|
icon: 'glyphicon-import',
|
|
label: Sao.i18n.gettext('Import'),
|
|
}, null, {
|
|
id: 'close',
|
|
icon: 'glyphicon-remove',
|
|
label: Sao.i18n.gettext('Close Tab'),
|
|
},
|
|
];
|
|
},
|
|
create_tabcontent: function() {
|
|
this.el = jQuery('<div/>', {
|
|
'class': this.class_
|
|
});
|
|
|
|
var toolbar = this.create_toolbar().appendTo(this.el);
|
|
this.title = toolbar.find('.title');
|
|
|
|
this.content = jQuery('<div/>').appendTo(this.el);
|
|
|
|
if (this.info_bar) {
|
|
this.el.append(this.info_bar.el);
|
|
}
|
|
},
|
|
set_menu: function(menu) {
|
|
var previous;
|
|
this.menu_def().forEach(function(item) {
|
|
var menuitem;
|
|
if (item) {
|
|
if (!this[item.id]) {
|
|
return;
|
|
}
|
|
menuitem = jQuery('<li/>', {
|
|
'role': 'presentation'
|
|
});
|
|
var link = jQuery('<a/>', {
|
|
'id': item.id,
|
|
'role': 'menuitem',
|
|
'href': '#',
|
|
'tabindex': -1
|
|
}).append(jQuery('<span/>', {
|
|
'class': 'glyphicon ' + item.icon,
|
|
'aria-hidden': 'true'
|
|
})).append(' ' + item.label).appendTo(menuitem);
|
|
this.menu_buttons[item.id] = menuitem;
|
|
link.click(function() {
|
|
this[item.id]();
|
|
}.bind(this));
|
|
} else if (!item && previous) {
|
|
menuitem = jQuery('<li/>', {
|
|
'role': 'separator',
|
|
'class': 'divider hidden-xs',
|
|
});
|
|
} else {
|
|
return;
|
|
}
|
|
previous = menuitem;
|
|
menuitem.appendTo(menu);
|
|
}.bind(this));
|
|
},
|
|
create_toolbar: function() {
|
|
var toolbar = jQuery('<nav/>', {
|
|
'class': 'toolbar navbar navbar-default',
|
|
'role': 'toolbar'
|
|
}).append(jQuery('<div/>', {
|
|
'class': 'container-fluid'
|
|
}).append(jQuery('<div/>', {
|
|
'class': 'dropdown navbar-header navbar-left'
|
|
}).append(jQuery('<a/>', {
|
|
'href': "#",
|
|
'class': "navbar-brand dropdown-toggle",
|
|
'data-toggle': 'dropdown',
|
|
'role': 'button',
|
|
'aria-expanded': false,
|
|
'aria-haspopup': true
|
|
}).append(jQuery('<span/>', {
|
|
'class': 'title'
|
|
})).append(jQuery('<span/>', {
|
|
'class': 'caret'
|
|
}))).append(jQuery('<ul/>', {
|
|
'class': 'dropdown-menu',
|
|
'role': 'menu'
|
|
})).append(jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'close visible-xs visible-sm',
|
|
'aria-label': Sao.i18n.gettext('Close')
|
|
}).append(jQuery('<span/>', {
|
|
'aria-hidden': true
|
|
}).append('×')).click(function() {
|
|
this.close();
|
|
}.bind(this)))).append(jQuery('<div/>', {
|
|
'class': 'btn-toolbar navbar-right',
|
|
'role': 'toolbar'
|
|
})));
|
|
var wrapper = jQuery('<div/>', {
|
|
'class': 'toolbar-wrapper'
|
|
}).append(toolbar);
|
|
this.set_menu(toolbar.find('ul[role*="menu"]'));
|
|
|
|
var group;
|
|
var add_button = function(item) {
|
|
if (!item || !item.tooltip) {
|
|
group = null;
|
|
return;
|
|
}
|
|
if (!item.id || !this[item.id]) {
|
|
return;
|
|
}
|
|
if (!group) {
|
|
group = jQuery('<div/>', {
|
|
'class': 'btn-group',
|
|
'role': 'group'
|
|
}).appendTo(toolbar.find('.btn-toolbar'));
|
|
}
|
|
this.buttons[item.id] = jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'btn btn-default navbar-btn',
|
|
'title': item.label,
|
|
'id': item.id
|
|
})
|
|
.append(jQuery('<span/>', {
|
|
'class': 'glyphicon ' + item.icon,
|
|
'aria-hidden': 'true'
|
|
}))
|
|
.appendTo(group);
|
|
this.buttons[item.id].click(item, function(event) {
|
|
var item = event.data;
|
|
var button = this.buttons[item.id];
|
|
button.prop('disabled', true);
|
|
(this[item.id](this) || jQuery.when())
|
|
.always(function() {
|
|
button.prop('disabled', false);
|
|
});
|
|
}.bind(this));
|
|
};
|
|
this.menu_def().forEach(add_button.bind(this));
|
|
this.status_label = jQuery('<span/>', {
|
|
'class': 'badge',
|
|
}).appendTo(jQuery('<div/>', {
|
|
'class': 'navbar-text hidden-xs',
|
|
}).insertAfter(this.buttons.previous));
|
|
toolbar.find('.btn-toolbar > .btn-group').last().addClass(
|
|
'hidden-xs');
|
|
var tabs = jQuery('#tabs');
|
|
toolbar.affix({
|
|
'target': tabs.parent(),
|
|
'offset': {
|
|
'top': function() {
|
|
return jQuery('#main_navbar').height();
|
|
}
|
|
}
|
|
});
|
|
toolbar.on('affix.bs.affix', function() {
|
|
wrapper.height(jQuery('#main_navbar').height());
|
|
});
|
|
toolbar.on('affix-top.bs.affix affix-bottom.bs.affix',
|
|
function() {
|
|
wrapper.height('');
|
|
});
|
|
toolbar.on('affixed.bs.affix', function() {
|
|
Sao.Tab.affix_set_with(toolbar);
|
|
});
|
|
toolbar.on('affixed-top.bs.affix affixed-bottom.bs.affix',
|
|
function() {
|
|
Sao.Tab.affix_unset_width(toolbar);
|
|
});
|
|
return wrapper;
|
|
},
|
|
show: function() {
|
|
jQuery('#tablist').find('a[href="#' + this.id + '"]').tab('show');
|
|
},
|
|
close: function() {
|
|
var tabs = jQuery('#tabs');
|
|
var tablist = jQuery('#tablist');
|
|
var tab = tablist.find('#nav-' + this.id);
|
|
var content = tabs.find('#' + this.id);
|
|
this.show();
|
|
return this._close_allowed().then(function() {
|
|
var next = tab.nextAll('li').first();
|
|
if (!next.length) {
|
|
next = tab.prevAll('li').first();
|
|
}
|
|
tab.remove();
|
|
content.remove();
|
|
Sao.Tab.tabs.splice(Sao.Tab.tabs.indexOf(this), 1);
|
|
if (next.length) {
|
|
next.find('a').tab('show');
|
|
} else {
|
|
Sao.set_url();
|
|
}
|
|
tabs.trigger('ready');
|
|
}.bind(this));
|
|
},
|
|
_close_allowed: function() {
|
|
return jQuery.when();
|
|
},
|
|
set_name: function(name) {
|
|
this.name = name;
|
|
this.name_el.text(Sao.common.ellipsize(name, 20));
|
|
this.name_el.parents('li').first().attr('title', name);
|
|
},
|
|
get_url: function() {
|
|
},
|
|
});
|
|
|
|
Sao.Tab.affix_set_with = function(toolbar) {
|
|
var width = jQuery(toolbar.parent()).width();
|
|
toolbar.css('width', width);
|
|
};
|
|
Sao.Tab.affix_unset_width = function(toolbar) {
|
|
toolbar.css('width', '');
|
|
};
|
|
jQuery(window).resize(function() {
|
|
jQuery('.toolbar').each(function(i, toolbar) {
|
|
toolbar = jQuery(toolbar);
|
|
toolbar.affix('checkPosition');
|
|
if (toolbar.hasClass('affix')) {
|
|
Sao.Tab.affix_set_with(toolbar);
|
|
} else {
|
|
Sao.Tab.affix_unset_width(toolbar);
|
|
}
|
|
});
|
|
});
|
|
|
|
Sao.Tab.counter = 0;
|
|
Sao.Tab.tabs = [];
|
|
Sao.Tab.tabs.close = function(warning) {
|
|
if (warning && Sao.Tab.tabs.length) {
|
|
return Sao.common.sur.run(
|
|
Sao.i18n.gettext(
|
|
'The following action requires to close all tabs.\n' +
|
|
'Do you want to continue?')).then(function() {
|
|
return Sao.Tab.tabs.close(false);
|
|
});
|
|
}
|
|
if (Sao.Tab.tabs.length) {
|
|
var tab = Sao.Tab.tabs[0];
|
|
return tab.close().then(function() {
|
|
if (!~Sao.Tab.tabs.indexOf(tab)) {
|
|
return Sao.Tab.tabs.close();
|
|
} else {
|
|
return jQuery.Deferred().reject();
|
|
}
|
|
});
|
|
}
|
|
if (Sao.main_menu_screen) {
|
|
return Sao.main_menu_screen.save_tree_state().then(function() {
|
|
Sao.main_menu_screen = null;
|
|
});
|
|
}
|
|
return jQuery.when();
|
|
};
|
|
Sao.Tab.tabs.get_current = function() {
|
|
var tabs = jQuery('#tablist');
|
|
var i = tabs.find('li').index(tabs.find('li.active'));
|
|
return Sao.Tab.tabs[i];
|
|
};
|
|
Sao.Tab.tabs.close_current = function() {
|
|
var tab = this.get_current();
|
|
tab.close();
|
|
};
|
|
|
|
Sao.Tab.create = function(attributes) {
|
|
if (attributes.context === undefined) {
|
|
attributes.context = {};
|
|
}
|
|
var tab;
|
|
if (attributes.model) {
|
|
tab = new Sao.Tab.Form(attributes.model, attributes);
|
|
} else {
|
|
tab = new Sao.Tab.Board(attributes);
|
|
}
|
|
tab.view_prm.done(function() {
|
|
Sao.Tab.add(tab);
|
|
});
|
|
};
|
|
|
|
Sao.Tab.add = function(tab) {
|
|
var tabs = jQuery('#tabs');
|
|
var tablist = jQuery('#tablist');
|
|
var tabcontent = jQuery('#tabcontent');
|
|
var tab_link = jQuery('<a/>', {
|
|
'aria-controls': tab.id,
|
|
'role': 'tab',
|
|
'data-toggle': 'tab',
|
|
'href': '#' + tab.id
|
|
}).on('show.bs.tab', function() {
|
|
Sao.set_url(tab.get_url(), tab.name);
|
|
})
|
|
.append(jQuery('<button/>', {
|
|
'class': 'close'
|
|
}).append(jQuery('<span/>', {
|
|
'aria-hidden': true
|
|
}).append('×')).append(jQuery('<span/>', {
|
|
'class': 'sr-only'
|
|
}).append(Sao.i18n.gettext('Close'))).click(function() {
|
|
tab.close();
|
|
}))
|
|
.append(tab.name_el);
|
|
jQuery('<li/>', {
|
|
'role': 'presentation',
|
|
'data-placement': 'bottom',
|
|
id: 'nav-' + tab.id
|
|
}).append(tab_link)
|
|
.appendTo(tablist);
|
|
jQuery('<div/>', {
|
|
role: 'tabpanel',
|
|
'class': 'tab-pane',
|
|
id: tab.id
|
|
}).html(tab.el)
|
|
.appendTo(tabcontent);
|
|
tab_link.tab('show');
|
|
tabs.trigger('ready');
|
|
};
|
|
|
|
Sao.Tab.previous_tab = function() {
|
|
Sao.Tab.move('prevAll');
|
|
};
|
|
|
|
Sao.Tab.next_tab = function() {
|
|
Sao.Tab.move('nextAll');
|
|
};
|
|
|
|
Sao.Tab.move = function(direction) {
|
|
var current_tab = this.tabs.get_current();
|
|
var tabs = jQuery('#tabs');
|
|
var tablist = jQuery('#tablist');
|
|
var tab = tablist.find('#nav-' + current_tab.id);
|
|
var next = tab[direction]('li').first();
|
|
if (next) {
|
|
next.find('a').tab('show');
|
|
tabs.trigger('ready');
|
|
}
|
|
};
|
|
|
|
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);
|
|
screen.tab = this;
|
|
this.screen = screen;
|
|
this.attributes = jQuery.extend({}, attributes);
|
|
|
|
this.info_bar = new Sao.Window.InfoBar();
|
|
this.create_tabcontent();
|
|
|
|
screen.message_callback = this.record_message.bind(this);
|
|
screen.switch_callback = function() {
|
|
Sao.set_url(this.get_url(), this.name);
|
|
}.bind(this);
|
|
|
|
this.set_buttons_sensitive();
|
|
|
|
this.view_prm = this.screen.switch_view().done(function() {
|
|
this.set_name(attributes.name || '');
|
|
this.content.append(screen.screen_container.el);
|
|
if (attributes.res_id) {
|
|
if (!jQuery.isArray(attributes.res_id)) {
|
|
attributes.res_id = [attributes.res_id];
|
|
}
|
|
screen.group.load(attributes.res_id);
|
|
screen.set_current_record(
|
|
screen.group.get(attributes.res_id));
|
|
screen.display();
|
|
} else {
|
|
if (screen.current_view.view_type == 'form') {
|
|
screen.new_();
|
|
}
|
|
if (~['tree', 'graph', 'calendar'].indexOf(
|
|
screen.current_view.view_type)) {
|
|
screen.search_filter();
|
|
}
|
|
}
|
|
this.update_revision();
|
|
}.bind(this));
|
|
},
|
|
create_toolbar: function() {
|
|
var toolbar = Sao.Tab.Form._super.create_toolbar.call(this);
|
|
var screen = this.screen;
|
|
var buttons = this.buttons;
|
|
var prm = screen.model.execute('view_toolbar_get', [],
|
|
screen.context());
|
|
prm.done(function(toolbars) {
|
|
[
|
|
['action', 'glyphicon-cog',
|
|
Sao.i18n.gettext('Launch action')],
|
|
['relate', 'glyphicon-share-alt',
|
|
Sao.i18n.gettext('Open related records')],
|
|
['print', 'glyphicon-print',
|
|
Sao.i18n.gettext('Print report')]
|
|
].forEach(function(menu_action) {
|
|
var button = jQuery('<div/>', {
|
|
'class': 'btn-group',
|
|
'role': 'group'
|
|
})
|
|
.append(jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'btn btn-default navbar-btn dropdown-toggle',
|
|
'data-toggle': 'dropdown',
|
|
'aria-expanded': false,
|
|
'aria-haspopup': true,
|
|
'title': menu_action[2],
|
|
'id': menu_action[0],
|
|
})
|
|
.append(jQuery('<span/>', {
|
|
'class': 'glyphicon ' + menu_action[1],
|
|
'aria-hidden': 'true'
|
|
}))
|
|
.append(jQuery('<span/>', {
|
|
'class': 'caret'
|
|
})))
|
|
.append(jQuery('<ul/>', {
|
|
'class': 'dropdown-menu',
|
|
'role': 'menu',
|
|
'aria-labelledby': menu_action[0]
|
|
}))
|
|
.appendTo(toolbar.find('.btn-toolbar > .btn-group').last());
|
|
buttons[menu_action[0]] = button;
|
|
var dropdown = button
|
|
.on('show.bs.dropdown', function() {
|
|
jQuery(this).parents('.btn-group').removeClass(
|
|
'hidden-xs');
|
|
}).on('hide.bs.dropdown', function() {
|
|
jQuery(this).parents('.btn-group').addClass(
|
|
'hidden-xs');
|
|
});
|
|
var menu = button.find('ul[role*="menu"]');
|
|
button.click(function() {
|
|
menu.find('.' + menu_action[0] + '_button').remove();
|
|
var buttons = screen.get_buttons();
|
|
buttons.forEach(function(button) {
|
|
var button_kw = (button.attributes.keyword ||
|
|
'action');
|
|
if (button_kw != menu_action[0]) {
|
|
return;
|
|
}
|
|
var item = jQuery('<li/>', {
|
|
'role': 'presentation',
|
|
'class': menu_action[0] + '_button'
|
|
})
|
|
.append(
|
|
jQuery('<a/>', {
|
|
'role': 'menuitem',
|
|
'href': '#',
|
|
'tabindex': -1
|
|
}).append(
|
|
button.attributes.string || ''))
|
|
.click(function() {
|
|
screen.button(button.attributes);
|
|
})
|
|
.appendTo(menu);
|
|
});
|
|
});
|
|
|
|
toolbars[menu_action[0]].forEach(function(action) {
|
|
var item = jQuery('<li/>', {
|
|
'role': 'presentation'
|
|
})
|
|
.append(jQuery('<a/>', {
|
|
'role': 'menuitem',
|
|
'href': '#',
|
|
'tabindex': -1
|
|
}).append(action.name))
|
|
.click(function() {
|
|
var prm = jQuery.when();
|
|
if (this.screen.modified()) {
|
|
prm = this.save();
|
|
}
|
|
prm.then(function() {
|
|
var exec_action = jQuery.extend({}, action);
|
|
var record_id = null;
|
|
if (screen.current_record) {
|
|
record_id = screen.current_record.id;
|
|
}
|
|
var record_ids = screen.current_view
|
|
.selected_records().map(function(record) {
|
|
return record.id;
|
|
});
|
|
exec_action = Sao.Action.evaluate(exec_action,
|
|
menu_action[0], screen.current_record);
|
|
var data = {
|
|
model: screen.model_name,
|
|
id: record_id,
|
|
ids: record_ids
|
|
};
|
|
Sao.Action.exec_action(exec_action, data,
|
|
screen.context());
|
|
});
|
|
}.bind(this))
|
|
.appendTo(menu);
|
|
}.bind(this));
|
|
}.bind(this));
|
|
}.bind(this));
|
|
return toolbar;
|
|
},
|
|
_close_allowed: function() {
|
|
return this.modified_save();
|
|
},
|
|
modified_save: function() {
|
|
this.screen.save_tree_state();
|
|
this.screen.current_view.set_value();
|
|
if (this.screen.modified()) {
|
|
return Sao.common.sur_3b.run(
|
|
Sao.i18n.gettext('This record has been modified\n' +
|
|
'do you want to save it?'))
|
|
.then(function(result) {
|
|
switch(result) {
|
|
case 'ok':
|
|
return this.save();
|
|
case 'ko':
|
|
return this.reload(false);
|
|
default:
|
|
return jQuery.Deferred().reject();
|
|
}
|
|
}.bind(this));
|
|
}
|
|
return jQuery.when();
|
|
},
|
|
new_: function() {
|
|
if (!Sao.common.MODELACCESS.get(this.screen.model_name).create) {
|
|
return jQuery.when();
|
|
}
|
|
return this.modified_save().then(function() {
|
|
return this.screen.new_().then(function() {
|
|
this.info_bar.message();
|
|
}.bind(this));
|
|
// TODO activate_save
|
|
}.bind(this));
|
|
},
|
|
save: function() {
|
|
var access = Sao.common.MODELACCESS.get(this.screen.model_name);
|
|
if (!(access.write || access.create)) {
|
|
return jQuery.Deferred().reject();
|
|
}
|
|
return this.screen.save_current().then(
|
|
function() {
|
|
this.info_bar.message(
|
|
Sao.i18n.gettext('Record saved.'), 'info');
|
|
this.screen.count_tab_domain();
|
|
}.bind(this),
|
|
function() {
|
|
this.info_bar.message(
|
|
this.screen.invalid_message(), 'danger');
|
|
return jQuery.Deferred().reject();
|
|
}.bind(this));
|
|
},
|
|
switch_: function() {
|
|
return this.modified_save().done(function() {
|
|
this.screen.switch_view();
|
|
}.bind(this));
|
|
},
|
|
reload: function(test_modified) {
|
|
if (test_modified === undefined) {
|
|
test_modified = true;
|
|
}
|
|
var reload = function() {
|
|
return this.screen.cancel_current().then(function() {
|
|
this.screen.save_tree_state(false);
|
|
if (this.screen.current_view.view_type != 'form') {
|
|
this.screen.search_filter(
|
|
this.screen.screen_container.search_entry.val());
|
|
// TODO set current_record
|
|
}
|
|
this.screen.count_tab_domain();
|
|
return this.screen.display().then(function() {
|
|
this.info_bar.message();
|
|
}.bind(this));
|
|
// TODO activate_save
|
|
}.bind(this));
|
|
}.bind(this);
|
|
if (test_modified) {
|
|
return this.modified_save().then(reload);
|
|
} else {
|
|
return reload();
|
|
}
|
|
},
|
|
copy: function() {
|
|
if (!Sao.common.MODELACCESS.get(this.screen.model_name).create) {
|
|
return jQuery.when();
|
|
}
|
|
return this.modified_save().then(function() {
|
|
return this.screen.copy().then(function() {
|
|
this.info_bar.message(
|
|
Sao.i18n.gettext(
|
|
'Working now on the duplicated record(s).'),
|
|
'info');
|
|
this.screen.count_tab_domain();
|
|
}.bind(this));
|
|
}.bind(this));
|
|
},
|
|
delete_: function() {
|
|
if (!Sao.common.MODELACCESS.get(this.screen.model_name)['delete']) {
|
|
return jQuery.when();
|
|
}
|
|
var msg;
|
|
if (this.screen.current_view.view_type == 'form') {
|
|
msg = Sao.i18n.gettext('Are you sure to remove this record?');
|
|
} else {
|
|
msg = Sao.i18n.gettext('Are you sure to remove those records?');
|
|
}
|
|
return Sao.common.sur.run(msg).then(function() {
|
|
return this.screen.remove(true, false, true).then(
|
|
function() {
|
|
this.info_bar.message(
|
|
Sao.i18n.gettext('Records removed.'),
|
|
'info');
|
|
this.screen.count_tab_domain();
|
|
}.bind(this), function() {
|
|
this.info_bar.message(
|
|
Sao.i18n.gettext('Records not removed.'),
|
|
'danger');
|
|
}.bind(this));
|
|
}.bind(this));
|
|
},
|
|
previous: function() {
|
|
return this.modified_save().then(function() {
|
|
this.screen.display_previous();
|
|
this.info_bar.message();
|
|
// TODO activate_save
|
|
}.bind(this));
|
|
},
|
|
next: function() {
|
|
return this.modified_save().then(function() {
|
|
this.screen.display_next();
|
|
this.info_bar.message();
|
|
// TODO activate_save
|
|
}.bind(this));
|
|
},
|
|
search: function() {
|
|
var search_entry = this.screen.screen_container.search_entry;
|
|
if (search_entry.is(':visible')) {
|
|
window.setTimeout(function() {
|
|
search_entry.focus();
|
|
}, 0);
|
|
}
|
|
return jQuery.when();
|
|
},
|
|
logs: function() {
|
|
var record = this.screen.current_record;
|
|
if ((!record) || (record.id < 0)) {
|
|
this.info_bar.message(
|
|
Sao.i18n.gettext('You have to select one record.'),
|
|
'info');
|
|
return jQuery.when();
|
|
}
|
|
var fields = [
|
|
['id', Sao.i18n.gettext('ID:')],
|
|
['create_uid.rec_name',
|
|
Sao.i18n.gettext('Creation User:')],
|
|
['create_date', Sao.i18n.gettext('Creation Date:')],
|
|
['write_uid.rec_name',
|
|
Sao.i18n.gettext('Latest Modification by:')],
|
|
['write_date', Sao.i18n.gettext('Latest Modification Date:')]
|
|
];
|
|
|
|
return 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 += Sao.i18n.gettext('Model: ') + this.screen.model.name;
|
|
Sao.common.message.run(message);
|
|
}.bind(this));
|
|
},
|
|
revision: function() {
|
|
var current_id = null;
|
|
if (this.screen.current_record) {
|
|
current_id = this.screen.current_record.id;
|
|
}
|
|
var set_revision = function(revisions) {
|
|
return function(revision) {
|
|
if (revision) {
|
|
// Add a millisecond as microseconds are truncated
|
|
revision.add(1, 'milliseconds');
|
|
}
|
|
if ((this.screen.current_view.view_type == 'form') &&
|
|
(revision < revisions[revisions.length - 1][0])) {
|
|
revision = revisions[revisions.length - 1][0];
|
|
}
|
|
if (revision != this.screen.context()._datetime) {
|
|
// Update group context that will be propagated by
|
|
// recreating new group
|
|
this.screen.group._context._datetime = revision;
|
|
if (this.screen.current_view.view_type != 'form') {
|
|
this.screen.search_filter(
|
|
this.screen.screen_container
|
|
.search_entry.val());
|
|
} else {
|
|
// Test if record exist in revisions
|
|
this.screen.new_group();
|
|
this.screen.group.load([current_id]);
|
|
}
|
|
this.screen.display(true);
|
|
this.update_revision();
|
|
}
|
|
}.bind(this);
|
|
}.bind(this);
|
|
return this.modified_save().then(function() {
|
|
var ids = this.screen.current_view.selected_records().map(
|
|
function(record) {
|
|
return record.id;
|
|
});
|
|
return this.screen.model.execute('history_revisions',
|
|
[ids], this.screen.context())
|
|
.then(function(revisions) {
|
|
new Sao.Window.Revision(revisions, set_revision(revisions));
|
|
});
|
|
}.bind(this));
|
|
},
|
|
update_revision: function() {
|
|
var revision = this.screen.context()._datetime;
|
|
var label;
|
|
if (revision) {
|
|
var date_format = Sao.common.date_format();
|
|
var time_format = '%H:%M:%S.%f';
|
|
revision = Sao.common.format_datetime(date_format, time_format,
|
|
revision);
|
|
label = this.name + ' @ '+ revision;
|
|
} else {
|
|
label = this.name;
|
|
}
|
|
this.title.html(label);
|
|
this.set_buttons_sensitive(revision);
|
|
},
|
|
set_buttons_sensitive: function(revision) {
|
|
if (!revision) {
|
|
var access = Sao.common.MODELACCESS.get(this.screen.model_name);
|
|
[['new_', access.create],
|
|
['save', access.create || access.write],
|
|
['delete_', access.delete],
|
|
['copy', access.create],
|
|
['import', access.create],
|
|
].forEach(function(e) {
|
|
var button = e[0];
|
|
var access = e[1];
|
|
if (this.buttons[button]) {
|
|
this.buttons[button].toggleClass('disabled', !access);
|
|
}
|
|
if (this.menu_buttons[name]) {
|
|
this.menu_buttons[name]
|
|
.toggleClass('disabled', !access);
|
|
}
|
|
}.bind(this));
|
|
} else {
|
|
['new_', 'save', 'delete_', 'copy', 'import'].forEach(
|
|
function(name) {
|
|
if (this.buttons[name]) {
|
|
this.buttons[name].addClass('disabled');
|
|
}
|
|
if (this.menu_buttons[name]) {
|
|
this.menu_buttons[name].addClass('disabled');
|
|
}
|
|
}.bind(this));
|
|
}
|
|
},
|
|
attach: function() {
|
|
var record = this.screen.current_record;
|
|
if (!record || (record.id < 0)) {
|
|
return;
|
|
}
|
|
new Sao.Window.Attachment(record, function() {
|
|
this.update_attachment_count(true);
|
|
}.bind(this));
|
|
},
|
|
update_attachment_count: function(reload) {
|
|
var record = this.screen.current_record;
|
|
if (record) {
|
|
record.get_attachment_count(reload).always(
|
|
this.attachment_count.bind(this));
|
|
} else {
|
|
this.attachment_count(0);
|
|
}
|
|
},
|
|
attachment_count: function(count) {
|
|
var badge = this.buttons.attach.find('.badge');
|
|
if (!badge.length) {
|
|
badge = jQuery('<span/>', {
|
|
'class': 'badge'
|
|
}).appendTo(this.buttons.attach);
|
|
}
|
|
var text = count || '';
|
|
if (count > 99) {
|
|
text = '99+';
|
|
}
|
|
badge.text(text);
|
|
this.buttons.attach.attr(
|
|
'title', Sao.i18n.gettext("Attachment(%1)", count));
|
|
var record_id = this.screen.get_id();
|
|
this.buttons.attach.prop('disabled',
|
|
record_id < 0 || record_id === null);
|
|
},
|
|
note: function() {
|
|
var record = this.screen.current_record;
|
|
if (!record || (record.id < 0)) {
|
|
return;
|
|
}
|
|
new Sao.Window.Note(record, function() {
|
|
this.update_unread_note(true);
|
|
}.bind(this));
|
|
},
|
|
update_unread_note: function(reload) {
|
|
var record = this.screen.current_record;
|
|
if (record) {
|
|
record.get_unread_note(reload).always(
|
|
this._unread_note.bind(this));
|
|
} else {
|
|
this._unread_note(0);
|
|
}
|
|
},
|
|
_unread_note: function(unread) {
|
|
var badge = this.buttons.note.find('.badge');
|
|
if (!badge.length) {
|
|
badge = jQuery('<span/>', {
|
|
'class': 'badge'
|
|
}).appendTo(this.buttons.note);
|
|
}
|
|
var text = unread || '';
|
|
if (unread > 99) {
|
|
text = '99+';
|
|
}
|
|
badge.text(text);
|
|
this.buttons.note.attr(
|
|
'title', Sao.i18n.gettext("Note(%1)", unread));
|
|
var record_id = this.screen.get_id();
|
|
this.buttons.note.prop('disabled',
|
|
record_id < 0 || record_id === null);
|
|
},
|
|
record_message: function(data) {
|
|
if (data) {
|
|
var name = "_";
|
|
if (data[0] !== 0) {
|
|
name = data[0];
|
|
}
|
|
var buttons = ['print', 'relate', 'attach'];
|
|
buttons.forEach(function(button_id){
|
|
var button = this.buttons[button_id];
|
|
if (button) {
|
|
var disabled = button.is(':disabled');
|
|
button.prop('disabled', disabled || data[0] === 0);
|
|
}
|
|
}.bind(this));
|
|
this.buttons.switch_.prop('disabled',
|
|
this.attributes.view_ids > 1);
|
|
var msg = name + ' / ' + data[1];
|
|
if (data[1] < data[2]) {
|
|
msg += Sao.i18n.gettext(' of ') + data[2];
|
|
}
|
|
this.status_label.text(msg).attr('title', msg);
|
|
}
|
|
this.info_bar.message();
|
|
// TODO activate_save
|
|
},
|
|
action: function() {
|
|
window.setTimeout(function() {
|
|
this.buttons.action.find('button').click();
|
|
}.bind(this));
|
|
},
|
|
relate: function() {
|
|
window.setTimeout(function() {
|
|
this.buttons.relate.find('button').click();
|
|
}.bind(this));
|
|
},
|
|
print: function() {
|
|
window.setTimeout(function() {
|
|
this.buttons.print.find('button').click();
|
|
}.bind(this));
|
|
},
|
|
export: function(){
|
|
new Sao.Window.Export(this.screen,
|
|
this.screen.current_view.selected_records().map(function(r) {
|
|
return r.id;
|
|
}),
|
|
this.screen.current_view.get_fields(),
|
|
this.screen.context());
|
|
},
|
|
import: function(){
|
|
new Sao.Window.Import(this.screen);
|
|
},
|
|
get_url: function() {
|
|
return this.screen.get_url(this.attributes.name);
|
|
},
|
|
});
|
|
|
|
Sao.Tab.Board = Sao.class_(Sao.Tab, {
|
|
class_: 'tab-board',
|
|
init: function(attributes) {
|
|
var UIView, view_prm;
|
|
Sao.Tab.Board._super.init.call(this);
|
|
this.model = attributes.model;
|
|
this.view_id = (attributes.view_ids.length > 0 ?
|
|
attributes.view_ids[0] : null);
|
|
this.context = attributes.context;
|
|
this.name = attributes.name || '';
|
|
this.dialogs = [];
|
|
this.board = null;
|
|
UIView = new Sao.Model('ir.ui.view');
|
|
this.view_prm = UIView.execute('read', [[this.view_id], ['arch']],
|
|
this.context);
|
|
this.view_prm.done(function(views) {
|
|
var view, board;
|
|
view = jQuery(jQuery.parseXML(views[0].arch));
|
|
this.board = new Sao.View.Board(view, this.context);
|
|
this.board.actions_prms.done(function() {
|
|
var i, len, action;
|
|
for (i = 0, len = this.board.actions.length; i < len; i++) {
|
|
action = this.board.actions[i];
|
|
action.screen.tab = this;
|
|
}
|
|
}.bind(this));
|
|
this.el.append(this.board.el);
|
|
}.bind(this));
|
|
this.create_tabcontent();
|
|
this.set_name(this.name);
|
|
this.title.html(this.name_el.text());
|
|
},
|
|
reload: function() {
|
|
this.board.reload();
|
|
},
|
|
record_message: function() {
|
|
var i, len;
|
|
var action;
|
|
|
|
len = this.board.actions.length;
|
|
for (i = 0, len=len; i < len; i++) {
|
|
action = this.board.actions[i];
|
|
action.update_domain(this.board.actions);
|
|
}
|
|
},
|
|
attachment_count: function() {
|
|
},
|
|
note: function() {
|
|
},
|
|
update_unread_note: function() {
|
|
}
|
|
});
|
|
|
|
Sao.Tab.Wizard = Sao.class_(Sao.Tab, {
|
|
class_: 'tab-wizard',
|
|
init: function(wizard) {
|
|
Sao.Tab.Wizard._super.init.call(this);
|
|
this.wizard = wizard;
|
|
this.set_name(wizard.name);
|
|
wizard.tab = this;
|
|
this.create_tabcontent();
|
|
this.title.html(this.name_el.text());
|
|
this.el.append(wizard.form);
|
|
},
|
|
create_toolbar: function() {
|
|
return jQuery('<span/>');
|
|
},
|
|
_close_allowed: function() {
|
|
var wizard = this.wizard;
|
|
var prm = jQuery.when();
|
|
if ((wizard.state !== wizard.end_state) &&
|
|
(wizard.end_state in wizard.states)) {
|
|
prm = wizard.response(wizard.end_state);
|
|
}
|
|
var dfd = jQuery.Deferred();
|
|
prm.always(function() {
|
|
if (wizard.state === wizard.end_state) {
|
|
dfd.resolve();
|
|
} else {
|
|
dfd.reject();
|
|
}
|
|
});
|
|
return dfd.promise();
|
|
}
|
|
});
|
|
}());
|