diff --git a/addons/share/static/src/css/share.css b/addons/share/static/src/css/share.css index 4bd4f1d67e5..8b137891791 100644 --- a/addons/share/static/src/css/share.css +++ b/addons/share/static/src/css/share.css @@ -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; -} diff --git a/addons/share/static/src/js/share.js b/addons/share/static/src/js/share.js index 45cc2bd20ca..b084e82f7c9 100644 --- a/addons/share/static/src/js/share.js +++ b/addons/share/static/src/js/share.js @@ -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); diff --git a/addons/share/static/src/xml/share.xml b/addons/share/static/src/xml/share.xml index 9a1363846a0..d8d3ab506fe 100644 --- a/addons/share/static/src/xml/share.xml +++ b/addons/share/static/src/xml/share.xml @@ -5,9 +5,8 @@ - - - + + diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py index d6fa426f7ab..e115cab2552 100644 --- a/addons/share/wizard/share_wizard.py +++ b/addons/share/wizard/share_wizard.py @@ -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 """ + + """ % { + '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' diff --git a/addons/share/wizard/share_wizard_view.xml b/addons/share/wizard/share_wizard_view.xml index 128b32b07da..330363879cf 100644 --- a/addons/share/wizard/share_wizard_view.xml +++ b/addons/share/wizard/share_wizard_view.xml @@ -23,25 +23,43 @@ + + share.step1.form.link + share.wizard + form + +
+ + + + + + + + +