summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Lesuisse <al@openerp.com>2012-09-21 01:53:43 +0200
committerAntony Lesuisse <al@openerp.com>2012-09-21 01:53:43 +0200
commit283131289d8cccd1f05acb262dfc19cf27a2b539 (patch)
tree4538feca71972ef9cbdd53083cdaca5f418ec59b
parenteafe3416291a08d114d75d2e8259590070889eac (diff)
parentf154707dcb6bcecfb978a37104a3fdeb2a71194d (diff)
[MERGE] note: remove optionals tags, pad: fix lazy pad creation
bzr revid: al@openerp.com-20120920235343-tveo33j410atkt2y
-rw-r--r--addons/note/note.py1
-rw-r--r--addons/note/note_demo.xml50
-rw-r--r--addons/note/note_view.xml8
-rw-r--r--addons/note/security/res.groups.csv1
-rw-r--r--addons/pad/pad.py49
-rw-r--r--addons/pad/py_etherpad/__init__.py253
-rw-r--r--addons/pad/static/src/js/pad.js14
7 files changed, 320 insertions, 56 deletions
diff --git a/addons/note/note.py b/addons/note/note.py
index fb3f0cee853..9d62f7a2cb7 100644
--- a/addons/note/note.py
+++ b/addons/note/note.py
@@ -185,5 +185,4 @@ class note_base_config_settings(osv.osv_memory):
_columns = {
'module_note_pad': fields.boolean('Use collaborative pads (etherpad)'),
'group_note_fancy': fields.boolean('Use fancy layouts for notes', implied_group='note.group_note_fancy'),
- 'group_note_tags': fields.boolean('Allow setting tags on notes', implied_group='note.group_note_tags'),
}
diff --git a/addons/note/note_demo.xml b/addons/note/note_demo.xml
index 16fa5a3f66b..7769e3ee303 100644
--- a/addons/note/note_demo.xml
+++ b/addons/note/note_demo.xml
@@ -4,28 +4,27 @@
<record model="note.stage" id="demo_note_stage_01">
<field name="name">Today</field>
<field name="sequence">1</field>
- <field name="user_id" eval="ref('base.user_demo')"/>
+ <field name="user_id" ref="base.user_demo"/>
</record>
<record model="note.stage" id="demo_note_stage_02">
<field name="name">Tomorrow</field>
<field name="sequence">2</field>
- <field name="user_id" eval="ref('base.user_demo')"/>
+ <field name="user_id" ref="base.user_demo"/>
</record>
<record model="note.stage" id="demo_note_stage_03">
<field name="name">Later</field>
<field name="sequence">3</field>
- <field name="user_id" eval="ref('base.user_demo')"/>
+ <field name="user_id" ref="base.user_demo"/>
</record>
<record model="note.stage" id="demo_note_stage_04">
- <field name="name">Notes</field>
+ <field name="name">Morning</field>
<field name="sequence">4</field>
- <field name="user_id" eval="ref('base.user_demo')"/>
+ <field name="user_id" ref="base.user_root"/>
</record>
-
<record id="note_1" model="note.note">
<field name="name">Customer report #349872</field>
<field name="memo"><![CDATA[<b>Customer report #349872</b>
@@ -35,8 +34,9 @@
<br/>* We should use the term Calendar, not Meeting.
]]>
</field>
- <field name="stage_id" ref="note_stage_01"/>
+ <field name="stage_id" ref="demo_note_stage_01"/>
<field name="color">2</field>
+ <field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="note_2" model="note.note">
@@ -44,14 +44,7 @@
<br/><br/>* Followed by the telephone conversation and mail about D.544.3
]]>
</field>
- <field name="stage_id" ref="note_stage_01"/>
- </record>
-
- <record id="note_3" model="note.note">
- <field name="memo"><![CDATA[<b>Call Marc</b>
- <br/><br/>]]>
- </field>
- <field name="stage_id" ref="note_stage_01"/>
+ <field name="stage_id" ref="demo_note_stage_01"/>
</record>
<record id="note_4" model="note.note">
@@ -67,7 +60,8 @@
<br/>* wine
]]>
</field>
- <field name="stage_id" ref="note_stage_02"/>
+ <field name="stage_id" ref="demo_note_stage_02"/>
+ <field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="note_6" model="note.note">
@@ -79,15 +73,6 @@
<field name="stage_id" ref="note_stage_02"/>
</record>
- <record id="note_7" model="note.note">
- <field name="memo"><![CDATA[<b>Read some documentation about OpenERP before diving into the code</b>
- <br/><br/>* Open ERP: a modern approach to integrated business management
- <br/>* Open ERP for Retail and Industrial Management
- ]]>
- </field>
- <field name="stage_id" ref="note_stage_03"/>
- </record>
-
<record id="note_8" model="note.note">
<field name="memo"><![CDATA[<b>New computer specs</b>
<br/><br/>* Motherboard
@@ -108,6 +93,7 @@
</field>
<field name="stage_id" ref="note_stage_03"/>
<field name="color">3</field>
+ <field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="note_9" model="note.note">
@@ -116,16 +102,7 @@
<br/>* Open ERP for Retail and Industrial Management
]]>
</field>
- <field name="stage_id" ref="note_stage_02"/>
- </record>
-
- <record id="note_10" model="note.note">
- <field name="memo"><![CDATA[<b>Read some documentation about OpenERP before diving into the code</b>
- <br/><br/>* Open ERP: a modern approach to integrated business management
- <br/>* Open ERP for Retail and Industrial Management
- ]]>
- </field>
- <field name="stage_id" ref="note_stage_03"/>
+ <field name="stage_id" ref="demo_note_stage_02"/>
</record>
<record id="note_12" model="note.note">
@@ -134,8 +111,9 @@
<br/>* Open ERP for Retail and Industrial Management
]]>
</field>
- <field name="stage_id" ref="note_stage_03"/>
+ <field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
<field name="color">7</field>
+ <field name="stage_ids" eval="['note_stage_03','demo_note_stage_04']"/>
</record>
</data>
diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml
index a92c6abe30a..62b007aab6e 100644
--- a/addons/note/note_view.xml
+++ b/addons/note/note_view.xml
@@ -101,7 +101,7 @@
<field name="name"/>
<field name="open"/>
<field name="stage_id"/>
- <field name="tag_ids" widget="many2many_tags" groups="note.group_note_tags"/>
+ <field name="tag_ids" widget="many2many_tags"/>
</tree>
</field>
</record>
@@ -130,7 +130,7 @@
<field name="arch" type="xml">
<search string="Notes">
<field name="memo" string="Note"/>
- <field name="tag_ids" groups="note.group_note_tags"/>
+ <field name="tag_ids"/>
<filter name="open_true" string="Active" domain="['|',('open', '=', True),('date_done','=',time.strftime('%%Y-%%m-%%d'))]"/>
<filter name="open_false" string="Archive" domain="[('open', '=', False)]"/>
<group expand="0" string="Group By...">
@@ -159,10 +159,6 @@
<field name="group_note_fancy" class="oe_inline"/>
<label for="group_note_fancy"/>
</div>
- <div>
- <field name="group_note_tags" class="oe_inline"/>
- <label for="group_note_tags"/>
- </div>
</div>
</group>
</xpath>
diff --git a/addons/note/security/res.groups.csv b/addons/note/security/res.groups.csv
index 61c54c964ff..88d7b2cd667 100644
--- a/addons/note/security/res.groups.csv
+++ b/addons/note/security/res.groups.csv
@@ -1,3 +1,2 @@
id,name,implied_ids/id
-group_note_tags,Memo / Display tags,
group_note_fancy,Memo / Fancy mode,
diff --git a/addons/pad/pad.py b/addons/pad/pad.py
index 48ac940ccfa..0cbb6107979 100644
--- a/addons/pad/pad.py
+++ b/addons/pad/pad.py
@@ -5,24 +5,56 @@ import re
import string
import urllib2
from tools.translate import _
+from openerp.tools.misc import html2plaintext
+from py_etherpad import EtherpadLiteClient
class pad_common(osv.osv_memory):
_name = 'pad.common'
def pad_generate_url(self, cr, uid, context=None):
- pad_server = self.pool.get('res.users').browse(cr, uid, uid, context).company_id.pad_server
+ company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id;
+
+ pad = {
+ "server" : company.pad_server,
+ "key" : company.pad_key or "4DxmsNIbnQUVQMW9S9tx2oLOSjFdrx1l",
+ }
+
# make sure pad server in the form of http://hostname
- if not pad_server:
+ if not pad["server"]:
return ''
- if not pad_server.startswith('http'):
- pad_server = 'http://' + pad_server
- pad_server = pad_server.rstrip('/')
+ if not pad["server"].startswith('http'):
+ pad["server"] = 'http://' + pad["server"]
+ pad["server"] = pad["server"].rstrip('/')
# generate a salt
s = string.ascii_uppercase + string.digits
salt = ''.join([s[random.randint(0, len(s) - 1)] for i in range(10)])
+ #path
+ path = '%s-%s-%s' % (cr.dbname.replace('_','-'), self._name, salt)
# contruct the url
- url = '%s/p/%s-%s-%s' % (pad_server, cr.dbname.replace('_','-'), self._name, salt)
- return url
+ url = '%s/p/%s' % (pad["server"], path)
+
+ #if create with content
+ if "field_name" in context and "model" in context and "object_id" in context:
+ myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api')
+ myPad.createPad(path)
+
+ #get attr on the field model
+ model = self.pool.get(context["model"])
+ field = model._all_columns[context['field_name']]
+ real_field = field.column.pad_content_field
+
+ #get content of the real field
+ for record in model.browse(cr, uid, [context["object_id"]]):
+ if record[real_field]:
+ myPad.setText(path, html2plaintext(record[real_field]))
+ #Etherpad for html not functional
+ #myPad.setHTML(path, record[real_field])
+
+ return {
+ "server": pad["server"],
+ "path": path,
+ "url": url,
+ }
def pad_get_content(self, cr, uid, url, context=None):
content = ''
@@ -57,7 +89,8 @@ class pad_common(osv.osv_memory):
for k,v in self._all_columns:
field = v.column
if hasattr(field,'pad_content_field'):
- default[k] = self.pad_generate_url(cr, uid, context)
+ pad = self.pad_generate_url(cr, uid, context)
+ default[k] = pad['url']
return super(pad_common, self).copy(cr, uid, id, default, context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/pad/py_etherpad/__init__.py b/addons/pad/py_etherpad/__init__.py
new file mode 100644
index 00000000000..6af310b48aa
--- /dev/null
+++ b/addons/pad/py_etherpad/__init__.py
@@ -0,0 +1,253 @@
+#!/usr/bin/env python
+"""Module to talk to EtherpadLite API."""
+
+import json
+import urllib
+import urllib2
+
+
+class EtherpadLiteClient:
+ """Client to talk to EtherpadLite API."""
+ API_VERSION = 1 # TODO probably 1.1 sometime soon
+
+ CODE_OK = 0
+ CODE_INVALID_PARAMETERS = 1
+ CODE_INTERNAL_ERROR = 2
+ CODE_INVALID_FUNCTION = 3
+ CODE_INVALID_API_KEY = 4
+ TIMEOUT = 20
+
+ apiKey = ""
+ baseUrl = "http://localhost:9001/api"
+
+ def __init__(self, apiKey=None, baseUrl=None):
+ if apiKey:
+ self.apiKey = apiKey
+
+ if baseUrl:
+ self.baseUrl = baseUrl
+
+ def call(self, function, arguments=None):
+ """Create a dictionary of all parameters"""
+ url = '%s/%d/%s' % (self.baseUrl, self.API_VERSION, function)
+
+ params = arguments or {}
+ params.update({'apikey': self.apiKey})
+ data = urllib.urlencode(params, True)
+
+ try:
+ opener = urllib2.build_opener()
+ request = urllib2.Request(url=url, data=data)
+ response = opener.open(request, timeout=self.TIMEOUT)
+ result = response.read()
+ response.close()
+ except urllib2.HTTPError:
+ raise
+
+ result = json.loads(result)
+ if result is None:
+ raise ValueError("JSON response could not be decoded")
+
+ return self.handleResult(result)
+
+ def handleResult(self, result):
+ """Handle API call result"""
+ if 'code' not in result:
+ raise Exception("API response has no code")
+ if 'message' not in result:
+ raise Exception("API response has no message")
+
+ if 'data' not in result:
+ result['data'] = None
+
+ if result['code'] == self.CODE_OK:
+ return result['data']
+ elif result['code'] == self.CODE_INVALID_PARAMETERS or result['code'] == self.CODE_INVALID_API_KEY:
+ raise ValueError(result['message'])
+ elif result['code'] == self.CODE_INTERNAL_ERROR:
+ raise Exception(result['message'])
+ elif result['code'] == self.CODE_INVALID_FUNCTION:
+ raise Exception(result['message'])
+ else:
+ raise Exception("An unexpected error occurred whilst handling the response")
+
+ # GROUPS
+ # Pads can belong to a group. There will always be public pads that do not belong to a group (or we give this group the id 0)
+
+ def createGroup(self):
+ """creates a new group"""
+ return self.call("createGroup")
+
+ def createGroupIfNotExistsFor(self, groupMapper):
+ """this functions helps you to map your application group ids to etherpad lite group ids"""
+ return self.call("createGroupIfNotExistsFor", {
+ "groupMapper": groupMapper
+ })
+
+ def deleteGroup(self, groupID):
+ """deletes a group"""
+ return self.call("deleteGroup", {
+ "groupID": groupID
+ })
+
+ def listPads(self, groupID):
+ """returns all pads of this group"""
+ return self.call("listPads", {
+ "groupID": groupID
+ })
+
+ def createGroupPad(self, groupID, padName, text=''):
+ """creates a new pad in this group"""
+ params = {
+ "groupID": groupID,
+ "padName": padName,
+ }
+ if text:
+ params['text'] = text
+ return self.call("createGroupPad", params)
+
+ # AUTHORS
+ # Theses authors are bind to the attributes the users choose (color and name).
+
+ def createAuthor(self, name=''):
+ """creates a new author"""
+ params = {}
+ if name:
+ params['name'] = name
+ return self.call("createAuthor", params)
+
+ def createAuthorIfNotExistsFor(self, authorMapper, name=''):
+ """this functions helps you to map your application author ids to etherpad lite author ids"""
+ params = {
+ 'authorMapper': authorMapper
+ }
+ if name:
+ params['name'] = name
+ return self.call("createAuthorIfNotExistsFor", params)
+
+ # SESSIONS
+ # Sessions can be created between a group and a author. This allows
+ # an author to access more than one group. The sessionID will be set as
+ # a cookie to the client and is valid until a certain date.
+
+ def createSession(self, groupID, authorID, validUntil):
+ """creates a new session"""
+ return self.call("createSession", {
+ "groupID": groupID,
+ "authorID": authorID,
+ "validUntil": validUntil
+ })
+
+ def deleteSession(self, sessionID):
+ """deletes a session"""
+ return self.call("deleteSession", {
+ "sessionID": sessionID
+ })
+
+ def getSessionInfo(self, sessionID):
+ """returns informations about a session"""
+ return self.call("getSessionInfo", {
+ "sessionID": sessionID
+ })
+
+ def listSessionsOfGroup(self, groupID):
+ """returns all sessions of a group"""
+ return self.call("listSessionsOfGroup", {
+ "groupID": groupID
+ })
+
+ def listSessionsOfAuthor(self, authorID):
+ """returns all sessions of an author"""
+ return self.call("listSessionsOfAuthor", {
+ "authorID": authorID
+ })
+
+ # PAD CONTENT
+ # Pad content can be updated and retrieved through the API
+
+ def getText(self, padID, rev=None):
+ """returns the text of a pad"""
+ params = {"padID": padID}
+ if rev is not None:
+ params['rev'] = rev
+ return self.call("getText", params)
+
+ # introduced with pull request merge
+ def getHtml(self, padID, rev=None):
+ """returns the html of a pad"""
+ params = {"padID": padID}
+ if rev is not None:
+ params['rev'] = rev
+ return self.call("getHTML", params)
+
+ def setText(self, padID, text):
+ """sets the text of a pad"""
+ return self.call("setText", {
+ "padID": padID,
+ "text": text
+ })
+
+ def setHtml(self, padID, html):
+ """sets the text of a pad from html"""
+ return self.call("setHTML", {
+ "padID": padID,
+ "html": html
+ })
+
+ # PAD
+ # Group pads are normal pads, but with the name schema
+ # GROUPID$PADNAME. A security manager controls access of them and its
+ # forbidden for normal pads to include a in the name.
+
+ def createPad(self, padID, text=''):
+ """creates a new pad"""
+ params = {
+ "padID": padID,
+ }
+ if text:
+ params['text'] = text
+ return self.call("createPad", params)
+
+ def getRevisionsCount(self, padID):
+ """returns the number of revisions of this pad"""
+ return self.call("getRevisionsCount", {
+ "padID": padID
+ })
+
+ def deletePad(self, padID):
+ """deletes a pad"""
+ return self.call("deletePad", {
+ "padID": padID
+ })
+
+ def getReadOnlyID(self, padID):
+ """returns the read only link of a pad"""
+ return self.call("getReadOnlyID", {
+ "padID": padID
+ })
+
+ def setPublicStatus(self, padID, publicStatus):
+ """sets a boolean for the public status of a pad"""
+ return self.call("setPublicStatus", {
+ "padID": padID,
+ "publicStatus": publicStatus
+ })
+
+ def getPublicStatus(self, padID):
+ """return true of false"""
+ return self.call("getPublicStatus", {
+ "padID": padID
+ })
+
+ def setPassword(self, padID, password):
+ """returns ok or a error message"""
+ return self.call("setPassword", {
+ "padID": padID,
+ "password": password
+ })
+
+ def isPasswordProtected(self, padID):
+ """returns true or false"""
+ return self.call("isPasswordProtected", {
+ "padID": padID
+ })
diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js
index b7c13ba1b89..e598ecca4f5 100644
--- a/addons/pad/static/src/js/pad.js
+++ b/addons/pad/static/src/js/pad.js
@@ -16,10 +16,17 @@ instance.web.form.FieldPad = instance.web.form.AbstractField.extend({
var self = this;
var _super = self._super;
_super.apply(self,[val]);
+
if (val === false || val === "") {
- self.field_manager.dataset.call('pad_generate_url').then(function(r) {
- _super.apply(self,[r]);
- self.render_value();
+ self.field_manager.dataset.call('pad_generate_url',{context:{
+ model: self.field_manager.model,
+ field_name: self.name,
+ object_id: self.field_manager.datarecord.id
+ }}).then(function(data) {
+ if(data&&data.url){
+ _super.apply(self,[data.url]);
+ self.render_value();
+ }
});
} else {
self.render_value();
@@ -27,7 +34,6 @@ instance.web.form.FieldPad = instance.web.form.AbstractField.extend({
this._dirty_flag = true;
},
render_value: function() {
- console.log("display");
var self = this;
var value = this.get('value');