[MERGE] share_embed by chs
bzr revid: al@openerp.com-20111218155640-54qy546y276xcyop
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user