--- a/utils.py Wed Jul 08 16:21:31 2009 +0200
+++ b/utils.py Thu Jul 09 09:42:44 2009 +0200
@@ -326,4 +326,11 @@
"""
# XXX deprecated, no more necessary
+def compute_cardinality(eschema, rschema, role):
+ if role == 'subject':
+ targetschema = rschema.objects(eschema)[0]
+ return rschema.rproperty(eschema, targetschema, 'cardinality')[0]
+ targetschema = rschema.subjects(eschema)[0]
+ return rschema.rproperty(targetschema, eschema, 'cardinality')[1]
+
--- a/web/data/cubicweb.edition.js Wed Jul 08 16:21:31 2009 +0200
+++ b/web/data/cubicweb.edition.js Thu Jul 09 09:42:44 2009 +0200
@@ -454,7 +454,8 @@
* @param eid : the eid of the entity being edited
* @param reload: boolean to reload page if true (when changing URL dependant data)
*/
-function inlineValidateAttributeForm(formid, rtype, eid, divid, reload, default_value) {
+function inlineValidateAttributeForm(formid, rtype, eid, divid, reload,
+ default_value, lzone) {
try {
var form = getNode(formid);
if (typeof FCKeditorAPI != "undefined") {
@@ -467,7 +468,7 @@
}
var zipped = formContents(form);
var d = asyncRemoteExec('edit_field', 'apply', zipped[0], zipped[1],
- rtype, eid, default_value);
+ rtype, eid, default_value, lzone);
} catch (ex) {
log('got exception', ex);
return false;
@@ -494,30 +495,35 @@
return false;
}
-function inlineValidateRelationForm(formid, rtype, role, eid, divid, vid, default_value) {
+function inlineValidateRelationForm(formid, rtype, role, eid, divid, reload, vid,
+ default_value, escape, lzone) {
try {
var form = getNode(formid);
var relname = rtype + ':' + eid;
var newtarget = jQuery('[name=' + relname + ']').val();
var zipped = formContents(form);
var d = asyncRemoteExec('edit_relation', 'apply', zipped[0], zipped[1], rtype, role,
- eid, vid, default_value);
+ eid, vid, default_value, escape, lzone);
} catch (ex) {
log('got exception', ex);
return false;
}
d.addCallback(function (result, req) {
- handleFormValidationResponse(formid, noop, noop, result);
- var fieldview = getNode(divid);
- fieldview.innerHTML = result[2];
- // switch inline form off only if no error
- if (result[0]) {
- // hide global error messages
- jQuery('div.errorMessage').remove();
- jQuery('#appMsg').hide();
- var inputname = 'edit' + role[0] + '-' + relname;
- jQuery('input[name=' + inputname + ']').val(newtarget);
- cancelInlineEdit(eid, rtype, divid);
+ if (reload) {
+ document.location.href = result[1];
+ } else {
+ handleFormValidationResponse(formid, noop, noop, result);
+ var fieldview = getNode(divid);
+ fieldview.innerHTML = result[2];
+ // switch inline form off only if no error
+ if (result[0]) {
+ // hide global error messages
+ jQuery('div.errorMessage').remove();
+ jQuery('#appMsg').hide();
+ var inputname = 'edit' + role[0] + '-' + relname;
+ jQuery('input[name=' + inputname + ']').val(newtarget);
+ cancelInlineEdit(eid, rtype, divid);
+ }
}
return false;
});
--- a/web/formfields.py Wed Jul 08 16:21:31 2009 +0200
+++ b/web/formfields.py Thu Jul 09 09:42:44 2009 +0200
@@ -14,7 +14,7 @@
from yams.constraints import SizeConstraint, StaticVocabularyConstraint
from cubicweb.schema import FormatConstraint
-from cubicweb.utils import ustrftime
+from cubicweb.utils import ustrftime, compute_cardinality
from cubicweb.common import tags, uilib
from cubicweb.web import INTERNAL_FIELD_VALUE
from cubicweb.web.formwidgets import (
@@ -460,7 +460,7 @@
fieldclass = None
if role == 'subject':
targetschema = rschema.objects(eschema)[0]
- card = rschema.rproperty(eschema, targetschema, 'cardinality')[0]
+ card = compute_cardinality(eschema, rschema, role)
help = rschema.rproperty(eschema, targetschema, 'description')
if rschema.is_final():
if rschema.rproperty(eschema, targetschema, 'internationalizable'):
@@ -470,7 +470,7 @@
kwargs.setdefault('initial', get_default)
else:
targetschema = rschema.subjects(eschema)[0]
- card = rschema.rproperty(targetschema, eschema, 'cardinality')[1]
+ card = compute_cardinality(eschema, rschema, role)
help = rschema.rproperty(targetschema, eschema, 'description')
kwargs['required'] = card in '1+'
kwargs['name'] = rschema.type
--- a/web/views/basecontrollers.py Wed Jul 08 16:21:31 2009 +0200
+++ b/web/views/basecontrollers.py Thu Jul 09 09:42:44 2009 +0200
@@ -388,7 +388,7 @@
return _validate_form(self.req, self.vreg)
@jsonize
- def js_edit_field(self, action, names, values, rtype, eid, default):
+ def js_edit_field(self, action, names, values, rtype, eid, default, lzone):
success, args = self.validate_form(action, names, values)
if success:
# Any X,N where we don't seem to use N is an optimisation
@@ -396,25 +396,25 @@
rset = self.req.execute('Any X,N WHERE X eid %%(x)s, X %s N' % rtype,
{'x': eid}, 'x')
entity = rset.get_entity(0, 0)
- value = entity.printable_value(rtype)
- return (success, args, value or default)
+ value = entity.printable_value(rtype) or default
+ return (success, args, lzone + value)
else:
return (success, args, None)
@jsonize
- def js_edit_relation(self, action, names, values,
- rtype, role, eid, vid, default):
+ def js_edit_relation(self, action, names, values, rtype,
+ role, eid, vid, default, escape, lzone):
success, args = self.validate_form(action, names, values)
if success:
entity = self.req.eid_rset(eid).get_entity(0, 0)
rset = entity.related(rtype, role)
if rset:
output = self.view(vid, rset)
- if vid == 'textoutofcontext':
+ if escape == 'True':
output = xml_escape(output)
else:
output = default
- return (success, args, output)
+ return (success, args, lzone + output)
else:
return (success, args, None)
--- a/web/views/editforms.py Wed Jul 08 16:21:31 2009 +0200
+++ b/web/views/editforms.py Thu Jul 09 09:42:44 2009 +0200
@@ -17,13 +17,13 @@
from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
specified_etype_implements, yes)
-from cubicweb.utils import make_uid
+from cubicweb.utils import make_uid, compute_cardinality
from cubicweb.view import EntityView
from cubicweb.common import tags
from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, eid_param
from cubicweb.web.form import FormViewMixIn
-from cubicweb.web.formfields import RelationField
-from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton, Select
+from cubicweb.web.formfields import guess_field
+from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
from cubicweb.web.views import forms
@@ -90,43 +90,58 @@
# FIXME editableField class could be toggleable from userprefs
- onsubmit = ("return inlineValidateAttributeForm('%(divid)s-form', '%(rtype)s', "
- "'%(eid)s', '%(divid)s', %(reload)s, '%(default)s');")
- ondblclick = "showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')"
+ _onclick = "showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')"
+ _defaultlandingzone = u'<img title="%s" src="data/file.gif"/>'
+ _landingzonemsg = _('click to edit this field')
+ # default relation vids according to cardinality
+ _one_rvid = 'incontext'
+ _many_rvid = 'csv'
- def cell_call(self, row, col, rtype=None, role='subject', reload=False,
- vid='textoutofcontext', default=None):
+ def _compute_best_vid(self, entity, rtype, role):
+ if compute_cardinality(entity.e_schema,
+ entity.schema.rschema(rtype),
+ role) in '+*':
+ return self._many_rvid
+ return self._one_rvid
+
+ def cell_call(self, row, col, rtype=None, role='subject',
+ reload=False, # controls reloading the whole page after change
+ rvid=None, # vid to be applied to other side of rtype
+ escape=True, # depending on the vid, will xml_escape or not
+ default=None, # default value
+ landing_zone=None # prepend value with a separate html element to click onto
+ # (esp. needed when values are links)
+ ):
"""display field to edit entity's `rtype` relation on double-click"""
- rschema = self.schema.rschema(rtype)
+ assert rtype
entity = self.entity(row, col)
+ rschema = entity.schema.rschema(rtype)
if not default:
- default = self.req._('not specified')
+ default = xml_escape(self.req._('<no value>'))
+ # compute value, checking perms, build form
if rschema.is_final():
- value = entity.printable_value(rtype)
+ value = entity.printable_value(rtype) or default
if not entity.has_perm('update'):
self.w(value)
return
+ form = self._build_attribute_form(entity, value, rtype, role, reload,
+ row, col, default, landing_zone)
else:
+ if rvid is None:
+ rvid = self._compute_best_vid(entity, rtype, role)
rset = entity.related(rtype, role)
- # XXX xml_escape but that depends of the actual vid
- value = xml_escape(self.view(vid, rset, 'null') or default)
- # XXX consider local roles ?
- if role == 'subject'and not rschema.has_perm(self.req, 'add',
- fromeid=entity.eid):
- self.w(value)
- return
- elif role == 'object'and not rschema.has_perm(self.req, 'add',
- toeid=entity.eid):
- self.w(value)
- return
- if not value.strip():
- value = default
- if rschema.is_final():
- form = self._build_attribute_form(entity, value, rtype, role,
- reload, row, col, default)
- else:
- form = self._build_relation_form(entity, value, rtype, role,
- row, col, vid, default)
+ candidate = self.view(rvid, rset, 'null')
+ if candidate and escape:
+ value = xml_escape(candidate)
+ value = candidate or default
+ if role == 'subject'and not rschema.has_perm(self.req, 'add',
+ fromeid=entity.eid):
+ return self.w(value)
+ elif role == 'object' and not rschema.has_perm(self.req, 'add',
+ toeid=entity.eid):
+ return self.w(value)
+ form = self._build_relation_form(entity, value, rtype, role, reload, row, col,
+ rvid, default, escape, landing_zone)
renderer = self.vreg.select_object('formrenderers', 'base', self.req,
entity=entity,
display_label=False, display_help=False,
@@ -135,13 +150,17 @@
display_progress_div=False)
self.w(form.form_render(renderer=renderer))
- def _build_relation_form(self, entity, value, rtype, role, row, col, vid, default):
- entity = self.entity(row, col)
+ def _build_relation_form(self, entity, value, rtype, role, row, col, reload, rvid,
+ default, escape, lzone):
+ lzone = lzone or self._defaultlandingzone % self.req._(self._landingzonemsg)
+ value = lzone + value
divid = 'd%s' % make_uid('%s-%s' % (rtype, entity.eid))
- event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, 'vid' : vid,
- 'default' : default, 'role' : role}
+ event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, 'vid' : rvid,
+ 'reload' : reload, 'default' : default, 'role' : role,
+ 'escape' : escape, 'lzone' : lzone}
onsubmit = ("return inlineValidateRelationForm('%(divid)s-form', '%(rtype)s', "
- "'%(role)s', '%(eid)s', '%(divid)s', '%(vid)s', '%(default)s');"
+ "'%(role)s', '%(eid)s', '%(divid)s', %(reload)s, '%(vid)s', "
+ "'%(default)s', '%(escape)s', '%(lzone)s');"
% event_data)
cancelclick = "cancelInlineEdit(%s,\'%s\',\'%s\')" % (
entity.eid, rtype, divid)
@@ -151,18 +170,19 @@
form_buttons=[SubmitButton(),
Button(stdmsgs.BUTTON_CANCEL,
onclick=cancelclick)])
- form.append_field(RelationField(name=rtype, role=role, sort=True,
- widget=Select(),
- label=u' '))
+ field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role)
+ form.append_field(field)
self.w(tags.div(value, klass='editableField', id=divid,
- ondblclick=self.ondblclick % event_data))
+ onclick=self._onclick % event_data))
return form
- def _build_attribute_form(self, entity, value, rtype, role, reload, row, col, default):
+ def _build_attribute_form(self, entity, value, rtype, role, reload, row, col, default, lzone):
eid = entity.eid
divid = 'd%s' % make_uid('%s-%s' % (rtype, eid))
event_data = {'divid' : divid, 'eid' : eid, 'rtype' : rtype,
- 'reload' : dumps(reload), 'default' : default}
+ 'reload' : dumps(reload), 'default' : default, 'lzone' : lzone}
+ onsubmit = ("return inlineValidateAttributeForm('%(divid)s-form', '%(rtype)s', "
+ "'%(eid)s', '%(divid)s', %(reload)s, '%(default)s', '%(lzone)s');")
buttons = [SubmitButton(stdmsgs.BUTTON_OK),
Button(stdmsgs.BUTTON_CANCEL,
onclick="cancelInlineEdit(%s,\'%s\',\'%s\')" % (
@@ -171,9 +191,9 @@
row=row, col=col, form_buttons=buttons,
domid='%s-form' % divid, action='#',
cssstyle='display: none',
- onsubmit=self.onsubmit % event_data)
+ onsubmit=onsubmit % event_data)
self.w(tags.div(value, klass='editableField', id=divid,
- ondblclick=self.ondblclick % event_data))
+ onclick=self._onclick % event_data))
return form