[MERGE] share_embed by chs

bzr revid: al@openerp.com-20111218155640-54qy546y276xcyop
This commit is contained in:
Antony Lesuisse
2011-12-18 16:56:40 +01:00
5 changed files with 204 additions and 88 deletions
-13
View File
@@ -1,14 +1 @@
.openerp li.oe-share {
background: url(../img/share.png) no-repeat 0 60%;
padding-left: 20px;
}
.openerp a.oe-share {
background: url(../img/share.png) no-repeat center center;
display: block;
float: left;
width: 20px;
height: 20px;
margin-top: 3px;
}
+15 -34
View File
@@ -1,7 +1,8 @@
openerp.share = function(instance) {
function launch_wizard(self, view) {
function launch_wizard(self, view, button) {
var button = button || 'go_step_1';
var action = view.widget_parent.action;
var Share = new instance.web.DataSet(self, 'share.wizard', view.dataset.get_context());
var domain = new instance.web.CompoundDomain(view.dataset.domain);
@@ -16,9 +17,10 @@ function launch_wizard(self, view) {
name: action.name,
domain: result.domain,
action_id: action.id,
view_type: view.fields_view.type,
}, function(result) {
var share_id = result.result;
var step1 = Share.call('go_step_1', [[share_id],], function(result) {
var step1 = Share.call(button, [[share_id],], function(result) {
var action = result;
self.do_action(action);
});
@@ -26,37 +28,15 @@ function launch_wizard(self, view) {
});
}
var _has_share = null;
function if_has_share(yes, no) {
if (!_has_share) {
_has_share = $.Deferred(function() {
var self = this;
instance.connection.on_session_invalid.add_last(function() { _has_share = null; });
var func = new instance.web.Model(null, "share.wizard").get_func("has_share");
func(instance.connection.uid).pipe(function(res) {
if(res) {
self.resolve();
} else {
self.reject();
}
});
});
}
_has_share.done(yes).fail(no);
}
instance.web.Sidebar = instance.web.Sidebar.extend({
add_default_sections: function() {
this._super();
var self = this;
if_has_share(function() {
self.add_items('other', [{
label: 'Share',
callback: self.on_sidebar_click_share,
classname: 'oe-share',
}]);
});
self.add_items('other', [{
label: 'Share',
callback: self.on_sidebar_click_share,
classname: 'oe-share',
}]);
},
on_sidebar_click_share: function(item) {
var view = this.widget_parent
@@ -67,13 +47,14 @@ instance.web.Sidebar = instance.web.Sidebar.extend({
instance.web.ViewManagerAction.include({
start: function() {
var self = this;
if_has_share(function() {
self.$element.find('a.oe-share').click(self.on_click_share);
}, function() {
self.$element.find('a.oe-share').remove();
});
self.$element.find('a.oe-share_link').click(self.on_click_share_link);
self.$element.find('a.oe-share').click(self.on_click_share);
return this._super.apply(this, arguments);
},
on_click_share_link: function(e) {
e.preventDefault();
launch_wizard(this, this.views[this.active_view].controller,'go_step_1_link');
},
on_click_share: function(e) {
e.preventDefault();
launch_wizard(this, this.views[this.active_view].controller);
+2 -3
View File
@@ -5,9 +5,8 @@
<t t-extend="ViewManagerAction">
<t t-jquery=".oe-shortcut-toggle" t-operation="after">
<a class="oe-share" href="#share" title="Share this in 2 clicks...">
<!--<img src="/share/static/src/img/share.png"/>-->
</a>
<a class="oe-share_link" href="#share_link" title="Link or embed"><img src="/share/static/src/img/share.png"/></a>
<a class="oe-share" href="#share" title="Share by email"><img src="/share/static/src/img/share.png"/></a>
</t>
</t>
+132 -27
View File
@@ -22,12 +22,16 @@ import logging
import random
import time
from urllib import quote_plus
import uuid
import simplejson
import tools
from osv import osv, fields
from osv import expression
from tools.translate import _
from tools.safe_eval import safe_eval
import openerp
FULL_ACCESS = ('perm_read', 'perm_write', 'perm_create', 'perm_unlink')
READ_WRITE_ACCESS = ('perm_read', 'perm_write')
@@ -78,7 +82,7 @@ class share_wizard(osv.osv_memory):
def _user_type_selection(self, cr, uid, context=None):
"""Selection values may be easily overridden/extended via inheritance"""
return [('emails','List of emails')]
return [('embedded', 'Direct link or embed code'), ('emails','Emails'), ]
"""Override of create() to auto-compute the action name"""
def create(self, cr, uid, values, context=None):
@@ -101,11 +105,53 @@ class share_wizard(osv.osv_memory):
result[this.id] = this.share_url_template() % data
return result
def _generate_embedded_code(self, wizard, options=None):
cr = wizard._cr
uid = wizard._uid
context = wizard._context
if options is None:
options = {}
js_options = {}
title = options['title'] if 'title' in options else wizard.embed_option_title
search = (options['search'] if 'search' in options else wizard.embed_option_search) if wizard.access_mode != 'readonly' else False
if not title:
js_options['display_title'] = False
if search:
js_options['search_view'] = True
js_options_str = (', ' + simplejson.dumps(js_options)) if js_options else ''
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default=None, context=context)
user = wizard.result_line_ids[0]
return """
<script type="text/javascript" src="http://localhost:8069/web/webclient/js"></script>
<script type="text/javascript">
new openerp.init(%(init)s).web.embed(%(server)s, %(dbname)s, %(login)s, %(password)s,%(action)d%(options)s);
</script> """ % {
'init': simplejson.dumps(openerp.conf.server_wide_modules),
'server': simplejson.dumps(base_url),
'dbname': simplejson.dumps(cr.dbname),
'login': simplejson.dumps(user.login),
'password': simplejson.dumps(user.password),
'action': user.user_id.action_id.id,
'options': js_options_str,
}
def _embed_code(self, cr, uid, ids, _fn, _args, context=None):
result = dict.fromkeys(ids, '')
for this in self.browse(cr, uid, ids, context=context):
result[this.id] = self._generate_embedded_code(this)
return result
_columns = {
'action_id': fields.many2one('ir.actions.act_window', 'Action to share', required=True,
help="The action that opens the screen containing the data you wish to share."),
'view_type': fields.char('Current View Type', size=32, required=True),
'domain': fields.char('Domain', size=256, help="Optional domain for further data filtering"),
'user_type': fields.selection(lambda s, *a, **k: s._user_type_selection(*a, **k),'Users to share with', required=True,
'user_type': fields.selection(lambda s, *a, **k: s._user_type_selection(*a, **k),'Sharing method', required=True,
help="Select the type of user(s) you would like to share data with."),
'new_users': fields.text("Emails"),
'access_mode': fields.selection([('readonly','Can view'),('readwrite','Can edit')],'Access Mode', required=True,
@@ -115,18 +161,39 @@ class share_wizard(osv.osv_memory):
help='Main access page for users that are granted shared access'),
'name': fields.char('Share Title', size=64, required=True, help="Title for the share (displayed to users as menu and shortcut name)"),
'message': fields.text("Personal Message", help="An optional personal message, to be included in the e-mail notification."),
'embed_code': fields.function(_embed_code, type='text'),
'embed_option_title': fields.boolean("Display title"),
'embed_option_search': fields.boolean('Display search view'),
}
_defaults = {
'user_type' : 'emails',
'view_type': 'tree',
'user_type' : 'embedded',
'domain': lambda self, cr, uid, context, *a: context.get('domain', '[]'),
'action_id': lambda self, cr, uid, context, *a: context.get('action_id'),
'access_mode': 'readonly',
'embed_option_title': True,
'embed_option_search': True,
}
def go_step_1_link(self, cr, uid, ids, context=None):
dummy, step1_form_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'share', 'share_step1_form_link')
return {
'name': _('Link or embed your documents'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'share.wizard',
'view_id': False,
'res_id': ids[0],
'views': [(step1_form_view_id, 'form')],
'type': 'ir.actions.act_window',
'target': 'new'
}
def go_step_1(self, cr, uid, ids, context=None):
dummy, step1_form_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'share', 'share_step1_form')
return {
'name': _('Grant instant access to your documents'),
'name': _('Share your documents by email'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'share.wizard',
@@ -155,33 +222,52 @@ class share_wizard(osv.osv_memory):
current_user = user_obj.browse(cr, UID_ROOT, uid, context=context)
created_ids = []
existing_ids = []
for new_user in (wizard_data.new_users or '').split('\n'):
# Ignore blank lines
new_user = new_user.strip()
if not new_user: continue
# Ignore the user if it already exists.
existing = user_obj.search(cr, UID_ROOT, [('login', '=', new_user)])
existing_ids.extend(existing)
if existing:
new_line = { 'user_id': existing[0],
'newly_created': False}
if wizard_data.user_type == 'emails':
for new_user in (wizard_data.new_users or '').split('\n'):
# Ignore blank lines
new_user = new_user.strip()
if not new_user: continue
# Ignore the user if it already exists.
existing = user_obj.search(cr, UID_ROOT, [('login', '=', new_user)])
existing_ids.extend(existing)
if existing:
new_line = { 'user_id': existing[0],
'newly_created': False}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
continue
new_pass = generate_random_pass()
user_id = user_obj.create(cr, UID_ROOT, {
'login': new_user,
'password': new_pass,
'name': new_user,
'user_email': new_user,
'groups_id': [(6,0,[group_id])],
'share': True,
'company_id': current_user.company_id.id
})
new_line = { 'user_id': user_id,
'password': new_pass,
'newly_created': True}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
continue
created_ids.append(user_id)
elif wizard_data.user_type == 'embedded':
new_login = 'embedded-%s' % (uuid.uuid4().hex,)
new_pass = generate_random_pass()
user_id = user_obj.create(cr, UID_ROOT, {
'login': new_user,
'password': new_pass,
'name': new_user,
'user_email': new_user,
'groups_id': [(6,0,[group_id])],
'share': True,
'company_id': current_user.company_id.id
'login': new_login,
'password': new_pass,
'name': new_login,
'groups_id': [(6,0,[group_id])],
'share': True,
'company_id': current_user.company_id.id
})
new_line = { 'user_id': user_id,
'password': new_pass,
'newly_created': True}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
created_ids.append(user_id)
return created_ids, existing_ids
def _create_shortcut(self, cr, uid, values, context=None):
@@ -241,21 +327,33 @@ class share_wizard(osv.osv_memory):
def _shared_action_def(self, cr, uid, wizard_data, context=None):
copied_action = wizard_data.action_id
if wizard_data.access_mode == 'readonly':
view_mode = wizard_data.view_type
view_id = copied_action.view_id.id if copied_action.view_id.type == wizard_data.view_type else False
else:
view_mode = copied_action.view_mode
view_id = copied_action.view_id.id
action_def = {
'name': wizard_data.name,
'domain': copied_action.domain,
'context': self._cleanup_action_context(wizard_data.action_id.context, uid),
'res_model': copied_action.res_model,
'view_mode': copied_action.view_mode,
'view_mode': view_mode,
'view_type': copied_action.view_type,
'search_view_id': copied_action.search_view_id.id,
'view_id': copied_action.view_id.id,
'search_view_id': copied_action.search_view_id.id if wizard_data.access_mode != 'readonly' else False,
'view_id': view_id,
'auto_search': True,
}
if copied_action.view_ids:
action_def['view_ids'] = [(0,0,{'sequence': x.sequence,
'view_mode': x.view_mode,
'view_id': x.view_id.id })
for x in copied_action.view_ids]
for x in copied_action.view_ids
if (wizard_data.access_mode != 'readonly' or x.view_mode == wizard_data.view_type)
]
return action_def
def _setup_action_and_shortcut(self, cr, uid, wizard_data, user_ids, make_home, context=None):
@@ -660,6 +758,8 @@ class share_wizard(osv.osv_memory):
msg_ids = []
for result_line in wizard_data.result_line_ids:
email_to = result_line.user_id.user_email
if not email_to:
continue
subject = wizard_data.name
body = _("Hello,")
body += "\n\n"
@@ -685,7 +785,6 @@ class share_wizard(osv.osv_memory):
body += "--\n"
body += _("OpenERP is a powerful and user-friendly suite of Business Applications (CRM, Sales, HR, etc.)\n"
"It is open source and can be found on http://www.openerp.com.")
msg_ids.append(mail_message.schedule_with_attach(cr, uid,
user.user_email,
[email_to],
@@ -697,6 +796,12 @@ class share_wizard(osv.osv_memory):
mail_message.send(cr, uid, msg_ids, context=context)
self._logger.info('%d share notification(s) sent.', len(msg_ids))
def onchange_embed_options(self, cr, uid, ids, opt_title, opt_search, context=None):
wizard = self.browse(cr, uid, ids[0], context)
options = dict(title=opt_title, search=opt_search)
return {'value': {'embed_code': self._generate_embedded_code(wizard, options)}}
share_wizard()
class share_result_line(osv.osv_memory):
_name = 'share.wizard.result.line'
+55 -11
View File
@@ -23,25 +23,43 @@
</field>
</record>
<record id="share_step1_form_link" model="ir.ui.view">
<field name="name">share.step1.form.link</field>
<field name="model">share.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Link or embed your documents">
<field name="user_type" invisible="1"/>
<separator colspan="4" string="Sharing Options"/>
<group colspan="4" col="4">
<field name="name" colspan="4"/>
<field name="access_mode" colspan="4"/>
</group>
<separator colspan="4"/>
<group colspan="4">
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="go_step_2" string="Share" colspan="1" type="object" icon="gtk-go-forward"/>
</group>
</form>
</field>
</record>
<record id="share_step1_form" model="ir.ui.view">
<field name="name">share.step1.form</field>
<field name="model">share.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Grant instant access to your documents">
<group name="groups_group" colspan="4" col="4">
<separator colspan="4" string="Who do you want to share with?"/>
<field name="user_type" />
</group>
<group colspan="4" name="emails_group" attrs="{'invisible':[('user_type','!=','emails')]}">
<form string="Share by email your documents">
<field name="user_type" invisible="1"/>
<group colspan="4" name="emails_group">
<separator colspan="4" string="Share with these people (one e-mail per line)"/>
<field colspan="4" nolabel="1" name="new_users" attrs="{'required':[('user_type','=','emails')]}"/>
</group>
<separator colspan="4" string="Optional: include a personal message"/>
<group colspan="4" col="4">
<separator colspan="4" string="Optional: include a personal message"/>
<field name="message" colspan="4" nolabel="1"/>
</group>
<separator colspan="4" string="Extra Options"/>
<separator colspan="4" string="Sharing Options"/>
<group colspan="4" col="4">
<field name="name" colspan="4"/>
<field name="access_mode" colspan="4"/>
@@ -61,15 +79,30 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Access granted!">
<separator colspan="4" string="An e-mail notification with instructions has been sent to the following people:"/>
<field name="result_line_ids" nolabel="1" colspan="4" mode="tree">
<field name="user_type" invisible="1"/>
<field name="access_mode" invisible="1"/>
<group colspan="4" col="1" attrs="{'invisible':[('user_type','=','embedded')]}">
<separator string="An e-mail notification with instructions has been sent to the following people:"/>
<field name="result_line_ids" nolabel="1" mode="tree">
<tree string="Summary">
<field name="login"/>
</tree>
<form string="Access info">
<field name="login"/>
</form>
</field>
</field>
</group>
<group colspan="4" col="1" attrs="{'invisible':[('user_type','!=','embedded')]}">
<separator string="Use this link"/>
<field name="share_root_url" nolabel="1"/>
<separator string="Or insert the following code where you want to embed your documents"/>
<group col="4" string="Options">
<field name="embed_option_title" on_change="onchange_embed_options(embed_option_title, embed_option_search)"/>
<field name="embed_option_search" on_change="onchange_embed_options(embed_option_title, embed_option_search)" attrs="{'invisible':[('access_mode','=','readonly')]}"/>
</group>
<field name="embed_code" nolabel="1"/>
</group>
<separator colspan="4"/>
<group colspan="4">
<button special="cancel" string="Close" icon='gtk-ok'/>
@@ -98,6 +131,17 @@
- 'domain' (string expression for full domain to apply as sent to server,
with dynamic data like 'uid' replaced by actual value (i.e. after eval)!)
-->
<record id="action_share_wizard_step1_link" model="ir.actions.act_window">
<field name="name">Share Wizard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">share.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="share_step1_form_link"/>
<field name="target">new</field>
<field name="context">{'default_user_type':'embedded'}</field>
</record>
<record id="action_share_wizard_step1" model="ir.actions.act_window">
<field name="name">Share Wizard</field>
<field name="type">ir.actions.act_window</field>