--- a/.hgtags Tue Jun 23 13:43:39 2009 +0200
+++ b/.hgtags Tue Jun 23 13:46:18 2009 +0200
@@ -40,3 +40,4 @@
4003d24974f15f17bd03b7efd6a5047cad4e4c41 cubicweb-debian-version-3_2_3-1
2d7d3062ca03d4b4144100013dc4ab7f9d9cb25e cubicweb-version-3_3_0
07214e923e75c8f0490e609e9bee0f4964b87114 cubicweb-debian-version-3_3_0-1
+a356da3e725bfcb59d8b48a89d04be05ea261fd3 3.3.1
--- a/__pkginfo__.py Tue Jun 23 13:43:39 2009 +0200
+++ b/__pkginfo__.py Tue Jun 23 13:46:18 2009 +0200
@@ -7,7 +7,7 @@
distname = "cubicweb"
modname = "cubicweb"
-numversion = (3, 3, 0)
+numversion = (3, 3, 1)
version = '.'.join(str(num) for num in numversion)
license = 'LGPL v2'
--- a/common/migration.py Tue Jun 23 13:43:39 2009 +0200
+++ b/common/migration.py Tue Jun 23 13:46:18 2009 +0200
@@ -17,6 +17,8 @@
from logilab.common.decorators import cached
from logilab.common.configuration import REQUIRED, read_old_config
+from cubicweb import ConfigurationError
+
def migration_files(config, toupgrade):
"""return an orderer list of path of scripts to execute to upgrade
@@ -328,18 +330,18 @@
self.config.add_cubes(newcubes)
return newcubes
- def cmd_remove_cube(self, cube):
+ def cmd_remove_cube(self, cube, removedeps=False):
+ if removedeps:
+ toremove = self.config.expand_cubes([cube])
+ else:
+ toremove = (cube,)
origcubes = self.config._cubes
- basecubes = list(origcubes)
- for pkg in self.config.expand_cubes([cube]):
- try:
- basecubes.remove(pkg)
- except ValueError:
- continue
+ basecubes = [c for c in origcubes if not c in toremove]
self.config._cubes = tuple(self.config.expand_cubes(basecubes))
removed = [p for p in origcubes if not p in self.config._cubes]
- assert cube in removed, \
- "can't remove cube %s, used as a dependancy" % cube
+ if not cube in removed:
+ raise ConfigurationError("can't remove cube %s, "
+ "used as a dependency" % cube)
return removed
def rewrite_configuration(self):
--- a/common/mixins.py Tue Jun 23 13:43:39 2009 +0200
+++ b/common/mixins.py Tue Jun 23 13:46:18 2009 +0200
@@ -191,11 +191,18 @@
return rset.get_entity(0, 0)
return None
- def change_state(self, stateeid, trcomment=None, trcommentformat=None):
+ def change_state(self, state, trcomment=None, trcommentformat=None):
"""change the entity's state according to a state defined in given
parameters
"""
- assert not isinstance(stateeid, basestring), 'change_state wants a state eid'
+ if isinstance(state, basestring):
+ state = self.wf_state(state)
+ assert state is not None, 'not a %s state: %s' % (self.id, state)
+ if hasattr(state, 'eid'):
+ stateeid = state.eid
+ else:
+ stateeid = state
+ stateeid = typed_eid(stateeid)
if trcomment:
self.req.set_shared_data('trcomment', trcomment)
if trcommentformat:
--- a/debian/changelog Tue Jun 23 13:43:39 2009 +0200
+++ b/debian/changelog Tue Jun 23 13:46:18 2009 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.3.1-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Aurélien Campéas <aurelien.campeas@logilab.fr> Mon, 22 Jun 2009 12:00:00 +0200
+
cubicweb (3.3.0-1) unstable; urgency=low
* new upstream release
--- a/devtools/fill.py Tue Jun 23 13:43:39 2009 +0200
+++ b/devtools/fill.py Tue Jun 23 13:46:18 2009 +0200
@@ -10,7 +10,7 @@
from random import randint, choice
from copy import deepcopy
-from datetime import datetime, date, timedelta
+from datetime import datetime, date, time#timedelta
from decimal import Decimal
from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
@@ -163,7 +163,7 @@
def generate_time(self, attrname, index):
"""generates a random time (format is ' HH:MM')"""
- return timedelta(0, 11, index%60) #'11:%02d' % (index % 60)
+ return time(11, index%60) #'11:%02d' % (index % 60)
def generate_datetime(self, attrname, index):
"""generates a random date (format is 'yyyy-mm-dd HH:MM')"""
--- a/entity.py Tue Jun 23 13:43:39 2009 +0200
+++ b/entity.py Tue Jun 23 13:46:18 2009 +0200
@@ -398,7 +398,7 @@
path = etype.lower()
if mainattr != 'eid':
value = getattr(self, mainattr)
- if value is None:
+ if value is None or unicode(value) == u'':
mainattr = 'eid'
path += '/eid'
elif needcheck:
--- a/interfaces.py Tue Jun 23 13:43:39 2009 +0200
+++ b/interfaces.py Tue Jun 23 13:46:18 2009 +0200
@@ -197,6 +197,14 @@
"""interface for items that do have a begin date 'start' and an end date 'stop'
"""
+ @property
+ def start(self):
+ """return start date"""
+
+ @property
+ def stop(self):
+ """return stop state"""
+
class ICalendarViews(Interface):
"""calendar views interface"""
def matching_dates(self, begin, end):
--- a/schema.py Tue Jun 23 13:43:39 2009 +0200
+++ b/schema.py Tue Jun 23 13:46:18 2009 +0200
@@ -6,8 +6,10 @@
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"
+_ = unicode
import re
+from os.path import join
from logging import getLogger
from warnings import warn
@@ -34,7 +36,7 @@
BASEGROUPS = ('managers', 'users', 'guests', 'owners')
-LOGGER = getLogger('cubicweb.schemaloader')
+_LOGGER = getLogger('cubicweb.schemaloader')
# schema entities created from serialized schema have an eid rproperty
ybo.ETYPE_PROPERTIES += ('eid',)
@@ -636,8 +638,8 @@
raise RQLSyntaxError(expression)
for mainvar in mainvars.split(','):
if len(self.rqlst.defined_vars[mainvar].references()) <= 2:
- LOGGER.warn('You did not use the %s variable in your RQL expression %s',
- mainvar, self)
+ _LOGGER.warn('You did not use the %s variable in your RQL '
+ 'expression %s', mainvar, self)
def __str__(self):
return self.full_rql
@@ -904,9 +906,9 @@
def _load_definition_files(self, cubes=None):
# bootstraping, ignore cubes
- for filepath in self.include_schema_files('bootstrap'):
- self.info('loading %s', filepath)
- self.handle_file(filepath)
+ filepath = join(self.lib_directory, 'bootstrap.py')
+ self.info('loading %s', filepath)
+ self.handle_file(filepath)
def unhandled_file(self, filepath):
"""called when a file without handler associated has been found"""
@@ -930,10 +932,10 @@
return super(CubicWebSchemaLoader, self).load(config, path=path, **kwargs)
def _load_definition_files(self, cubes):
- for filepath in (self.include_schema_files('bootstrap')
- + self.include_schema_files('base')
- + self.include_schema_files('workflow')
- + self.include_schema_files('Bookmark')):
+ for filepath in (join(self.lib_directory, 'bootstrap.py'),
+ join(self.lib_directory, 'base.py'),
+ join(self.lib_directory, 'workflow.py'),
+ join(self.lib_directory, 'Bookmark.py')):
self.info('loading %s', filepath)
self.handle_file(filepath)
for cube in cubes:
--- a/server/migractions.py Tue Jun 23 13:43:39 2009 +0200
+++ b/server/migractions.py Tue Jun 23 13:46:18 2009 +0200
@@ -523,8 +523,9 @@
self.exec_event_script('postcreate', self.config.cube_dir(pack))
self.commit()
- def cmd_remove_cube(self, cube):
- removedcubes = super(ServerMigrationHelper, self).cmd_remove_cube(cube)
+ def cmd_remove_cube(self, cube, removedeps=False):
+ removedcubes = super(ServerMigrationHelper, self).cmd_remove_cube(
+ cube, removedeps)
if not removedcubes:
return
fsschema = self.fs_schema
--- a/server/schemaserial.py Tue Jun 23 13:43:39 2009 +0200
+++ b/server/schemaserial.py Tue Jun 23 13:46:18 2009 +0200
@@ -109,7 +109,7 @@
ETYPE_NAME_MAP[etype])
print sql
sqlcu.execute(sql)
- # other table renaming done once schema has been readen
+ # other table renaming done once schema has been read
# print 'reading schema from the database...'
index = {}
permsdict = deserialize_ertype_permissions(session)
--- a/server/test/unittest_migractions.py Tue Jun 23 13:43:39 2009 +0200
+++ b/server/test/unittest_migractions.py Tue Jun 23 13:46:18 2009 +0200
@@ -7,6 +7,7 @@
from logilab.common.testlib import TestCase, unittest_main
from cubicweb.devtools.apptest import RepositoryBasedTC, get_versions
+from cubicweb import ConfigurationError
from cubicweb.schema import CubicWebSchemaLoader
from cubicweb.server.sqlutils import SQL_PREFIX
from cubicweb.server.repository import Repository
@@ -365,7 +366,7 @@
finally:
self.mh.cmd_set_size_constraint('CWEType', 'description', None)
- def test_add_remove_cube(self):
+ def test_add_remove_cube_and_deps(self):
cubes = set(self.config.cubes())
schema = self.repo.schema
self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
@@ -374,11 +375,10 @@
('Note', 'Note'), ('Note', 'Bookmark')]))
try:
try:
- self.mh.cmd_remove_cube('email')
+ self.mh.cmd_remove_cube('email', removedeps=True)
# file was there because it's an email dependancy, should have been removed
- cubes.remove('email')
- cubes.remove('file')
- self.assertEquals(set(self.config.cubes()), cubes)
+ self.failIf('email' in self.config.cubes())
+ self.failIf('file' in self.config.cubes())
for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
'sender', 'in_thread', 'reply_to', 'data_format'):
self.failIf(ertype in schema, ertype)
@@ -392,17 +392,14 @@
self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
- self.failIf('email' in self.config.cubes())
- self.failIf('file' in self.config.cubes())
except :
import traceback
traceback.print_exc()
raise
finally:
self.mh.cmd_add_cube('email')
- cubes.add('email')
- cubes.add('file')
- self.assertEquals(set(self.config.cubes()), cubes)
+ self.failUnless('email' in self.config.cubes())
+ self.failUnless('file' in self.config.cubes())
for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
'sender', 'in_thread', 'reply_to', 'data_format'):
self.failUnless(ertype in schema, ertype)
@@ -420,8 +417,6 @@
email_version)
self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
file_version)
- self.failUnless('email' in self.config.cubes())
- self.failUnless('file' in self.config.cubes())
# trick: overwrite self.maxeid to avoid deletion of just reintroduced
# types (and their associated tables!)
self.maxeid = self.execute('Any MAX(X)')[0][0]
@@ -429,6 +424,38 @@
# next test may fail complaining of missing tables
self.commit()
+
+ def test_add_remove_cube_no_deps(self):
+ cubes = set(self.config.cubes())
+ schema = self.repo.schema
+ try:
+ try:
+ self.mh.cmd_remove_cube('email')
+ cubes.remove('email')
+ self.failIf('email' in self.config.cubes())
+ self.failUnless('file' in self.config.cubes())
+ for ertype in ('Email', 'EmailThread', 'EmailPart',
+ 'sender', 'in_thread', 'reply_to'):
+ self.failIf(ertype in schema, ertype)
+ except :
+ import traceback
+ traceback.print_exc()
+ raise
+ finally:
+ self.mh.cmd_add_cube('email')
+ self.failUnless('email' in self.config.cubes())
+ # trick: overwrite self.maxeid to avoid deletion of just reintroduced
+ # types (and their associated tables!)
+ self.maxeid = self.execute('Any MAX(X)')[0][0]
+ # why this commit is necessary is unclear to me (though without it
+ # next test may fail complaining of missing tables
+ self.commit()
+
+ def test_remove_dep_cube(self):
+ ex = self.assertRaises(ConfigurationError, self.mh.cmd_remove_cube, 'file')
+ self.assertEquals(str(ex), "can't remove cube file, used as a dependency")
+
+
def test_set_state(self):
user = self.session.user
self.mh.set_state(user.eid, 'deactivated')
--- a/test/unittest_entity.py Tue Jun 23 13:43:39 2009 +0200
+++ b/test/unittest_entity.py Tue Jun 23 13:46:18 2009 +0200
@@ -390,6 +390,11 @@
metainf['extid'] = 1234
self.assertEquals(note.absolute_url(), 'http://cubicweb2.com/note/1234')
+ def test_absolute_url_empty_field(self):
+ card = self.add_entity('Card', wikiid=u'', title=u'test')
+ self.assertEquals(card.absolute_url(),
+ 'http://testing.fr/cubicweb/card/eid/%s' % card.eid)
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/web/data/cubicweb.css Tue Jun 23 13:43:39 2009 +0200
+++ b/web/data/cubicweb.css Tue Jun 23 13:46:18 2009 +0200
@@ -1,6 +1,6 @@
/*
* :organization: Logilab
- * :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ * :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
/***************************************/
@@ -12,7 +12,7 @@
padding :0px;
}
-html, body {
+html, body {
background: #e2e2e2;
}
@@ -277,8 +277,8 @@
position: relative;
min-height: 800px;
}
-
-table#mainLayout{
+
+table#mainLayout{
margin:0px 3px;
}
@@ -321,7 +321,7 @@
/* boxes */
div.navboxes {
- margin-top: 8px;
+ margin-top: 8px;
}
div.boxFrame {
@@ -459,9 +459,9 @@
max-width: 50em;
}
-ul.sideBox li{
+ul.sideBox li{
list-style: none;
- background: none;
+ background: none;
padding: 0px 0px 1px 1px;
}
@@ -576,7 +576,7 @@
div.primaryRight{
float:right;
-
+
}
div.metadata {
@@ -603,7 +603,7 @@
padding-bottom:0.4px
}
-div.row span.label{
+div.row span.label{
padding-right:1em
}
@@ -772,20 +772,20 @@
/* addcombobox */
/***************************************/
-input#newopt{
- width:120px ;
+input#newopt{
+ width:120px ;
display:block;
float:left;
}
-div#newvalue{
+div#newvalue{
margin-top:2px;
}
#add_newopt{
background: #fffff8 url("go.png") 50% 50% no-repeat;
width: 20px;
- line-height: 20px;
+ line-height: 20px;
display:block;
float:left;
}
@@ -794,7 +794,7 @@
/* buttons */
/***************************************/
-input.button{
+input.button{
margin: 1em 1em 0px 0px;
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
@@ -838,7 +838,7 @@
font-weight: bold;
}
-input.validateButton {
+input.validateButton {
margin: 1em 1em 0px 0px;
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
--- a/web/data/cubicweb.facets.css Tue Jun 23 13:43:39 2009 +0200
+++ b/web/data/cubicweb.facets.css Tue Jun 23 13:46:18 2009 +0200
@@ -1,7 +1,7 @@
#filterbox fieldset{
margin: 0px;
padding: 0px;
-}
+}
div.facet {
margin-bottom: 8px;
@@ -14,11 +14,11 @@
font-size: 80%;
color: #000;
margin-bottom: 2px;
- cursor: pointer;
+ cursor: pointer;
font: bold 100% Georgia;
}
-div.facetTitle a {
+div.facetTitle a {
padding-left: 10px;
background: transparent url("puce.png") 0% 50% no-repeat;
}
@@ -26,12 +26,12 @@
div.facetBody {
}
-.opened{
- color: #000 !important;
+.opened{
+ color: #000 !important;
}
div.overflowed{
- height: 12em;
+ height: 12em;
overflow-y: auto;
}
@@ -50,12 +50,12 @@
}
div.facetValue img{
- float: left;
+ float: left;
background: #fff;
}
div.facetValue a {
- margin-left: 20px;
+ margin-left: 20px;
display: block;
margin-top: -6px; /* FIXME why do we need this ? */
}
@@ -78,11 +78,11 @@
}
-div.facetCheckBox{
+div.facetCheckBox{
line-height:0.8em;
}
-.facet input{
+.facet input{
margin-top:3px;
border:1px solid #ccc;
font-size:11px;
--- a/web/data/cubicweb.htmlhelpers.js Tue Jun 23 13:43:39 2009 +0200
+++ b/web/data/cubicweb.htmlhelpers.js Tue Jun 23 13:46:18 2009 +0200
@@ -247,6 +247,11 @@
}
}
+function limitTextAreaSize(textarea, size) {
+ var $area = jQuery(textarea);
+ $area.val($area.val().slice(0, size));
+}
+
//============= page loading events ==========================================//
function roundedCornersOnLoad() {
jQuery('div.sideBox').corner('bottom 6px');
--- a/web/data/cubicweb.login.css Tue Jun 23 13:43:39 2009 +0200
+++ b/web/data/cubicweb.login.css Tue Jun 23 13:46:18 2009 +0200
@@ -1,7 +1,7 @@
/* styles for the login popup and login form
*
* :organization: Logilab
- * :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ * :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
@@ -12,7 +12,7 @@
width: 26em;
padding: 0px 1px 1px;
font-weight: bold;
- background: #E4EAD8;
+ background: #E4EAD8;
}
div#popupLoginBox div#loginContent {
@@ -20,7 +20,7 @@
padding: 5px 3px 4px;
}
-div#loginBox {
+div#loginBox {
position : absolute;
top: 15%;
left : 50%;
@@ -32,12 +32,12 @@
text-align: center;
}
-div#loginBox h1 {
+div#loginBox h1 {
color: #FF7700;
font-size: 140%;
}
-div#loginTitle {
+div#loginTitle {
color: #fff;
font-weight: bold;
font-size: 140%;
@@ -46,32 +46,32 @@
background: #ff7700 url("banner.png") left top repeat-x;
}
-div#loginBox div#loginContent form {
+div#loginBox div#loginContent form {
padding-top: 1em;
- width: 90%;
- margin: auto;
+ width: 90%;
+ margin: auto;
}
-#popupLoginBox table td {
- padding: 0px 3px;
+#popupLoginBox table td {
+ padding: 0px 3px;
white-space: nowrap;
}
-#loginContent table {
+#loginContent table {
padding: 0px 0.5em;
margin: auto;
}
-#loginBox table td {
- padding: 0px 3px 0.6em;
+#loginBox table td {
+ padding: 0px 3px 0.6em;
white-space: nowrap;
}
-#loginBox .loginButton {
+#loginBox .loginButton {
margin-top: 0.6em;
}
-#loginContent input.data {
+#loginContent input.data {
width:12em;
}
@@ -79,5 +79,5 @@
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
margin: 2px 0px 0px;
- background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
+ background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
}
--- a/web/data/cubicweb.preferences.js Tue Jun 23 13:43:39 2009 +0200
+++ b/web/data/cubicweb.preferences.js Tue Jun 23 13:46:18 2009 +0200
@@ -4,6 +4,8 @@
* move me in a more appropriate place
*/
+var prefsValues = {};
+
function togglePrefVisibility(elemId) {
clearPreviousMessages();
jQuery('#' + elemId).toggleClass('hidden');
@@ -21,7 +23,6 @@
_toggleFieldset(fieldsetid, 0, linklabel, linkhref);
}
-
function _toggleFieldset(fieldsetid, closeaction, linklabel, linkhref){
jQuery('#'+fieldsetid).find('div.openlink').each(function(){
var link = A({'href' : "javascript:noop();",
@@ -75,7 +76,6 @@
jQuery('#err-value:' + formid).remove();
}
-
function checkValues(form, success){
var unfreezeButtons = false;
jQuery(form).find('select').each(function () {
@@ -100,8 +100,8 @@
}
function _checkValue(input, unfreezeButtons){
- var currentValueInput = jQuery("input[name=current-" + input.attr('name') + "]");
- if (currentValueInput.val() != input.val()){
+ var currentValue = prefsValues[input.attr('name')];
+ if (currentValue != input.val()){
input.addClass('changed');
unfreezeButtons = true;
}else{
@@ -112,27 +112,22 @@
return unfreezeButtons;
}
-
function setCurrentValues(form){
- jQuery(form).find('input[name^=current-value]').each(function () {
- var currentValueInput = jQuery(this);
- var name = currentValueInput.attr('name').split('-')[1];
- jQuery(form).find("[name=" + name + "]").each(function (){
- var input = jQuery(this);
- if(input.attr('type') == 'radio'){
- // NOTE: there seems to be a bug with jQuery(input).attr('checked')
- // in our case, we can't rely on its value, we use
- // the DOM API instead.
- if(input[0].checked){
- currentValueInput.val(input.val());
- }
- }else{
- currentValueInput.val(input.val());
- }
- });
- });
+ jQuery(form).find('input[name^=value]').each(function () {
+ var input = jQuery(this);
+ if(input.attr('type') == 'radio'){
+ // NOTE: there seems to be a bug with jQuery(input).attr('checked')
+ // in our case, we can't rely on its value, we use
+ // the DOM API instead.
+ if(input[0].checked){
+ prefsValues[input.attr('name')] = input.val();
+ }
+ }else{
+ prefsValues[input.attr('name')] = input.val();
+ }
+ });
}
-
+
function initEvents(){
jQuery('form').each(function() {
var form = jQuery(this);
@@ -153,4 +148,3 @@
$(document).ready(function() {
initEvents();
});
-
--- a/web/facet.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/facet.py Tue Jun 23 13:46:18 2009 +0200
@@ -744,7 +744,7 @@
% (cssclass, html_escape(unicode(self.value))))
self.w(u'<div class="facetCheckBoxWidget">')
self.w(u'<img src="%s" alt="%s" cubicweb:unselimg="true" /> ' % (imgsrc, imgalt))
- self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid,title))
+ self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid, title))
self.w(u'</div>\n')
self.w(u'</div>\n')
self.w(u'</div>\n')
--- a/web/formwidgets.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/formwidgets.py Tue Jun 23 13:46:18 2009 +0200
@@ -148,7 +148,7 @@
"""<textarea>"""
def render(self, form, field):
name, values, attrs = self._render_attrs(form, field)
- attrs.setdefault('onkeypress', 'autogrow(this)')
+ attrs.setdefault('onkeyup', 'autogrow(this)')
attrs.setdefault('cols', 80)
attrs.setdefault('rows', 20)
if not values:
--- a/web/test/unittest_form.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/test/unittest_form.py Tue Jun 23 13:46:18 2009 +0200
@@ -147,12 +147,12 @@
<option value="text/html">text/html</option>
<option value="text/plain">text/plain</option>
<option selected="selected" value="text/rest">text/rest</option>
-</select><textarea cols="60" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="5" tabindex="1"/>''')
+</select><textarea cols="60" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="5" tabindex="1"/>''')
def test_richtextfield_2(self):
self.req.use_fckeditor = lambda: True
- self._test_richtextfield('<input name="description_format:%(eid)s" style="display: block" type="hidden" value="text/rest"/><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="0"/>')
+ self._test_richtextfield('<input name="description_format:%(eid)s" style="display: block" type="hidden" value="text/rest"/><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="20" tabindex="0"/>')
def test_filefield(self):
@@ -197,7 +197,7 @@
<input name="data:%(eid)s__detach" type="checkbox"/>
detach attached file
<p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
-<textarea cols="80" name="data:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="3">new widgets system</textarea>''' % {'eid': file.eid})
+<textarea cols="80" name="data:%(eid)s" onkeyup="autogrow(this)" rows="20" tabindex="3">new widgets system</textarea>''' % {'eid': file.eid})
def test_passwordfield(self):
--- a/web/views/actions.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/actions.py Tue Jun 23 13:46:18 2009 +0200
@@ -6,6 +6,7 @@
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from cubicweb.vregistry import objectify_selector
from cubicweb.selectors import (EntitySelector,
@@ -18,8 +19,6 @@
from cubicweb.web.views import linksearch_select_url, vid_from_rset
from cubicweb.web.views.autoform import AutomaticEntityForm
-_ = unicode
-
class has_editable_relation(EntitySelector):
"""accept if some relations for an entity found in the result set is
--- a/web/views/autoform.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/autoform.py Tue Jun 23 13:46:18 2009 +0200
@@ -292,7 +292,7 @@
by default true if there is no related entity and we need at least one
"""
- return not existant and card in '1+'
+ return not existant and card in '1+' or self.req.form.has_key('force_%s_display' % rschema)
def should_display_add_new_relation_link(self, rschema, existant, card):
"""return true if we should add a link to add a new creation form
--- a/web/views/basecomponents.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/basecomponents.py Tue Jun 23 13:46:18 2009 +0200
@@ -29,7 +29,8 @@
"""build the rql input form, usually displayed in the header"""
id = 'rqlinput'
property_defs = VISIBLE_PROP_DEF
-
+ visible = False
+
def call(self, view=None):
if hasattr(view, 'filter_box_context_info'):
rset = view.filter_box_context_info()[0]
@@ -148,8 +149,10 @@
site_wide = True
def call(self):
- self.w(u'<span id="appliName"><a href="%s">%s</a></span>' % (
- self.req.base_url(), self.req.property_value('ui.site-title')))
+ title = self.req.property_value('ui.site-title')
+ if title:
+ self.w(u'<span id="appliName"><a href="%s">%s</a></span>' % (
+ self.req.base_url(), title))
class SeeAlsoVComponent(component.RelatedObjectsVComponent):
--- a/web/views/basetemplates.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/basetemplates.py Tue Jun 23 13:46:18 2009 +0200
@@ -431,7 +431,7 @@
self.w(u'<div id="%s" class="%s">' % (id, klass))
if title:
self.w(u'<div id="loginTitle">%s</div>'
- % self.req.property_value('ui.site-title'))
+ % (self.req.property_value('ui.site-title') or u' '))
self.w(u'<div id="loginContent">\n')
if message:
--- a/web/views/cwproperties.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/cwproperties.py Tue Jun 23 13:46:18 2009 +0200
@@ -139,7 +139,6 @@
w(u'<h2 class="propertiesform">%s</h2>\n' %
(make_togglable_link('fieldset_' + group, label.capitalize())))
w(u'<div id="fieldset_%s" %s>' % (group, status))
-
# create selection
sorted_objects = sorted((self.req.__('%s_%s' % (group, o)), o, f)
for o, f in objects.iteritems())
@@ -217,10 +216,9 @@
eidparam=True))
subform.vreg = self.vreg
subform.form_add_hidden('pkey', key, eidparam=True)
- subform.form_add_hidden("current-value:%s" % entity.eid,)
form.form_add_subform(subform)
return subform
-
+
def is_user_prefs(cls, req, rset, row=None, col=0, **kwargs):
return req.user.eid == rset[row or 0][col]
@@ -303,7 +301,7 @@
choices = entity.vreg.user_property_keys()
return [(u'', u'')] + sorted(zip((_(v) for v in choices), choices))
-
+
class PropertyValueField(StringField):
"""specific field for CWProperty.value which will be different according to
the selected key type and vocabulary information
@@ -355,7 +353,6 @@
self.choices = field.vocabulary(form)
self.widget = wdg
-
uicfg.autoform_field.tag_attribute(('CWProperty', 'pkey'), PropertyKeyField)
uicfg.autoform_field.tag_attribute(('CWProperty', 'value'), PropertyValueField)
--- a/web/views/idownloadable.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/idownloadable.py Tue Jun 23 13:46:18 2009 +0200
@@ -125,7 +125,7 @@
"""the secondary view is a link to download the file"""
entity = self.entity(row, col)
url = html_escape(entity.absolute_url())
- name = html_escape(entity.download_file_name())
+ name = html_escape(title or entity.download_file_name())
durl = html_escape(entity.download_url())
self.w(u'<a href="%s">%s</a> [<a href="%s">%s</a>]' %
(url, name, durl, self.req._('download')))
--- a/web/views/primary.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/views/primary.py Tue Jun 23 13:46:18 2009 +0200
@@ -54,6 +54,7 @@
self.w(u'<table width="100%"><tr><td style="width: 75%">')
self.w(u'<div>')
self.w(u'<div class="mainInfo">')
+ self.content_navigation_components('navcontenttop')
try:
self.render_entity_attributes(entity)
except TypeError: # XXX bw compat
@@ -61,7 +62,6 @@
'deprecated (%s)' % self.__class__)
self.render_entity_attributes(entity, [])
self.w(u'</div>')
- self.content_navigation_components('navcontenttop')
if self.main_related_section:
try:
self.render_entity_relations(entity)
--- a/web/widgets.py Tue Jun 23 13:43:39 2009 +0200
+++ b/web/widgets.py Tue Jun 23 13:46:18 2009 +0200
@@ -418,7 +418,7 @@
hidden = u'<input type="hidden" name="edits-%s" value="%s"/>\n'\
'<input type="hidden" name="%s" value="text/html"/>\n' % (
frname, format, frname)
- return u'%s<textarea cubicweb:type="wysiwyg" onkeypress="autogrow(this)" name="%s" %s>%s</textarea>' % (
+ return u'%s<textarea cubicweb:type="wysiwyg" onkeyup="autogrow(this)" name="%s" %s>%s</textarea>' % (
hidden, self.rname, self.format_attrs(), dvalue)
if with_format and entity.e_schema.has_metadata(self.name, 'format'):
fmtwdg = entity.get_widget(self.name + '_format')
@@ -426,7 +426,7 @@
self.attrs['tabindex'] = entity.req.next_tabindex()
else:
fmtwdgstr = ''
- return u'%s<br/><textarea onkeypress="autogrow(this)" name="%s" %s>%s</textarea>' % (
+ return u'%s<br/><textarea onkeyup="autogrow(this)" name="%s" %s>%s</textarea>' % (
fmtwdgstr, self.rname, self.format_attrs(), dvalue)