[MERGE] share, needs style fixing
bzr revid: al@openerp.com-20111025100607-fub4h85n8w20omth
This commit is contained in:
@@ -40,10 +40,6 @@ class share_wizard_portal(osv.osv_memory):
|
||||
_columns = {
|
||||
'user_ids': fields.many2many('res.users', 'share_wizard_res_user_rel', 'share_id', 'user_id', 'Existing users', domain=[('share', '=', True)]),
|
||||
'group_ids': fields.many2many('res.groups', 'share_wizard_res_group_rel', 'share_id', 'group_id', 'Existing groups', domain=[('share', '=', False)]),
|
||||
|
||||
# no clean way to extend selection yet, copy the field.
|
||||
'user_type': fields.selection(_user_type_selection,'Users to share with',
|
||||
help="Select the type of user(s) you would like to share data with."),
|
||||
}
|
||||
|
||||
def is_portal_manager(self, cr, uid, context=None):
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="share.share_step1_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/group[@name='emails_group']" position="before">
|
||||
<group name="groups_group" colspan="4" col="4" groups="portal.group_portal_manager">
|
||||
<separator colspan="4" string="Who do you want to share with?"/>
|
||||
<field name="user_type" />
|
||||
</group>
|
||||
<xpath expr="/form/group[@name='emails_group']" position="after">
|
||||
<group name="user_group" colspan="4" attrs="{'invisible':[('user_type','!=','existing')]}">
|
||||
<field colspan="4" nolabel="1" name="user_ids" mode="tree">
|
||||
<tree string="Existing users">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2010-2011 OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
{
|
||||
"name" : "Web Share",
|
||||
"version" : "1.5",
|
||||
"version" : "2.0",
|
||||
"depends" : ["base", "mail"],
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Hidden',
|
||||
@@ -53,6 +54,8 @@ synchronization with other companies, etc.
|
||||
'installable': True,
|
||||
'web': True,
|
||||
'certificate' : '001301246528927038493',
|
||||
'js': ['static/src/js/share.js'],
|
||||
'css': ['static/src/css/share.css'],
|
||||
'images': ['images/share_wizard.jpeg','images/sharing_wizard_step1.jpeg', 'images/sharing_wizard_step2.jpeg'],
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
.openerp li.oe-share {
|
||||
background: url(../img/share.png) no-repeat;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.openerp a.oe-share {
|
||||
background: url(../img/share.png) no-repeat;
|
||||
display: block;
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
openerp.share = function(instance) {
|
||||
var QWeb = instance.web.qweb;
|
||||
QWeb.add_template('/share/static/src/xml/share.xml');
|
||||
|
||||
function launch_wizard(self, view) {
|
||||
var action = view.widget_parent.action;
|
||||
var Share = new instance.web.DataSet(self, 'share.wizard', view.dataset.get_context());
|
||||
var domain = view.dataset.domain;
|
||||
|
||||
if (view.fields_view.type == 'form') {
|
||||
domain = new instance.web.CompoundDomain(domain, [['id', '=', view.datarecord.id]]);
|
||||
}
|
||||
|
||||
Share.create({
|
||||
name: action.name,
|
||||
domain: domain,
|
||||
action_id: action.id,
|
||||
}, function(result) {
|
||||
var share_id = result.result;
|
||||
var step1 = Share.call('go_step_1', [[share_id],], function(result) {
|
||||
var action = result;
|
||||
self.do_action(action);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var _has_share = null;
|
||||
function if_has_share(yes, no) {
|
||||
if (!_has_share) {
|
||||
_has_share = $.Deferred(function() {
|
||||
var self = this;
|
||||
var session = instance.webclient.session;
|
||||
session.on_session_invalid.add_last(function() { _has_share = null; });
|
||||
var func = new instance.web.Model(session, "share.wizard").get_func("has_share");
|
||||
func(session.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',
|
||||
}]);
|
||||
});
|
||||
},
|
||||
on_sidebar_click_share: function(item) {
|
||||
var view = this.widget_parent
|
||||
launch_wizard(this, view);
|
||||
},
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
on_click_share: function(e) {
|
||||
e.preventDefault();
|
||||
launch_wizard(this, this.views[this.active_view].controller);
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- vim:fdl=1:
|
||||
-->
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<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>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -1,2 +0,0 @@
|
||||
import controllers
|
||||
import editors
|
||||
@@ -1,49 +0,0 @@
|
||||
import urlparse
|
||||
import cherrypy
|
||||
|
||||
from openobject import rpc
|
||||
from openobject.tools import expose, ast
|
||||
|
||||
import openerp.controllers
|
||||
|
||||
|
||||
|
||||
class ShareWizardController(openerp.controllers.SecuredController):
|
||||
_cp_path = "/share"
|
||||
|
||||
@expose()
|
||||
def index(self, domain, context, view_id, search_domain='[]', action_id=None):
|
||||
context = ast.literal_eval(context)
|
||||
|
||||
if not action_id:
|
||||
# This should not be needed anymore, but just in case users are
|
||||
# running the module with an older version of the web client...
|
||||
|
||||
# to remove soon-ish
|
||||
action_id = rpc.RPCProxy('ir.actions.act_window').search(
|
||||
[('view_id','=',int(view_id))], context=context)
|
||||
if not action_id: return ""
|
||||
|
||||
action_id = action_id[0]
|
||||
|
||||
domain = ast.literal_eval(domain)
|
||||
domain.extend(ast.literal_eval(search_domain))
|
||||
|
||||
scheme, netloc, _, _, _ = urlparse.urlsplit(cherrypy.request.base)
|
||||
share_root_url = urlparse.urlunsplit((
|
||||
scheme, netloc, '/openerp/login',
|
||||
'db=%(dbname)s&user=%(login)s&password=%(password)s', ''))
|
||||
|
||||
context.update(
|
||||
#active_ids=share_wiz_id,
|
||||
#active_id=share_wiz_id[0],
|
||||
_terp_view_name='Share Wizard',
|
||||
share_root_url=share_root_url)
|
||||
Share = rpc.RPCProxy('share.wizard')
|
||||
sharing_view_id = Share.create({
|
||||
'domain': str(domain),
|
||||
'action_id': action_id and int(action_id)
|
||||
}, context)
|
||||
return openerp.controllers.actions.execute(
|
||||
Share.go_step_1([sharing_view_id], context),
|
||||
ids=[sharing_view_id], context=context)
|
||||
@@ -1,94 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import openobject.templating
|
||||
|
||||
class FormEditor(openobject.templating.TemplateEditor):
|
||||
templates = ['/openerp/controllers/templates/form.mako']
|
||||
MAIN_FORM_BODY = u'id="main_form_body"'
|
||||
|
||||
def insert_share_button(self, output):
|
||||
# Insert the share button on the form title H1 line, at the very end,
|
||||
# but only if the user is a member of the sharing group
|
||||
share_opener_insertion = output.index('% endif', output.index(
|
||||
'/view_diagram/process',
|
||||
output.index(self.MAIN_FORM_BODY))) + len('% endif')
|
||||
return output[:share_opener_insertion] + '''
|
||||
<%
|
||||
if 'has_share' not in cp.session:
|
||||
cp.session['has_share'] = rpc.RPCProxy('share.wizard').has_share()
|
||||
%>
|
||||
% if cp.session['has_share'] and buttons.toolbar and not is_dashboard:
|
||||
<a id="share-opener" href="#share" title="${_('Share this in 2 clicks...')}">
|
||||
<img id="share-opener-img" src="/share/static/images/share.png"/>
|
||||
</a>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
jQuery("#share-opener").click(function() {
|
||||
jQuery(this).attr(
|
||||
"href",
|
||||
openobject.http.getURL('/share', {
|
||||
context: jQuery("#_terp_context").val(),
|
||||
domain: jQuery("#_terp_domain").val(),
|
||||
view_id: jQuery("#_terp_view_id").val(),
|
||||
action_id: jQuery("#_terp_action_id").val(),
|
||||
search_domain: jQuery("#_terp_view_type").val() == "form" ?
|
||||
("[('id','=',"+jQuery("#_terp_id").val()+")]") :
|
||||
jQuery("#_terp_search_domain").val(),
|
||||
}));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
\n
|
||||
% endif
|
||||
''' + output[share_opener_insertion:]
|
||||
|
||||
def edit(self, template, template_text):
|
||||
return self.insert_share_button(
|
||||
super(FormEditor, self).edit(template, template_text))
|
||||
|
||||
|
||||
class SidebarEditor(openobject.templating.TemplateEditor):
|
||||
templates = ['/openerp/widgets/templates/sidebar.mako']
|
||||
ADD_SHARE_SECTION = u'id="sidebar"'
|
||||
|
||||
def insert_share_link(self, output):
|
||||
# Insert the link on the line, right after the link to open the
|
||||
# attachment form, but only if the user is a member of the sharing group
|
||||
share_opener_insertion = output.index(
|
||||
'\n',
|
||||
output.index(self.ADD_SHARE_SECTION)) + 1
|
||||
return output[:share_opener_insertion] + '''
|
||||
<%
|
||||
if 'has_share' not in cp.session:
|
||||
cp.session['has_share'] = rpc.RPCProxy('share.wizard').has_share()
|
||||
%>
|
||||
% if cp.session['has_share']:
|
||||
<div id="share-wizard" class="sideheader-a"><h2>${_("Sharing")}</h2></div>
|
||||
<ul class="clean-a">
|
||||
<li>
|
||||
<a id="sharing" href="#share">${_("Share")}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
jQuery("#sharing").click(function() {
|
||||
jQuery(this).attr(
|
||||
"href",
|
||||
openobject.http.getURL('/share', {
|
||||
context: jQuery("#_terp_context").val(),
|
||||
domain: jQuery("#_terp_domain").val(),
|
||||
view_id: jQuery("#_terp_view_id").val(),
|
||||
action_id: jQuery("#_terp_action_id").val(),
|
||||
search_domain: jQuery("#_terp_view_type").val() == "form" ?
|
||||
("[('id','=',"+jQuery("#_terp_id").val()+")]") :
|
||||
jQuery("#_terp_search_domain").val(),
|
||||
}));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
\n
|
||||
% endif
|
||||
''' + output[share_opener_insertion:]
|
||||
|
||||
def edit(self, template, template_text):
|
||||
return self.insert_share_link(
|
||||
super(SidebarEditor, self).edit(template, template_text))
|
||||
@@ -119,24 +119,38 @@ class share_wizard(osv.osv_memory):
|
||||
values['name'] = action.name
|
||||
return super(share_wizard,self).create(cr, uid, values, context=context)
|
||||
|
||||
def share_url_template(self, cr, uid, _ids, context=None):
|
||||
# NOTE: take _ids in parameter to allow usage through browse_record objects
|
||||
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='', context=context)
|
||||
if base_url:
|
||||
base_url += '/?db=%(dbname)s&login=%(login)s'
|
||||
return base_url
|
||||
|
||||
def _share_root_url(self, cr, uid, ids, _fieldname, _args, context=None):
|
||||
result = dict.fromkeys(ids, '')
|
||||
data = dict(dbname=cr.dbname, login='')
|
||||
for this in self.browse(cr, uid, ids, context=context):
|
||||
result[this.id] = this.share_url_template() % data
|
||||
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."),
|
||||
'domain': fields.char('Domain', size=256, help="Optional domain for further data filtering"),
|
||||
'user_type': fields.selection(_user_type_selection,'Users to share with',
|
||||
'user_type': fields.selection(lambda s, *a, **k: s._user_type_selection(*a, **k),'Users to share with', 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,
|
||||
help="Access rights to be granted on the shared documents."),
|
||||
'result_line_ids': fields.one2many('share.wizard.result.line', 'share_wizard_id', 'Summary', readonly=True),
|
||||
'share_root_url': fields.char('Share Access URL', size=512, readonly=True, tooltip='Main access page for users that are granted shared access'),
|
||||
'share_root_url': fields.function(_share_root_url, string='Share Access URL', type='char', size=512, readonly=True,
|
||||
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."),
|
||||
}
|
||||
_defaults = {
|
||||
'user_type' : 'new',
|
||||
'user_type' : 'emails',
|
||||
'domain': lambda self, cr, uid, context, *a: context.get('domain', '[]'),
|
||||
'share_root_url': lambda self, cr, uid, context, *a: context.get('share_root_url') or _('Please specify "share_root_url" in context'),
|
||||
'action_id': lambda self, cr, uid, context, *a: context.get('action_id'),
|
||||
'access_mode': 'readonly',
|
||||
}
|
||||
@@ -537,12 +551,11 @@ class share_wizard(osv.osv_memory):
|
||||
try:
|
||||
domain = safe_eval(wizard_data.domain)
|
||||
if domain:
|
||||
domain_expr = expression.expression(domain)
|
||||
for rel_field, model in fields_relations:
|
||||
related_domain = []
|
||||
if not rel_field: continue
|
||||
for element in domain:
|
||||
if domain_expr._is_leaf(element):
|
||||
if expression.is_leaf(element):
|
||||
left, operator, right = element
|
||||
left = '%s.%s'%(rel_field, left)
|
||||
element = left, operator, right
|
||||
@@ -555,19 +568,6 @@ class share_wizard(osv.osv_memory):
|
||||
raise osv.except_osv(_('Sharing access could not be created'),
|
||||
_('Sorry, the current screen and filter you are trying to share are not supported at the moment.\nYou may want to try a simpler filter.'))
|
||||
|
||||
def _finish_result_lines(self, cr, uid, wizard_data, share_group_id, context=None):
|
||||
"""Perform finalization of the share, and populate the summary"""
|
||||
share_root_url = wizard_data.share_root_url
|
||||
format_url = '%(dbname)s' in share_root_url
|
||||
for result in wizard_data.result_line_ids:
|
||||
# share_root_url may contain placeholders for dbname, login and password
|
||||
share_url = (share_root_url % \
|
||||
{'login': quote_plus(result.user_id.login),
|
||||
'password': '', # kept empty for security reasons
|
||||
'dbname': quote_plus(cr.dbname)}) \
|
||||
if format_url else share_root_url
|
||||
result.write({'share_url': share_url}, context=context)
|
||||
|
||||
def _check_preconditions(self, cr, uid, wizard_data, context=None):
|
||||
self._assert(wizard_data.action_id and wizard_data.access_mode,
|
||||
_('Action and Access Mode are required to create a shared access'),
|
||||
@@ -662,15 +662,6 @@ class share_wizard(osv.osv_memory):
|
||||
# C.
|
||||
self._create_indirect_sharing_rules(cr, current_user, wizard_data, group_id, obj1, context=context)
|
||||
|
||||
# so far, so good -> check summary results and return them
|
||||
self._finish_result_lines(cr, uid, wizard_data, group_id, context=context)
|
||||
|
||||
# update share URL to make it generic
|
||||
generic_share_url = wizard_data.share_root_url % {'dbname': cr.dbname,
|
||||
'login': '',
|
||||
'password': ''}
|
||||
wizard_data.write({'share_root_url': generic_share_url}, context=context)
|
||||
|
||||
# refresh wizard_data
|
||||
wizard_data = self.browse(cr, uid, ids[0], context=context)
|
||||
|
||||
@@ -742,11 +733,20 @@ share_wizard()
|
||||
class share_result_line(osv.osv_memory):
|
||||
_name = 'share.wizard.result.line'
|
||||
_rec_name = 'user_id'
|
||||
|
||||
|
||||
def _share_url(self, cr, uid, ids, _fieldname, _args, context=None):
|
||||
result = dict.fromkeys(ids, '')
|
||||
for this in self.browse(cr, uid, ids, context=context):
|
||||
data = dict(dbname=cr.dbname, login=this.login)
|
||||
result[this.id] = this.share_wizard_id.share_url_template() % data
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'user_id': fields.many2one('res.users', required=True, readonly=True),
|
||||
'login': fields.related('user_id', 'login', string='Login', type='char', size=64, required=True, readonly=True),
|
||||
'password': fields.char('Password', size=64, readonly=True),
|
||||
'share_url': fields.char('Share URL', size=512, required=True),
|
||||
'share_url': fields.function(_share_url, string='Share URL', type='char', size=512),
|
||||
'share_wizard_id': fields.many2one('share.wizard', 'Share Wizard', required=True),
|
||||
'newly_created': fields.boolean('Newly created', readonly=True),
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
<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')]}">
|
||||
<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')]}"/>
|
||||
@@ -78,7 +82,6 @@
|
||||
- 'action_id' (id of action)
|
||||
- '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)!)
|
||||
- 'share_root_url' : URL for direct access to share page (may include %(login)s and %(password)s placeholders)
|
||||
-->
|
||||
<record id="action_share_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Share Wizard</field>
|
||||
@@ -94,7 +97,6 @@
|
||||
- 'action_id' (id of action)
|
||||
- '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)!)
|
||||
- 'share_root_url' : URL for direct access to share page (may include %(login)s and %(password)s placeholders)
|
||||
-->
|
||||
<record id="action_share_wizard_step1" model="ir.actions.act_window">
|
||||
<field name="name">Share Wizard</field>
|
||||
|
||||
Reference in New Issue
Block a user