mirror of
https://github.com/NaN-tic/sao-base.git
synced 2023-12-14 03:13:01 +01:00
Add Gruntfile and fix jshint
This commit is contained in:
parent
70ce8b5556
commit
6fae77fb6d
63
Gruntfile.js
Normal file
63
Gruntfile.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
module.exports = function(grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
concat: {
|
||||
dist: {
|
||||
src: [
|
||||
'js/sao.js',
|
||||
'js/rpc.js',
|
||||
'js/pyson.js',
|
||||
'js/session.js',
|
||||
'js/model.js',
|
||||
'js/tab.js',
|
||||
'js/screen.js',
|
||||
'js/view.js',
|
||||
'js/action.js',
|
||||
'js/common.js'
|
||||
],
|
||||
dest: 'dist/<%= pkg.name %>.js'
|
||||
}
|
||||
},
|
||||
jshint: {
|
||||
dist: {
|
||||
options: {
|
||||
jshintrc: 'js/.jshintrc'
|
||||
},
|
||||
src: ['dist/<%= pkg.name %>.js']
|
||||
},
|
||||
grunt: {
|
||||
src: ['Gruntfile.js']
|
||||
},
|
||||
tests: {
|
||||
options: {
|
||||
jshintrc: 'tests/.jshintrc'
|
||||
},
|
||||
src: ['tests/*.js']
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %>-<%= pkg.version %> | GPL-3\n' +
|
||||
'This file is part of Tryton. ' +
|
||||
'The COPYRIGHT file at the top level of\n' +
|
||||
'this repository contains the full copyright notices ' +
|
||||
'and license terms. */\n'
|
||||
},
|
||||
dist: {
|
||||
src: 'dist/<%= pkg.name %>.js',
|
||||
dest: 'dist/<%= pkg.name %>.min.js'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Load the plugin that provides the "uglify" task.
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
|
||||
// Default task(s).
|
||||
grunt.registerTask('default', ['concat', 'jshint', 'uglify']);
|
||||
|
||||
};
|
16
index.html
16
index.html
|
@ -20,16 +20,12 @@ this repository contains the full copyright notices and license terms. -->
|
|||
document.write(unescape('%3CLINK rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" media="screen"/%3E'));
|
||||
}
|
||||
</SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/class.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/sao.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/rpc.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/session.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/model.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/tab.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/screen.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/view.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/action.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="js/common.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript" src="dist/sao.min.js"></SCRIPT>
|
||||
<SCRIPT type="text/javascript">
|
||||
if (typeof Sao == 'undefined') {
|
||||
document.write(unescape('%3CSCRIPT type="text/javascript" src="dist/sao.js"%3E%3C/SCRIPT%3E'));
|
||||
}
|
||||
</SCRIPT>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<DIV id="main">
|
||||
|
|
8
js/.jshintrc
Normal file
8
js/.jshintrc
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"browser": true,
|
||||
"devel": true,
|
||||
"jquery": true,
|
||||
"predef": [
|
||||
"Sao"
|
||||
]
|
||||
}
|
162
js/action.js
162
js/action.js
|
@ -1,85 +1,89 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.Action = {};
|
||||
Sao.Action = {};
|
||||
|
||||
Sao.Action.exec_action = function(action, data, context) {
|
||||
if (context == undefined) {
|
||||
context = {};
|
||||
}
|
||||
if (data == undefined) {
|
||||
data = {};
|
||||
} else {
|
||||
data = jQuery.extend({}, data);
|
||||
}
|
||||
switch (action['type']) {
|
||||
case 'ir.action.act_window':
|
||||
var params = {};
|
||||
params.view_ids = false;
|
||||
params.view_mode = null;
|
||||
if (!jQuery.isEmptyObject(action.views)) {
|
||||
params.view_ids = [];
|
||||
params.view_mode = [];
|
||||
action.views.forEach(function(x) {
|
||||
params.view_ids.push(x[0]);
|
||||
params.view_mode.push(x[1]);
|
||||
});
|
||||
} else if (!jQuery.isEmptyObject(action.view_id)) {
|
||||
params.view_ids = [action.view_id[0]];
|
||||
}
|
||||
// TODO context, domain, search, tab_domain
|
||||
params.name = false;
|
||||
if (action.window_name) {
|
||||
params.name = action.name;
|
||||
}
|
||||
params.model = action.res_model || data.res_model;
|
||||
params.res_id = action.res_id || data.res_id;
|
||||
Sao.Tab.create(params);
|
||||
return;
|
||||
case 'ir.action.wizard':
|
||||
return;
|
||||
case 'ir.action.report':
|
||||
return;
|
||||
case 'ir.action.url':
|
||||
window.open(action['url'], '_blank');
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Sao.Action.exec_keyword = function(keyword, data, context, warning, alwaysask)
|
||||
{
|
||||
if (warning == undefined) {
|
||||
warning = true;
|
||||
}
|
||||
if (alwaysask == undefined) {
|
||||
alwaysask = false;
|
||||
}
|
||||
var actions = [];
|
||||
var model_id = data['id'];
|
||||
var args = {
|
||||
'method': 'model.' + 'ir.action.keyword.get_keyword',
|
||||
'params': [keyword, [data['model'], model_id], {}]
|
||||
};
|
||||
var prm = Sao.rpc(args, Sao.Session.current_session);
|
||||
var exec_action = function(actions) {
|
||||
var keyact = {};
|
||||
for (var i in actions) {
|
||||
var action = actions[i];
|
||||
keyact[action['name'].replace(/_/g, '')] = action;
|
||||
Sao.Action.exec_action = function(action, data, context) {
|
||||
if (context === undefined) {
|
||||
context = {};
|
||||
}
|
||||
if (data === undefined) {
|
||||
data = {};
|
||||
} else {
|
||||
data = jQuery.extend({}, data);
|
||||
}
|
||||
switch (action.type) {
|
||||
case 'ir.action.act_window':
|
||||
var params = {};
|
||||
params.view_ids = false;
|
||||
params.view_mode = null;
|
||||
if (!jQuery.isEmptyObject(action.views)) {
|
||||
params.view_ids = [];
|
||||
params.view_mode = [];
|
||||
action.views.forEach(function(x) {
|
||||
params.view_ids.push(x[0]);
|
||||
params.view_mode.push(x[1]);
|
||||
});
|
||||
} else if (!jQuery.isEmptyObject(action.view_id)) {
|
||||
params.view_ids = [action.view_id[0]];
|
||||
}
|
||||
// TODO context, domain, search, tab_domain
|
||||
params.name = false;
|
||||
if (action.window_name) {
|
||||
params.name = action.name;
|
||||
}
|
||||
params.model = action.res_model || data.res_model;
|
||||
params.res_id = action.res_id || data.res_id;
|
||||
Sao.Tab.create(params);
|
||||
return;
|
||||
case 'ir.action.wizard':
|
||||
return;
|
||||
case 'ir.action.report':
|
||||
return;
|
||||
case 'ir.action.url':
|
||||
window.open(action.url, '_blank');
|
||||
return;
|
||||
}
|
||||
// TODO translation
|
||||
var prm = Sao.common.selection('Select your action', keyact, alwaysask);
|
||||
prm.done(function(action) {
|
||||
Sao.Action.exec_action(action, data, context);
|
||||
});
|
||||
prm.fail(function() {
|
||||
if (jQuery.isEmptyObject(keyact) && warning) {
|
||||
// TODO translation
|
||||
alert('No action defined!');
|
||||
}
|
||||
});
|
||||
return prm;
|
||||
};
|
||||
return prm.pipe(exec_action);
|
||||
};
|
||||
|
||||
Sao.Action.exec_keyword = function(keyword, data, context, warning,
|
||||
alwaysask)
|
||||
{
|
||||
if (warning === undefined) {
|
||||
warning = true;
|
||||
}
|
||||
if (alwaysask === undefined) {
|
||||
alwaysask = false;
|
||||
}
|
||||
var actions = [];
|
||||
var model_id = data.id;
|
||||
var args = {
|
||||
'method': 'model.' + 'ir.action.keyword.get_keyword',
|
||||
'params': [keyword, [data.model, model_id], {}]
|
||||
};
|
||||
var prm = Sao.rpc(args, Sao.Session.current_session);
|
||||
var exec_action = function(actions) {
|
||||
var keyact = {};
|
||||
for (var i in actions) {
|
||||
var action = actions[i];
|
||||
keyact[action.name.replace(/_/g, '')] = action;
|
||||
}
|
||||
// TODO translation
|
||||
var prm = Sao.common.selection('Select your action', keyact,
|
||||
alwaysask);
|
||||
prm.done(function(action) {
|
||||
Sao.Action.exec_action(action, data, context);
|
||||
});
|
||||
prm.fail(function() {
|
||||
if (jQuery.isEmptyObject(keyact) && warning) {
|
||||
// TODO translation
|
||||
alert('No action defined!');
|
||||
}
|
||||
});
|
||||
return prm;
|
||||
};
|
||||
return prm.pipe(exec_action);
|
||||
};
|
||||
}());
|
||||
|
|
24
js/class.js
24
js/class.js
|
@ -1,24 +0,0 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
|
||||
var Class = function(Parent, props) {
|
||||
|
||||
var ClassConstructor = function() {
|
||||
if (!(this instanceof ClassConstructor))
|
||||
throw Error('Constructor function requires new operator');
|
||||
if (this.init) {
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Plug prototype chain
|
||||
ClassConstructor.prototype = Object.create(Parent.prototype);
|
||||
ClassConstructor._super = Parent.prototype;
|
||||
if (props) {
|
||||
for (var name in props) {
|
||||
ClassConstructor.prototype[name] = props[name];
|
||||
}
|
||||
}
|
||||
return ClassConstructor;
|
||||
};
|
30
js/common.js
30
js/common.js
|
@ -1,18 +1,20 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.common = {};
|
||||
Sao.common = {};
|
||||
|
||||
Sao.common.selection = function(title, values, alwaysask) {
|
||||
if (alwaysask == undefined) {
|
||||
alwaysask = false;
|
||||
}
|
||||
if ((Object.keys(values).length == 1) && (!alwaysask)) {
|
||||
var prm = jQuery.Deferred();
|
||||
var key = Object.keys(values)[0];
|
||||
prm.resolve(values[key]);
|
||||
return prm;
|
||||
}
|
||||
// TODO
|
||||
};
|
||||
Sao.common.selection = function(title, values, alwaysask) {
|
||||
if (alwaysask === undefined) {
|
||||
alwaysask = false;
|
||||
}
|
||||
if ((Object.keys(values).length == 1) && (!alwaysask)) {
|
||||
var prm = jQuery.Deferred();
|
||||
var key = Object.keys(values)[0];
|
||||
prm.resolve(values[key]);
|
||||
return prm;
|
||||
}
|
||||
// TODO
|
||||
};
|
||||
}());
|
||||
|
|
1571
js/model.js
1571
js/model.js
File diff suppressed because it is too large
Load diff
1203
js/pyson.js
1203
js/pyson.js
File diff suppressed because it is too large
Load diff
292
js/rpc.js
292
js/rpc.js
|
@ -1,150 +1,152 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.rpc = function(args, session) {
|
||||
var dfd = jQuery.Deferred();
|
||||
if (!session) {
|
||||
session = new Sao.Session();
|
||||
}
|
||||
Sao.rpc = function(args, session) {
|
||||
var dfd = jQuery.Deferred();
|
||||
if (!session) {
|
||||
session = new Sao.Session();
|
||||
}
|
||||
|
||||
var ajax_prm = jQuery.ajax({
|
||||
'contentType': 'application/json',
|
||||
'data': JSON.stringify(Sao.rpc.prepareObject({
|
||||
'method': args.method,
|
||||
'params': [session.user_id, session.session].concat(args.params)
|
||||
})),
|
||||
'dataType': 'json',
|
||||
'url': '/' + (session.database || ''),
|
||||
'type': 'post'
|
||||
var ajax_prm = jQuery.ajax({
|
||||
'contentType': 'application/json',
|
||||
'data': JSON.stringify(Sao.rpc.prepareObject({
|
||||
'method': args.method,
|
||||
'params': [session.user_id, session.session].concat(args.params)
|
||||
})),
|
||||
'dataType': 'json',
|
||||
'url': '/' + (session.database || ''),
|
||||
'type': 'post'
|
||||
});
|
||||
|
||||
var ajax_success = function(data) {
|
||||
if (data === null) {
|
||||
Sao.warning('Unable to reach the server');
|
||||
dfd.reject();
|
||||
} else if (data.error) {
|
||||
if (data.error[0] == 'UserWarning') {
|
||||
} else if (data.error[0] == 'UserError') {
|
||||
// TODO
|
||||
} else if (data.error[0] == 'ConcurrencyException') {
|
||||
// TODO
|
||||
} else if (data.error[0] == 'NotLogged') {
|
||||
//Try to relog
|
||||
var cred_prm = jQuery.Deferred();
|
||||
Sao.Session.renew_credentials(session, cred_prm);
|
||||
cred_prm.done(function() {
|
||||
Sao.rpc(session, args, dfd);
|
||||
});
|
||||
cred_prm.fail(dfd.reject);
|
||||
} else {
|
||||
console.log('ERROR');
|
||||
Sao.error(data.error[0], data.error[1]);
|
||||
}
|
||||
dfd.reject();
|
||||
} else {
|
||||
dfd.resolve(data.result);
|
||||
}
|
||||
};
|
||||
|
||||
var ajax_error = function() {
|
||||
console.log('ERROR');
|
||||
dfd.reject();
|
||||
};
|
||||
ajax_prm.success(ajax_success);
|
||||
ajax_prm.error(ajax_error);
|
||||
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
Sao.rpc.convertJSONObject = function(value, index, parent) {
|
||||
if (value instanceof Array) {
|
||||
for (var i = 0, length = value.length; i < length; i++) {
|
||||
Sao.rpc.convertJSONObject(value[i], i, value);
|
||||
}
|
||||
} else if ((typeof(value) != 'string') &&
|
||||
(typeof(value) != 'number')) {
|
||||
if (value && value.__class__) {
|
||||
switch (value.__class__) {
|
||||
case 'datetime':
|
||||
value = new Date(Date.UTC(value.year,
|
||||
value.month, value.day, value.hour,
|
||||
value.minute, value.second));
|
||||
break;
|
||||
case 'date':
|
||||
value = new Date(value.year,
|
||||
value.month, value.day);
|
||||
break;
|
||||
case 'time':
|
||||
throw new Error('Time support not implemented');
|
||||
case 'buffer':
|
||||
throw new Error('Buffer support not implemented');
|
||||
case 'Decimal':
|
||||
value = new Number(value.decimal);
|
||||
break;
|
||||
}
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else {
|
||||
for (var p in value) {
|
||||
Sao.rpc.convertJSONObject(value[p], p, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent || value;
|
||||
};
|
||||
|
||||
Sao.rpc.prepareObject = function(value, index, parent) {
|
||||
if (value instanceof Array) {
|
||||
for (var i = 0, length = value.length; i < length; i++) {
|
||||
Sao.rpc.prepareObject(value[i], i, value);
|
||||
}
|
||||
} else if ((typeof(value) != 'string') && (typeof(value) != 'number')) {
|
||||
if (value instanceof Date) {
|
||||
if (value.getHours() || value.getMinutes() || value.getSeconds)
|
||||
{
|
||||
value = {
|
||||
'__class__': 'datetime',
|
||||
'year': value.getUTCFullYear(),
|
||||
'month': value.getUTCMonth(),
|
||||
'day': value.getUTCDate(),
|
||||
'hour': value.getUTCHours(),
|
||||
'minute': value.getUTCMinutes(),
|
||||
'second': value.getUTCSeconds()
|
||||
};
|
||||
} else {
|
||||
value = {
|
||||
'__class__': 'date',
|
||||
'year': value.getFullYear(),
|
||||
'month': value.getMonth(),
|
||||
'day': value.getDate()
|
||||
};
|
||||
}
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else if (value instanceof Number) {
|
||||
value = {
|
||||
'__class__': 'Decimal',
|
||||
'decimal': value.valueOf()
|
||||
};
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else {
|
||||
for (var p in value) {
|
||||
Sao.rpc.prepareObject(value[p], p, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent || value;
|
||||
};
|
||||
|
||||
jQuery.ajaxSetup({
|
||||
converters: {
|
||||
'text json': function(json) {
|
||||
return Sao.rpc.convertJSONObject(jQuery.parseJSON(json));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var ajax_success = function(data) {
|
||||
if (data === null) {
|
||||
Sao.warning('Unable to reach the server');
|
||||
dfd.reject();
|
||||
} else if (data.error) {
|
||||
if (data.error[0] == 'UserWarning') {
|
||||
} else if (data.error[0] == 'UserError') {
|
||||
// TODO
|
||||
} else if (data.error[0] == 'ConcurrencyException') {
|
||||
// TODO
|
||||
} else if (data.error[0] == 'NotLogged') {
|
||||
//Try to relog
|
||||
var cred_prm = jQuery.Deferred();
|
||||
Sao.Session.renew_credentials(session, cred_prm);
|
||||
cred_prm.done(function() {
|
||||
Sao.rpc(session, args, dfd);
|
||||
});
|
||||
cred_prm.fail(dfd.reject);
|
||||
} else {
|
||||
console.log('ERROR');
|
||||
Sao.error(data.error[0], data.error[1]);
|
||||
}
|
||||
dfd.reject();
|
||||
} else {
|
||||
dfd.resolve(data.result);
|
||||
}
|
||||
};
|
||||
|
||||
var ajax_error = function() {
|
||||
console.log('ERROR');
|
||||
dfd.reject();
|
||||
};
|
||||
ajax_prm.success(ajax_success);
|
||||
ajax_prm.error(ajax_error);
|
||||
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
Sao.rpc.convertJSONObject = function(value, index, parent) {
|
||||
if (value instanceof Array) {
|
||||
for (var i = 0, length = value.length; i < length; i++) {
|
||||
Sao.rpc.convertJSONObject(value[i], i, value);
|
||||
}
|
||||
} else if ((typeof(value) != 'string') &&
|
||||
(typeof(value) != 'number')) {
|
||||
if (value && value.__class__) {
|
||||
switch (value.__class__) {
|
||||
case 'datetime':
|
||||
value = new Date(Date.UTC(value.year,
|
||||
value.month, value.day, value.hour,
|
||||
value.minute, value.second));
|
||||
break;
|
||||
case 'date':
|
||||
value = new Date(value.year,
|
||||
value.month, value.day);
|
||||
break;
|
||||
case 'time':
|
||||
throw Error('Time support not implemented');
|
||||
case 'buffer':
|
||||
throw Error('Buffer support not implemented');
|
||||
case 'Decimal':
|
||||
value = new Number(value.decimal);
|
||||
break;
|
||||
}
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else {
|
||||
for (var p in value) {
|
||||
Sao.rpc.convertJSONObject(value[p], p, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent || value;
|
||||
};
|
||||
|
||||
Sao.rpc.prepareObject = function(value, index, parent) {
|
||||
if (value instanceof Array) {
|
||||
for (var i = 0, length = value.length; i < length; i++) {
|
||||
Sao.rpc.prepareObject(value[i], i, value);
|
||||
}
|
||||
} else if ((typeof(value) != 'string') && (typeof(value) != 'number')) {
|
||||
if (value instanceof Date) {
|
||||
if (value.getHours() || value.getMinutes() || value.getSeconds)
|
||||
{
|
||||
value = {
|
||||
'__class__': 'datetime',
|
||||
'year': value.getUTCFullYear(),
|
||||
'month': value.getUTCMonth(),
|
||||
'day': value.getUTCDate(),
|
||||
'hour': value.getUTCHours(),
|
||||
'minute': value.getUTCMinutes(),
|
||||
'second': value.getUTCSeconds()
|
||||
};
|
||||
} else {
|
||||
value = {
|
||||
'__class__': 'date',
|
||||
'year': value.getFullYear(),
|
||||
'month': value.getMonth(),
|
||||
'day': value.getDate()
|
||||
};
|
||||
}
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else if (value instanceof Number) {
|
||||
value = {
|
||||
'__class__': 'Decimal',
|
||||
'decimal': value.valueOf()
|
||||
};
|
||||
if (parent) {
|
||||
parent[index] = value;
|
||||
}
|
||||
} else {
|
||||
for (var p in value) {
|
||||
Sao.rpc.prepareObject(value[p], p, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent || value;
|
||||
};
|
||||
|
||||
jQuery.ajaxSetup({
|
||||
converters: {
|
||||
'text json': function(json) {
|
||||
return Sao.rpc.convertJSONObject(jQuery.parseJSON(json));
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
|
38
js/sao.js
38
js/sao.js
|
@ -1,13 +1,35 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
|
||||
var Sao = {};
|
||||
|
||||
Sao.error = function(title, message) {
|
||||
alert(title + '\n' + (message || ''));
|
||||
};
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.warning = function(title, message) {
|
||||
alert(title + '\n' + (message || ''));
|
||||
};
|
||||
Sao.error = function(title, message) {
|
||||
alert(title + '\n' + (message || ''));
|
||||
};
|
||||
|
||||
Sao.warning = function(title, message) {
|
||||
alert(title + '\n' + (message || ''));
|
||||
};
|
||||
|
||||
Sao.class_ = function(Parent, props) {
|
||||
var ClassConstructor = function() {
|
||||
if (!(this instanceof ClassConstructor))
|
||||
throw new Error('Constructor function requires new operator');
|
||||
if (this.init) {
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Plug prototype chain
|
||||
ClassConstructor.prototype = Object.create(Parent.prototype);
|
||||
ClassConstructor._super = Parent.prototype;
|
||||
if (props) {
|
||||
for (var name in props) {
|
||||
ClassConstructor.prototype[name] = props[name];
|
||||
}
|
||||
}
|
||||
return ClassConstructor;
|
||||
};
|
||||
}());
|
||||
|
|
260
js/screen.js
260
js/screen.js
|
@ -1,139 +1,141 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.Screen = Class(Object, {
|
||||
init: function(model_name, attributes) {
|
||||
this.model_name = model_name;
|
||||
this.model = new Sao.Model(model_name, attributes);
|
||||
this.attributes = jQuery.extend({}, attributes);
|
||||
this.view_ids = jQuery.extend([], attributes.view_ids);
|
||||
this.view_to_load = jQuery.extend([],
|
||||
attributes.mode || ['tree', 'form']);
|
||||
this.views = [];
|
||||
this.current_view = null;
|
||||
this.current_record = null;
|
||||
this.context = attributes.context || {};
|
||||
if (!attributes.row_activate) {
|
||||
this.row_activate = this.default_row_activate;
|
||||
} else {
|
||||
this.row_activate = attributes.row_activate;
|
||||
}
|
||||
this.el = $('<div/>', {
|
||||
'class': 'screen'
|
||||
});
|
||||
},
|
||||
load_next_view: function() {
|
||||
if (this.view_to_load) {
|
||||
var view_id;
|
||||
if (this.view_ids) {
|
||||
view_id = this.view_ids.shift();
|
||||
}
|
||||
var view_type = this.view_to_load.shift();
|
||||
return this.add_view_id(view_id, view_type);
|
||||
}
|
||||
return jQuery.when();
|
||||
},
|
||||
add_view_id: function(view_id, view_type) {
|
||||
// TODO preload
|
||||
var prm = this.model.execute('fields_view_get',
|
||||
[view_id, view_type], this.context);
|
||||
prm.done(this.add_view.bind(this));
|
||||
return prm;
|
||||
},
|
||||
add_view: function(view) {
|
||||
var arch = view.arch;
|
||||
var fields = view.fields;
|
||||
var xml_view = jQuery(jQuery.parseXML(arch));
|
||||
// TODO loading lazy/eager
|
||||
var loading = 'eager';
|
||||
if (xml_view.children().prop('tagName') == 'form') {
|
||||
loading = 'lazy';
|
||||
}
|
||||
for (var field in fields) {
|
||||
if (!(field in this.model.fields) || loading == 'eager') {
|
||||
fields[field]['loading'] = loading;
|
||||
Sao.Screen = Sao.class_(Object, {
|
||||
init: function(model_name, attributes) {
|
||||
this.model_name = model_name;
|
||||
this.model = new Sao.Model(model_name, attributes);
|
||||
this.attributes = jQuery.extend({}, attributes);
|
||||
this.view_ids = jQuery.extend([], attributes.view_ids);
|
||||
this.view_to_load = jQuery.extend([],
|
||||
attributes.mode || ['tree', 'form']);
|
||||
this.views = [];
|
||||
this.current_view = null;
|
||||
this.current_record = null;
|
||||
this.context = attributes.context || {};
|
||||
if (!attributes.row_activate) {
|
||||
this.row_activate = this.default_row_activate;
|
||||
} else {
|
||||
fields[field]['loading'] = this.model.fields[field]
|
||||
.description.loading;
|
||||
this.row_activate = attributes.row_activate;
|
||||
}
|
||||
}
|
||||
this.model.add_fields(fields);
|
||||
var view = Sao.View.parse(this, xml_view, view.field_childs);
|
||||
this.views.push(view);
|
||||
return view;
|
||||
},
|
||||
number_of_views: function() {
|
||||
return this.views.length + this.view_to_load.length;
|
||||
},
|
||||
switch_view: function(view_type) {
|
||||
// TODO check validity
|
||||
var self = this;
|
||||
if ((!view_type) || (!this.current_view) ||
|
||||
(this.current_view.view_type != view_type)) {
|
||||
for (var i = 0; i < this.number_of_views(); i++) {
|
||||
if (this.view_to_load.length) {
|
||||
return this.load_next_view().done(function() {
|
||||
self.current_view = self.views.slice(-1);
|
||||
return self.switch_view(view_type);
|
||||
});
|
||||
this.el = jQuery('<div/>', {
|
||||
'class': 'screen'
|
||||
});
|
||||
},
|
||||
load_next_view: function() {
|
||||
if (this.view_to_load) {
|
||||
var view_id;
|
||||
if (this.view_ids) {
|
||||
view_id = this.view_ids.shift();
|
||||
}
|
||||
this.current_view = this.views[
|
||||
(this.views.indexOf(this.current_view) + 1) %
|
||||
this.views.length];
|
||||
if (!view_type) {
|
||||
break;
|
||||
} else if (this.current_view.view_type == view_type) {
|
||||
break;
|
||||
var view_type = this.view_to_load.shift();
|
||||
return this.add_view_id(view_id, view_type);
|
||||
}
|
||||
return jQuery.when();
|
||||
},
|
||||
add_view_id: function(view_id, view_type) {
|
||||
// TODO preload
|
||||
var prm = this.model.execute('fields_view_get',
|
||||
[view_id, view_type], this.context);
|
||||
prm.done(this.add_view.bind(this));
|
||||
return prm;
|
||||
},
|
||||
add_view: function(view) {
|
||||
var arch = view.arch;
|
||||
var fields = view.fields;
|
||||
var xml_view = jQuery(jQuery.parseXML(arch));
|
||||
// TODO loading lazy/eager
|
||||
var loading = 'eager';
|
||||
if (xml_view.children().prop('tagName') == 'form') {
|
||||
loading = 'lazy';
|
||||
}
|
||||
for (var field in fields) {
|
||||
if (!(field in this.model.fields) || loading == 'eager') {
|
||||
fields[field].loading = loading;
|
||||
} else {
|
||||
fields[field].loading = this.model.fields[field]
|
||||
.description.loading;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.el.remove();
|
||||
this.el.append(this.current_view.el);
|
||||
// TODO display and cursor
|
||||
return jQuery.when();
|
||||
},
|
||||
search_filter: function() {
|
||||
var domain = [];
|
||||
// TODO domain parser
|
||||
this.model.add_fields(fields);
|
||||
var view_widget = Sao.View.parse(this, xml_view, view.field_childs);
|
||||
this.views.push(view_widget);
|
||||
return view_widget;
|
||||
},
|
||||
number_of_views: function() {
|
||||
return this.views.length + this.view_to_load.length;
|
||||
},
|
||||
switch_view: function(view_type) {
|
||||
// TODO check validity
|
||||
var self = this;
|
||||
if ((!view_type) || (!this.current_view) ||
|
||||
(this.current_view.view_type != view_type)) {
|
||||
var switch_current_view = function() {
|
||||
self.current_view = self.views.slice(-1);
|
||||
return self.switch_view(view_type);
|
||||
};
|
||||
for (var i = 0; i < this.number_of_views(); i++) {
|
||||
if (this.view_to_load.length) {
|
||||
return this.load_next_view().done(switch_current_view);
|
||||
}
|
||||
this.current_view = this.views[
|
||||
(this.views.indexOf(this.current_view) + 1) %
|
||||
this.views.length];
|
||||
if (!view_type) {
|
||||
break;
|
||||
} else if (this.current_view.view_type == view_type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.el.remove();
|
||||
this.el.append(this.current_view.el);
|
||||
// TODO display and cursor
|
||||
return jQuery.when();
|
||||
},
|
||||
search_filter: function() {
|
||||
var domain = [];
|
||||
// TODO domain parser
|
||||
|
||||
if (domain.length && this.attributes.domain) {
|
||||
domain.unshift('AND');
|
||||
domain.push(this.attributes.domain);
|
||||
} else
|
||||
domain = this.attributes.domain || [];
|
||||
var grp_prm = this.model.find(domain, this.attributes.offset,
|
||||
this.attributes.limit, this.attributes.order,
|
||||
this.context);
|
||||
var group_setter = function(group) {
|
||||
this.group = group;
|
||||
};
|
||||
grp_prm.done(group_setter.bind(this));
|
||||
return grp_prm;
|
||||
},
|
||||
display: function() {
|
||||
if (this.views) {
|
||||
for (var i = 0; i < this.views.length; i++)
|
||||
if (this.views[i])
|
||||
this.views[i].display();
|
||||
if (domain.length && this.attributes.domain) {
|
||||
domain.unshift('AND');
|
||||
domain.push(this.attributes.domain);
|
||||
} else
|
||||
domain = this.attributes.domain || [];
|
||||
var grp_prm = this.model.find(domain, this.attributes.offset,
|
||||
this.attributes.limit, this.attributes.order,
|
||||
this.context);
|
||||
var group_setter = function(group) {
|
||||
this.group = group;
|
||||
};
|
||||
grp_prm.done(group_setter.bind(this));
|
||||
return grp_prm;
|
||||
},
|
||||
display: function() {
|
||||
if (this.views) {
|
||||
for (var i = 0; i < this.views.length; i++)
|
||||
if (this.views[i])
|
||||
this.views[i].display();
|
||||
}
|
||||
},
|
||||
default_row_activate: function() {
|
||||
if ((this.current_view.view_type == 'tree') &&
|
||||
this.current_view.keyword_open) {
|
||||
Sao.Action.exec_keyword('tree_open', {
|
||||
'model': this.model_name,
|
||||
'id': this.get_id(),
|
||||
'ids': [this.get_id()]
|
||||
}, jQuery.extend({}, this.context));
|
||||
} else {
|
||||
this.switch_view('form');
|
||||
}
|
||||
},
|
||||
get_id: function() {
|
||||
if (this.current_record) {
|
||||
return this.current_record.id;
|
||||
}
|
||||
}
|
||||
},
|
||||
default_row_activate: function() {
|
||||
if ((this.current_view.view_type == 'tree') &&
|
||||
this.current_view.keyword_open) {
|
||||
Sao.Action.exec_keyword('tree_open', {
|
||||
'model': this.model_name,
|
||||
'id': this.get_id(),
|
||||
'ids': [this.get_id()]
|
||||
}, jQuery.extend({}, this.context));
|
||||
} else {
|
||||
this.switch_view('form');
|
||||
}
|
||||
},
|
||||
get_id: function() {
|
||||
if (this.current_record) {
|
||||
return this.current_record.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
||||
|
|
418
js/session.js
418
js/session.js
|
@ -1,220 +1,222 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.Session = Class(Object, {
|
||||
init: function(database, login) {
|
||||
this.database = database;
|
||||
this.login = login;
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
if (!Sao.Session.current_session) {
|
||||
Sao.Session.current_session = this;
|
||||
Sao.Session = Sao.class_(Object, {
|
||||
init: function(database, login) {
|
||||
this.database = database;
|
||||
this.login = login;
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
if (!Sao.Session.current_session) {
|
||||
Sao.Session.current_session = this;
|
||||
}
|
||||
},
|
||||
do_login: function(login, password) {
|
||||
var dfd = jQuery.Deferred();
|
||||
var args = {
|
||||
'method': 'common.db.login',
|
||||
'params': [login, password]
|
||||
};
|
||||
var ajax_prm = jQuery.ajax({
|
||||
'contentType': 'application/json',
|
||||
'data': JSON.stringify(args),
|
||||
'dataType': 'json',
|
||||
'url': '/' + this.database,
|
||||
'type': 'post'
|
||||
});
|
||||
|
||||
var ajax_success = function(data) {
|
||||
if (data === null) {
|
||||
Sao.warning('Unable to reach the server');
|
||||
dfd.reject();
|
||||
} else if (data.error) {
|
||||
console.log('ERROR');
|
||||
Sao.error(data.error[0], data.error[1]);
|
||||
dfd.reject();
|
||||
} else {
|
||||
if (!data.result) {
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
} else {
|
||||
this.user_id = data.result[0];
|
||||
this.session = data.result[1];
|
||||
}
|
||||
dfd.resolve();
|
||||
}
|
||||
};
|
||||
ajax_prm.success(ajax_success.bind(this));
|
||||
ajax_prm.error(dfd.reject);
|
||||
return dfd.promise();
|
||||
},
|
||||
do_logout: function() {
|
||||
if (!(this.user_id && this.session)) {
|
||||
return;
|
||||
}
|
||||
var args = {
|
||||
'method': 'common.db.logout',
|
||||
'params': []
|
||||
};
|
||||
var prm = Sao.rpc(this, args);
|
||||
this.database = null;
|
||||
this.login = null;
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
return prm;
|
||||
}
|
||||
},
|
||||
do_login: function(login, password) {
|
||||
var dfd = jQuery.Deferred();
|
||||
var args = {
|
||||
'method': 'common.db.login',
|
||||
'params': [login, password]
|
||||
});
|
||||
|
||||
Sao.Session.get_credentials = function(parent_dfd) {
|
||||
var login; // TODO use cookie
|
||||
var database = window.location.hash.replace(
|
||||
/^(#(!|))/, '') || null;
|
||||
var database_div, database_select;
|
||||
var login_div, login_input, password_input;
|
||||
|
||||
var ok_func = function() {
|
||||
var login_val = login_input.val();
|
||||
var password_val = password_input.val();
|
||||
var database_val = (database ||
|
||||
database_select.val());
|
||||
if (!(login_val && password_val)) {
|
||||
return;
|
||||
}
|
||||
var session = new Sao.Session(database_val,
|
||||
login_val);
|
||||
var prm = session.do_login(login_val, password_val);
|
||||
prm.done(function() {
|
||||
parent_dfd.resolve(session);
|
||||
});
|
||||
login_div.dialog('close');
|
||||
};
|
||||
var ajax_prm = jQuery.ajax({
|
||||
'contentType': 'application/json',
|
||||
'data': JSON.stringify(args),
|
||||
'dataType': 'json',
|
||||
'url': '/' + this.database,
|
||||
'type': 'post'
|
||||
|
||||
var keydown = function(ev) {
|
||||
if (ev.which === 13)
|
||||
ok_func();
|
||||
};
|
||||
|
||||
var fill_database = function() {
|
||||
jQuery.when(Sao.DB.list()).then(function(databases) {
|
||||
databases.forEach(function(database) {
|
||||
database_select.append(jQuery('<option/>', {
|
||||
'value': database,
|
||||
'text': database
|
||||
}));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
login_div = jQuery('<div/>', {
|
||||
'class': 'login'
|
||||
});
|
||||
if (!database) {
|
||||
login_div.append(jQuery('<label/>', {
|
||||
'text': 'Database:' // TODO translation
|
||||
}));
|
||||
database_select = jQuery('<select/>');
|
||||
login_div.append(database_select);
|
||||
fill_database();
|
||||
login_div.append(jQuery('<br/>'));
|
||||
}
|
||||
|
||||
login_div.append(jQuery('<label/>', {
|
||||
'text': 'Login:' // TODO translation
|
||||
}));
|
||||
login_input = jQuery('<input/>', {
|
||||
'type': 'input',
|
||||
'id': 'login',
|
||||
'val': login
|
||||
});
|
||||
login_input.keydown(keydown);
|
||||
login_div.append(login_input);
|
||||
login_div.append(jQuery('<br/>'));
|
||||
|
||||
login_div.append(jQuery('<label/>', {
|
||||
'text': 'Password:'
|
||||
}));
|
||||
password_input = jQuery('<input/>', {
|
||||
'type': 'password',
|
||||
'id': 'password'
|
||||
});
|
||||
password_input.keydown(keydown);
|
||||
login_div.append(password_input);
|
||||
login_div.append(jQuery('<br/>'));
|
||||
|
||||
login_div.dialog({
|
||||
'title': 'Login', // TODO translation
|
||||
'modal': true,
|
||||
'buttons': {
|
||||
'Cancel': function() {
|
||||
jQuery(this).dialog('close');
|
||||
},
|
||||
'OK': ok_func
|
||||
},
|
||||
'open': function() {
|
||||
if (login) {
|
||||
password_input.focus();
|
||||
} else {
|
||||
login_input.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var ajax_success = function(data) {
|
||||
if (data === null) {
|
||||
Sao.warning('Unable to reach the server');
|
||||
dfd.reject();
|
||||
} else if (data.error) {
|
||||
console.log('ERROR');
|
||||
Sao.error(data.error[0], data.error[1]);
|
||||
dfd.reject();
|
||||
} else {
|
||||
if (!data.result) {
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
} else {
|
||||
this.user_id = data.result[0];
|
||||
this.session = data.result[1];
|
||||
}
|
||||
dfd.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
Sao.Session.renew_credentials = function(session, parent_dfd) {
|
||||
var login_div, password_input;
|
||||
|
||||
var ok_func = function() {
|
||||
var password_val = password_input.val();
|
||||
var prm = session.do_login(session.login, password_val);
|
||||
prm.done(function() {
|
||||
parent_dfd.resolve();
|
||||
});
|
||||
login_div.dialog('close');
|
||||
};
|
||||
ajax_prm.success(ajax_success.bind(this));
|
||||
ajax_prm.error(dfd.reject);
|
||||
return dfd.promise();
|
||||
},
|
||||
do_logout: function() {
|
||||
if (!(this.user_id && this.session)) {
|
||||
return;
|
||||
}
|
||||
var keydown = function(ev) {
|
||||
if (ev.which === 13)
|
||||
ok_func();
|
||||
};
|
||||
|
||||
login_div = jQuery('<div/>', {
|
||||
'class': 'login'
|
||||
});
|
||||
login_div.append(jQuery('<label/>', {
|
||||
'text': 'Password:'
|
||||
}));
|
||||
password_input = jQuery('<input/>', {
|
||||
'type': 'password',
|
||||
'id': 'password'
|
||||
});
|
||||
password_input.keydown(keydown);
|
||||
login_div.append(password_input);
|
||||
login_div.append(jQuery('<br/>'));
|
||||
|
||||
login_div.dialog({
|
||||
'title': 'Login', // TODO translation
|
||||
'modal': true,
|
||||
'buttons': {
|
||||
'Cancel': function() {
|
||||
jQuery(this).dialog('close');
|
||||
},
|
||||
'OK': ok_func
|
||||
},
|
||||
'open': function() {
|
||||
password_input.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Sao.Session.current_session = null;
|
||||
|
||||
Sao.DB = {};
|
||||
|
||||
Sao.DB.list = function() {
|
||||
var args = {
|
||||
'method': 'common.db.logout',
|
||||
'method': 'common.db.list',
|
||||
'params': []
|
||||
};
|
||||
var prm = Sao.rpc(this, args);
|
||||
this.database = null;
|
||||
this.login = null;
|
||||
this.user_id = null;
|
||||
this.session = null;
|
||||
return prm;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.Session.get_credentials = function(parent_dfd) {
|
||||
var login; // TODO use cookie
|
||||
var database = window.location.hash.replace(
|
||||
/^(#(!|))/, '') || null;
|
||||
var database_div, database_select;
|
||||
var login_div, login_input, password_input;
|
||||
|
||||
var ok_func = function() {
|
||||
var login_val = login_input.val();
|
||||
var password_val = password_input.val();
|
||||
var database_val = (database ||
|
||||
database_select.val());
|
||||
if (!(login_val && password_val)) {
|
||||
return;
|
||||
}
|
||||
var session = new Sao.Session(database_val,
|
||||
login_val);
|
||||
var prm = session.do_login(login_val, password_val);
|
||||
prm.done(function() {
|
||||
parent_dfd.resolve(session);
|
||||
});
|
||||
login_div.dialog('close');
|
||||
return Sao.rpc(args);
|
||||
};
|
||||
|
||||
var keydown = function(ev) {
|
||||
if (ev.which === 13)
|
||||
ok_func();
|
||||
};
|
||||
|
||||
var fill_database = function() {
|
||||
$.when(Sao.DB.list()).then(function(databases) {
|
||||
databases.forEach(function(database) {
|
||||
database_select.append($('<option/>', {
|
||||
'value': database,
|
||||
'text': database
|
||||
}));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
login_div = $('<div/>', {
|
||||
'class': 'login'
|
||||
});
|
||||
if (!database) {
|
||||
login_div.append($('<label/>', {
|
||||
'text': 'Database:' // TODO translation
|
||||
}));
|
||||
database_select = $('<select/>');
|
||||
login_div.append(database_select);
|
||||
fill_database();
|
||||
login_div.append($('<br/>'));
|
||||
}
|
||||
|
||||
login_div.append($('<label/>', {
|
||||
'text': 'Login:' // TODO translation
|
||||
}));
|
||||
login_input = $('<input/>', {
|
||||
'type': 'input',
|
||||
'id': 'login',
|
||||
'val': login
|
||||
});
|
||||
login_input.keydown(keydown);
|
||||
login_div.append(login_input);
|
||||
login_div.append($('<br/>'));
|
||||
|
||||
login_div.append($('<label/>', {
|
||||
'text': 'Password:'
|
||||
}));
|
||||
password_input = $('<input/>', {
|
||||
'type': 'password',
|
||||
'id': 'password'
|
||||
});
|
||||
password_input.keydown(keydown);
|
||||
login_div.append(password_input);
|
||||
login_div.append($('<br/>'));
|
||||
|
||||
login_div.dialog({
|
||||
'title': 'Login', // TODO translation
|
||||
'modal': true,
|
||||
'buttons': {
|
||||
'Cancel': function() {
|
||||
$(this).dialog('close');
|
||||
},
|
||||
'OK': ok_func
|
||||
},
|
||||
'open': function() {
|
||||
if (login) {
|
||||
password_input.focus();
|
||||
} else {
|
||||
login_input.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Sao.Session.renew_credentials = function(session, parent_dfd) {
|
||||
var login_div, password_input;
|
||||
|
||||
var ok_func = function() {
|
||||
var password_val = password_input.val();
|
||||
var prm = session.do_login(session.login, password_val);
|
||||
prm.done(function() {
|
||||
parent_dfd.resolve();
|
||||
});
|
||||
login_div.dialog('close');
|
||||
};
|
||||
var keydown = function(ev) {
|
||||
if (ev.which === 13)
|
||||
ok_func();
|
||||
};
|
||||
|
||||
login_div = $('<div/>', {
|
||||
'class': 'login'
|
||||
});
|
||||
login_div.append($('<label/>', {
|
||||
'text': 'Password:'
|
||||
}));
|
||||
password_input = $('<input/>', {
|
||||
'type': 'password',
|
||||
'id': 'password'
|
||||
});
|
||||
password_input.keydown(keydown);
|
||||
login_div.append(password_input);
|
||||
login_div.append($('<br/>'));
|
||||
|
||||
login_div.dialog({
|
||||
'title': 'Login', // TODO translation
|
||||
'modal': true,
|
||||
'buttons': {
|
||||
'Cancel': function() {
|
||||
$(this).dialog('close');
|
||||
},
|
||||
'OK': ok_func
|
||||
},
|
||||
'open': function() {
|
||||
password_input.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Sao.Session.current_session = null;
|
||||
|
||||
Sao.DB = {};
|
||||
|
||||
Sao.DB.list = function() {
|
||||
var args = {
|
||||
'method': 'common.db.list',
|
||||
'params': []
|
||||
};
|
||||
return Sao.rpc(args);
|
||||
};
|
||||
}());
|
||||
|
|
88
js/tab.js
88
js/tab.js
|
@ -1,50 +1,52 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.Tab = Class(Object, {
|
||||
init: function() {
|
||||
}
|
||||
});
|
||||
Sao.Tab = Sao.class_(Object, {
|
||||
init: function() {
|
||||
}
|
||||
});
|
||||
|
||||
Sao.Tab.counter = 0;
|
||||
Sao.Tab.counter = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
jQuery('#tabs').tabs();
|
||||
tab.id = '#tab-' + Sao.Tab.counter++;
|
||||
jQuery('#tabs').tabs('add', tab.id, tab.name);
|
||||
jQuery(tab.id).html(tab.el);
|
||||
jQuery('#tabs').tabs('select', tab.id);
|
||||
};
|
||||
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);
|
||||
}
|
||||
jQuery('#tabs').tabs();
|
||||
tab.id = '#tab-' + Sao.Tab.counter++;
|
||||
jQuery('#tabs').tabs('add', tab.id, tab.name);
|
||||
jQuery(tab.id).html(tab.el);
|
||||
jQuery('#tabs').tabs('select', tab.id);
|
||||
};
|
||||
|
||||
Sao.Tab.Form = Class(Sao.Tab, {
|
||||
init: function(model_name, attributes) {
|
||||
Sao.Tab.Form._super.init.call(this);
|
||||
var screen = new Sao.Screen(model_name, attributes);
|
||||
this.screen = screen;
|
||||
this.attributes = jQuery.extend({}, attributes);
|
||||
this.name = attributes.name; // XXX use screen current view title
|
||||
var el = $('<div/>', {
|
||||
'class': 'form'
|
||||
});
|
||||
this.el = el;
|
||||
this.screen.load_next_view().pipe(function() {
|
||||
return screen.switch_view();
|
||||
}).done(function() {
|
||||
el.html(screen.el);
|
||||
}).done(function() {
|
||||
screen.search_filter().done(function() {
|
||||
screen.display();
|
||||
Sao.Tab.Form = Sao.class_(Sao.Tab, {
|
||||
init: function(model_name, attributes) {
|
||||
Sao.Tab.Form._super.init.call(this);
|
||||
var screen = new Sao.Screen(model_name, attributes);
|
||||
this.screen = screen;
|
||||
this.attributes = jQuery.extend({}, attributes);
|
||||
this.name = attributes.name; // XXX use screen current view title
|
||||
var el = jQuery('<div/>', {
|
||||
'class': 'form'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
this.el = el;
|
||||
this.screen.load_next_view().pipe(function() {
|
||||
return screen.switch_view();
|
||||
}).done(function() {
|
||||
el.html(screen.el);
|
||||
}).done(function() {
|
||||
screen.search_filter().done(function() {
|
||||
screen.display();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
|
538
js/view.js
538
js/view.js
|
@ -1,279 +1,287 @@
|
|||
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. */
|
||||
'use strict';
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Sao.View = Class(Object, {
|
||||
init: function(screen, xml) {
|
||||
this.screen = screen;
|
||||
this.view_type = null;
|
||||
this.el = null;
|
||||
}
|
||||
});
|
||||
Sao.View = Sao.class_(Object, {
|
||||
init: function(screen, xml) {
|
||||
this.screen = screen;
|
||||
this.view_type = null;
|
||||
this.el = null;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.View.parse = function(screen, xml, children_field) {
|
||||
switch (xml.children().prop('tagName')) {
|
||||
case 'tree':
|
||||
return new Sao.View.Tree(screen, xml, children_field);
|
||||
}
|
||||
};
|
||||
Sao.View.parse = function(screen, xml, children_field) {
|
||||
switch (xml.children().prop('tagName')) {
|
||||
case 'tree':
|
||||
return new Sao.View.Tree(screen, xml, children_field);
|
||||
case 'form':
|
||||
return new Sao.View.Form(screen, xml, children_field);
|
||||
}
|
||||
};
|
||||
|
||||
Sao.View.tree_column_get = function(type) {
|
||||
switch (type) {
|
||||
default:
|
||||
return Sao.View.Tree.CharColumn;
|
||||
}
|
||||
};
|
||||
Sao.View.tree_column_get = function(type) {
|
||||
return Sao.View.Tree.CharColumn;
|
||||
};
|
||||
|
||||
Sao.View.Tree = Class(Sao.View, {
|
||||
init: function(screen, xml, children_field) {
|
||||
Sao.View.Tree._super.init.call(this, screen, xml);
|
||||
this.view_type = 'tree';
|
||||
this.el = $('<div/>', {
|
||||
'class': 'treeview'
|
||||
});
|
||||
this.expanded = {};
|
||||
this.children_field = children_field;
|
||||
this.keyword_open = xml.children()[0].getAttribute('keyword_open');
|
||||
|
||||
// Columns
|
||||
this.columns = [];
|
||||
this.create_columns(screen.model, xml);
|
||||
|
||||
// Table of records
|
||||
this.table = $('<table/>', {
|
||||
'class': 'tree'
|
||||
});
|
||||
this.el.append(this.table);
|
||||
var thead = $('<thead/>');
|
||||
this.table.append(thead);
|
||||
var tr = $('<tr/>');
|
||||
thead.append(tr);
|
||||
this.columns.forEach(function(column) {
|
||||
var th = $('<th/>', {
|
||||
'text': column.attributes['string']
|
||||
Sao.View.Tree = Sao.class_(Sao.View, {
|
||||
init: function(screen, xml, children_field) {
|
||||
Sao.View.Tree._super.init.call(this, screen, xml);
|
||||
this.view_type = 'tree';
|
||||
this.el = jQuery('<div/>', {
|
||||
'class': 'treeview'
|
||||
});
|
||||
tr.append(th);
|
||||
});
|
||||
this.tbody = $('<tbody/>');
|
||||
this.table.append(this.tbody);
|
||||
this.expanded = {};
|
||||
this.children_field = children_field;
|
||||
this.keyword_open = xml.children()[0].getAttribute('keyword_open');
|
||||
|
||||
// Footer with pagination stuff
|
||||
var footer = $('<div/>', {
|
||||
'class': 'treefooter'
|
||||
});
|
||||
this.previous_button = $('<button/>').button({
|
||||
'disabled': true,
|
||||
'icons': {
|
||||
primary: 'ui-icon-triangle-1-w'
|
||||
},
|
||||
'text': false,
|
||||
'label': 'Previous' //TODO translation
|
||||
});
|
||||
footer.append(this.previous_button);
|
||||
this.pagination = $('<span/>', {
|
||||
text: '0 / 0'
|
||||
});
|
||||
footer.append(this.pagination);
|
||||
this.next_button = $('<button/>').button({
|
||||
'disabled': true,
|
||||
'icons': {
|
||||
primary: 'ui-icon-triangle-1-e'
|
||||
},
|
||||
'text': false,
|
||||
'label': 'Next' //TODO translation
|
||||
});
|
||||
this.pagination.append(this.next_button);
|
||||
this.el.append(footer);
|
||||
},
|
||||
create_columns: function(model, xml) {
|
||||
var self = this;
|
||||
xml.find('tree').children().each(function(pos, child) {
|
||||
if (child.tagName == 'field') {
|
||||
var name = child.getAttribute('name');
|
||||
var attributes = {
|
||||
'name': child.getAttribute('name'),
|
||||
'readonly': child.getAttribute('readonly') == 1,
|
||||
'widget': child.getAttribute('widget'),
|
||||
'tree_invisible': child.getAttribute('tree_invisible') == 1,
|
||||
'expand': child.getAttribute('expand') == 1,
|
||||
'icon': child.getAttribute('icon'),
|
||||
'sum': child.getAttribute('sum'),
|
||||
'width': child.getAttribute('width'),
|
||||
'orientation': child.getAttribute('orientation'),
|
||||
'float_time': child.getAttribute('float_time'),
|
||||
'pre_validate': child.getAttribute('pre_validate') == 1,
|
||||
'completion': child.getAttribute('completion') == 1
|
||||
};
|
||||
var attribute_names = ['relation', 'domain', 'selection',
|
||||
'relation_field', 'string', 'views', 'invisible',
|
||||
'add_remove', 'sort', 'context', 'filename'];
|
||||
for (var i in attribute_names) {
|
||||
var attr = attribute_names[i];
|
||||
if ((attr in model.fields[name].description) &&
|
||||
(child.getAttribute(attr) == null)) {
|
||||
attributes[attr] = model.fields[name].description[attr];
|
||||
// Columns
|
||||
this.columns = [];
|
||||
this.create_columns(screen.model, xml);
|
||||
|
||||
// Table of records
|
||||
this.table = jQuery('<table/>', {
|
||||
'class': 'tree'
|
||||
});
|
||||
this.el.append(this.table);
|
||||
var thead = jQuery('<thead/>');
|
||||
this.table.append(thead);
|
||||
var tr = jQuery('<tr/>');
|
||||
thead.append(tr);
|
||||
this.columns.forEach(function(column) {
|
||||
var th = jQuery('<th/>', {
|
||||
'text': column.attributes.string
|
||||
});
|
||||
tr.append(th);
|
||||
});
|
||||
this.tbody = jQuery('<tbody/>');
|
||||
this.table.append(this.tbody);
|
||||
|
||||
// Footer with pagination stuff
|
||||
var footer = jQuery('<div/>', {
|
||||
'class': 'treefooter'
|
||||
});
|
||||
this.previous_button = jQuery('<button/>').button({
|
||||
'disabled': true,
|
||||
'icons': {
|
||||
primary: 'ui-icon-triangle-1-w'
|
||||
},
|
||||
'text': false,
|
||||
'label': 'Previous' //TODO translation
|
||||
});
|
||||
footer.append(this.previous_button);
|
||||
this.pagination = jQuery('<span/>', {
|
||||
text: '0 / 0'
|
||||
});
|
||||
footer.append(this.pagination);
|
||||
this.next_button = jQuery('<button/>').button({
|
||||
'disabled': true,
|
||||
'icons': {
|
||||
primary: 'ui-icon-triangle-1-e'
|
||||
},
|
||||
'text': false,
|
||||
'label': 'Next' //TODO translation
|
||||
});
|
||||
this.pagination.append(this.next_button);
|
||||
this.el.append(footer);
|
||||
},
|
||||
create_columns: function(model, xml) {
|
||||
var self = this;
|
||||
xml.find('tree').children().each(function(pos, child) {
|
||||
var attributes, column;
|
||||
if (child.tagName == 'field') {
|
||||
var name = child.getAttribute('name');
|
||||
attributes = {
|
||||
'name': child.getAttribute('name'),
|
||||
'readonly': child.getAttribute('readonly') == 1,
|
||||
'widget': child.getAttribute('widget'),
|
||||
'tree_invisible': child.getAttribute(
|
||||
'tree_invisible') == 1,
|
||||
'expand': child.getAttribute('expand') == 1,
|
||||
'icon': child.getAttribute('icon'),
|
||||
'sum': child.getAttribute('sum'),
|
||||
'width': child.getAttribute('width'),
|
||||
'orientation': child.getAttribute('orientation'),
|
||||
'float_time': child.getAttribute('float_time'),
|
||||
'pre_validate': child.getAttribute('pre_validate') == 1,
|
||||
'completion': child.getAttribute('completion') == 1
|
||||
};
|
||||
var attribute_names = ['relation', 'domain', 'selection',
|
||||
'relation_field', 'string', 'views', 'invisible',
|
||||
'add_remove', 'sort', 'context', 'filename'];
|
||||
for (var i in attribute_names) {
|
||||
var attr = attribute_names[i];
|
||||
if ((attr in model.fields[name].description) &&
|
||||
(child.getAttribute(attr) === null)) {
|
||||
attributes[attr] = model.fields[name]
|
||||
.description[attr];
|
||||
}
|
||||
}
|
||||
var ColumnFactory = Sao.View.tree_column_get(
|
||||
attributes.widget);
|
||||
column = new ColumnFactory(model, attributes);
|
||||
} else if (child.tagName == 'button') {
|
||||
attributes = {
|
||||
'help': child.getAttribute('help'),
|
||||
'string': child.getAttribute('string'),
|
||||
'confirm': child.getAttribute('confirm'),
|
||||
'name': child.getAttribute('name')
|
||||
};
|
||||
column = new Sao.View.Tree.ButtonColumn(attributes);
|
||||
}
|
||||
var ColumnFactory = Sao.View.tree_column_get(
|
||||
attributes['widget']);
|
||||
var column = new ColumnFactory(model, attributes);
|
||||
} else if (child.tagName == 'button') {
|
||||
var attributes = {
|
||||
'help': child.getAttribute('help'),
|
||||
'string': child.getAttribute('string'),
|
||||
'confirm': child.getAttribute('confirm'),
|
||||
'name': child.getAttribute('name')
|
||||
};
|
||||
var column = new Sao.View.Tree.ButtonColumn(attributes);
|
||||
}
|
||||
self.columns.push(column);
|
||||
});
|
||||
},
|
||||
display: function() {
|
||||
this.tbody.empty();
|
||||
var add_row = function(record, pos, group) {
|
||||
var tree_row = new Sao.View.Tree.Row(this, record, pos);
|
||||
tree_row.display();
|
||||
};
|
||||
this.screen.group.forEach(add_row.bind(this));
|
||||
},
|
||||
switch_: function(path) {
|
||||
this.screen.row_activate();
|
||||
},
|
||||
select_changed: function(record) {
|
||||
this.screen.current_record = record;
|
||||
// TODO validate if editable
|
||||
// TODO update_children
|
||||
}
|
||||
});
|
||||
|
||||
Sao.View.Tree.Row = Class(Object, {
|
||||
init: function(tree, record, pos, parent) {
|
||||
this.tree = tree;
|
||||
this.record = record;
|
||||
this.children_field = tree.children_field;
|
||||
this.expander = null;
|
||||
this.expander_icon = null;
|
||||
if (parent) {
|
||||
var path = jQuery.extend([], parent.path.split('.'));
|
||||
} else
|
||||
var path = [];
|
||||
path.push(pos);
|
||||
this.path = path.join('.');
|
||||
this.el = $('<tr/>');
|
||||
this.el.click(this.select_row.bind(this));
|
||||
var switch_ = function() {
|
||||
this.el.addClass('ui-state-highlight');
|
||||
this.tree.select_changed(this.record);
|
||||
this.tree.switch_(path);
|
||||
};
|
||||
this.el.dblclick(switch_.bind(this));
|
||||
},
|
||||
is_expanded: function() {
|
||||
return (this.path in this.tree.expanded);
|
||||
},
|
||||
display: function() {
|
||||
console.log(this.path);
|
||||
var depth = this.path.split('.').length;
|
||||
for (var i = 0; i < this.tree.columns.length; i++) {
|
||||
var td = $('<td/>');
|
||||
if ((i == 0) && this.children_field) {
|
||||
if (this.is_expanded()) {
|
||||
var expanded = 'ui-icon-minus';
|
||||
} else
|
||||
var expanded = 'ui-icon-plus';
|
||||
this.expander = $('<span/>', {
|
||||
'class': 'expander'
|
||||
});
|
||||
this.expander.html(' ');
|
||||
// 16 == minimum width of icon
|
||||
this.expander.css('width', ((depth * 10) + 16) + 'px');
|
||||
this.expander.css('float', 'left');
|
||||
this.expander.click(this.toggle_row.bind(this));
|
||||
this.expander_icon = $('<i/>', {
|
||||
'class': 'ui-icon ' + expanded
|
||||
});
|
||||
this.expander.append(this.expander_icon);
|
||||
this.expander_icon.css('float', 'right');
|
||||
td.append(this.expander);
|
||||
var update_expander = function() {
|
||||
if (jQuery.isEmptyObject(
|
||||
this.record.field_get(this.children_field))) {
|
||||
|
||||
this.expander_icon.hide();
|
||||
}
|
||||
};
|
||||
this.record.load(this.children_field).done(
|
||||
update_expander.bind(this));
|
||||
}
|
||||
var column = this.tree.columns[i];
|
||||
td.append(column.render(this.record));
|
||||
this.el.append(td);
|
||||
}
|
||||
this.tree.tbody.append(this.el);
|
||||
if (this.is_expanded()) {
|
||||
var add_children = function() {
|
||||
var add_row = function(record, pos, group) {
|
||||
var tree_row = new Sao.View.Tree.Row(this.tree, record,
|
||||
pos, this);
|
||||
tree_row.display();
|
||||
};
|
||||
var children = this.record.field_get_client(children_field);
|
||||
children.forEach(add_row.bind(this));
|
||||
self.columns.push(column);
|
||||
});
|
||||
},
|
||||
display: function() {
|
||||
this.tbody.empty();
|
||||
var add_row = function(record, pos, group) {
|
||||
var tree_row = new Sao.View.Tree.Row(this, record, pos);
|
||||
tree_row.display();
|
||||
};
|
||||
var children_field = this.children_field;
|
||||
console.log('Load children of ' + this.path);
|
||||
this.record.load(this.children_field).done(add_children.bind(this));
|
||||
this.screen.group.forEach(add_row.bind(this));
|
||||
},
|
||||
switch_: function(path) {
|
||||
this.screen.row_activate();
|
||||
},
|
||||
select_changed: function(record) {
|
||||
this.screen.current_record = record;
|
||||
// TODO validate if editable
|
||||
// TODO update_children
|
||||
}
|
||||
},
|
||||
toggle_row: function() {
|
||||
if (this.is_expanded()) {
|
||||
this.expander_icon.removeClass('ui-icon-minus');
|
||||
this.expander_icon.addClass('ui-icon-plus');
|
||||
delete this.tree.expanded[this.path];
|
||||
} else {
|
||||
this.expander_icon.removeClass('ui-icon-plus');
|
||||
this.expander_icon.addClass('ui-icon-minus');
|
||||
this.tree.expanded[this.path] = this;
|
||||
}
|
||||
this.tree.display();
|
||||
},
|
||||
select_row: function() {
|
||||
this.el.toggleClass('ui-state-highlight');
|
||||
if (this.el.hasClass('ui-state-highlight')) {
|
||||
this.tree.select_changed(this.record);
|
||||
} else {
|
||||
this.tree.select_changed(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Sao.View.Tree.CharColumn = Class(Object, {
|
||||
init: function(model, attributes) {
|
||||
this.type = 'field';
|
||||
this.field = model.fields[attributes['name']];
|
||||
this.attributes = attributes;
|
||||
},
|
||||
render: function(record) {
|
||||
var cell = $('<span/>');
|
||||
var update_text = function() {
|
||||
cell.text(this.field.get_client(record));
|
||||
};
|
||||
record.load(this.attributes.name).done(update_text.bind(this));
|
||||
return cell;
|
||||
}
|
||||
});
|
||||
Sao.View.Tree.Row = Sao.class_(Object, {
|
||||
init: function(tree, record, pos, parent) {
|
||||
this.tree = tree;
|
||||
this.record = record;
|
||||
this.children_field = tree.children_field;
|
||||
this.expander = null;
|
||||
this.expander_icon = null;
|
||||
var path = [];
|
||||
if (parent) {
|
||||
path = jQuery.extend([], parent.path.split('.'));
|
||||
}
|
||||
path.push(pos);
|
||||
this.path = path.join('.');
|
||||
this.el = jQuery('<tr/>');
|
||||
this.el.click(this.select_row.bind(this));
|
||||
var switch_ = function() {
|
||||
this.el.addClass('ui-state-highlight');
|
||||
this.tree.select_changed(this.record);
|
||||
this.tree.switch_(path);
|
||||
};
|
||||
this.el.dblclick(switch_.bind(this));
|
||||
},
|
||||
is_expanded: function() {
|
||||
return (this.path in this.tree.expanded);
|
||||
},
|
||||
display: function() {
|
||||
console.log(this.path);
|
||||
var depth = this.path.split('.').length;
|
||||
var update_expander = function() {
|
||||
if (jQuery.isEmptyObject(
|
||||
this.record.field_get(
|
||||
this.children_field))) {
|
||||
|
||||
Sao.View.Tree.ButtonColumn = Class(Object, {
|
||||
init: function(attributes) {
|
||||
this.type = 'button';
|
||||
this.attributes = attributes;
|
||||
},
|
||||
render: function() {
|
||||
var button = $('<button/>', {
|
||||
'class': 'button',
|
||||
'label': this.attributes.string
|
||||
});
|
||||
return button;
|
||||
}
|
||||
});
|
||||
this.expander_icon.hide();
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < this.tree.columns.length; i++) {
|
||||
var td = jQuery('<td/>');
|
||||
if ((i === 0) && this.children_field) {
|
||||
var expanded = 'ui-icon-plus';
|
||||
if (this.is_expanded()) {
|
||||
expanded = 'ui-icon-minus';
|
||||
}
|
||||
this.expander = jQuery('<span/>', {
|
||||
'class': 'expander'
|
||||
});
|
||||
this.expander.html(' ');
|
||||
// 16 == minimum width of icon
|
||||
this.expander.css('width', ((depth * 10) + 16) + 'px');
|
||||
this.expander.css('float', 'left');
|
||||
this.expander.click(this.toggle_row.bind(this));
|
||||
this.expander_icon = jQuery('<i/>', {
|
||||
'class': 'ui-icon ' + expanded
|
||||
});
|
||||
this.expander.append(this.expander_icon);
|
||||
this.expander_icon.css('float', 'right');
|
||||
td.append(this.expander);
|
||||
this.record.load(this.children_field).done(
|
||||
update_expander.bind(this));
|
||||
}
|
||||
var column = this.tree.columns[i];
|
||||
td.append(column.render(this.record));
|
||||
this.el.append(td);
|
||||
}
|
||||
this.tree.tbody.append(this.el);
|
||||
if (this.is_expanded()) {
|
||||
var add_children = function() {
|
||||
var add_row = function(record, pos, group) {
|
||||
var tree_row = new Sao.View.Tree.Row(this.tree, record,
|
||||
pos, this);
|
||||
tree_row.display();
|
||||
};
|
||||
var children = this.record.field_get_client(children_field);
|
||||
children.forEach(add_row.bind(this));
|
||||
};
|
||||
var children_field = this.children_field;
|
||||
console.log('Load children of ' + this.path);
|
||||
this.record.load(this.children_field).done(
|
||||
add_children.bind(this));
|
||||
}
|
||||
},
|
||||
toggle_row: function() {
|
||||
if (this.is_expanded()) {
|
||||
this.expander_icon.removeClass('ui-icon-minus');
|
||||
this.expander_icon.addClass('ui-icon-plus');
|
||||
delete this.tree.expanded[this.path];
|
||||
} else {
|
||||
this.expander_icon.removeClass('ui-icon-plus');
|
||||
this.expander_icon.addClass('ui-icon-minus');
|
||||
this.tree.expanded[this.path] = this;
|
||||
}
|
||||
this.tree.display();
|
||||
},
|
||||
select_row: function() {
|
||||
this.el.toggleClass('ui-state-highlight');
|
||||
if (this.el.hasClass('ui-state-highlight')) {
|
||||
this.tree.select_changed(this.record);
|
||||
} else {
|
||||
this.tree.select_changed(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Sao.View.Tree.CharColumn = Sao.class_(Object, {
|
||||
init: function(model, attributes) {
|
||||
this.type = 'field';
|
||||
this.field = model.fields[attributes.name];
|
||||
this.attributes = attributes;
|
||||
},
|
||||
render: function(record) {
|
||||
var cell = jQuery('<span/>');
|
||||
var update_text = function() {
|
||||
cell.text(this.field.get_client(record));
|
||||
};
|
||||
record.load(this.attributes.name).done(update_text.bind(this));
|
||||
return cell;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.View.Tree.ButtonColumn = Sao.class_(Object, {
|
||||
init: function(attributes) {
|
||||
this.type = 'button';
|
||||
this.attributes = attributes;
|
||||
},
|
||||
render: function() {
|
||||
var button = jQuery('<button/>', {
|
||||
'class': 'button',
|
||||
'label': this.attributes.string
|
||||
});
|
||||
return button;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.View.Form = Sao.class_(Sao.View, {});
|
||||
}());
|
||||
|
|
31
package.json
Normal file
31
package.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "sao",
|
||||
"title": "sao",
|
||||
"description": "Tryton webclient",
|
||||
"version": "0.0.1",
|
||||
"homepage": "http://www.tryton.org/",
|
||||
"author": {
|
||||
"name": "Tryton"
|
||||
},
|
||||
"repository": {
|
||||
"type": "hg",
|
||||
"url": "http://hg.tryton.org/sandbox/sao"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://bugs.tryton.org/"
|
||||
},
|
||||
"licenses": ["GPL-3"],
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/grunt"
|
||||
},
|
||||
"dependencies": {
|
||||
"jquery": "~1.8.3",
|
||||
"jquery-core": "~1.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.0",
|
||||
"grunt-contrib-jshint": "~0.1.0",
|
||||
"grunt-contrib-nodeunit": "~0.1.0"
|
||||
},
|
||||
"keywords": ["tryton"]
|
||||
}
|
8
tests/.jshintrc
Normal file
8
tests/.jshintrc
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"browser": true,
|
||||
"jquery": true,
|
||||
"predef": [
|
||||
"QUnit",
|
||||
"Sao"
|
||||
]
|
||||
}
|
1643
tests/sao.js
1643
tests/sao.js
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue