109 __regid__ = 'doreledit' |
108 __regid__ = 'doreledit' |
110 __select__ = non_final_entity() & match_kwargs('rtype') |
109 __select__ = non_final_entity() & match_kwargs('rtype') |
111 # FIXME editableField class could be toggleable from userprefs |
110 # FIXME editableField class could be toggleable from userprefs |
112 |
111 |
113 _onclick = u"showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')" |
112 _onclick = u"showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')" |
114 _defaultlandingzone = (u'<img title="%(msg)s" ' |
113 _onsubmit = ("return inlineValidateRelationForm('%(rtype)s', '%(role)s', '%(eid)s', " |
115 'src="data/accessories-text-editor.png" ' |
114 "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');") |
|
115 _cancelclick = "hideInlineEdit(%s,\'%s\',\'%s\')" |
|
116 _defaultlandingzone = (u'<img title="%(msg)s" src="data/file.gif" ' |
116 'alt="%(msg)s"/>') |
117 'alt="%(msg)s"/>') |
117 _landingzonemsg = _('click to edit this field') |
118 _landingzonemsg = _('click to edit this field') |
118 # default relation vids according to cardinality |
119 # default relation vids according to cardinality |
119 _one_rvid = 'incontext' |
120 _one_rvid = 'incontext' |
120 _many_rvid = 'csv' |
121 _many_rvid = 'csv' |
121 |
122 |
122 def _compute_best_vid(self, eschema, rschema, role): |
|
123 if eschema.cardinality(rschema, role) in '+*': |
|
124 return self._many_rvid |
|
125 return self._one_rvid |
|
126 |
|
127 def _build_landing_zone(self, lzone): |
|
128 return lzone or self._defaultlandingzone % { |
|
129 'msg': xml_escape(self._cw._(self._landingzonemsg))} |
|
130 |
|
131 def _build_renderer(self, entity, rtype, role): |
|
132 return self._cw.vreg['formrenderers'].select( |
|
133 'base', self._cw, entity=entity, display_label=False, |
|
134 display_help=False, table_class='', |
|
135 button_bar_class='buttonbar', display_progress_div=False) |
|
136 |
|
137 def _build_form(self, entity, rtype, role, default, onsubmit, reload, |
|
138 extradata=None, **formargs): |
|
139 divid = 'd%s' % make_uid('%s-%s' % (rtype, entity.eid)) |
|
140 event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, |
|
141 'reload' : dumps(reload), 'default' : default} |
|
142 if extradata: |
|
143 event_data.update(extradata) |
|
144 onsubmit %= event_data |
|
145 cancelclick = "hideInlineEdit(%s,\'%s\',\'%s\')" % (entity.eid, rtype, |
|
146 divid) |
|
147 form = self._cw.vreg['forms'].select( |
|
148 'edition', self._cw, entity=entity, domid='%s-form' % divid, |
|
149 cssstyle='display: none', onsubmit=onsubmit, action='#', |
|
150 display_fields=[(rtype, role)], |
|
151 form_buttons=[SubmitButton(), Button(stdmsgs.BUTTON_CANCEL, |
|
152 onclick=cancelclick)], |
|
153 **formargs) |
|
154 form.event_data = event_data |
|
155 return form |
|
156 |
123 |
157 def cell_call(self, row, col, rtype=None, role='subject', |
124 def cell_call(self, row, col, rtype=None, role='subject', |
158 reload=False, # controls reloading the whole page after change |
125 reload=False, # controls reloading the whole page after change |
159 rvid=None, # vid to be applied to other side of rtype (non final relations only) |
126 rvid=None, # vid to be applied to other side of rtype (non final relations only) |
160 default=None, # default value |
127 default=None, # default value |
161 landing_zone=None # prepend value with a separate html element to click onto |
128 landing_zone=None # prepend value with a separate html element to click onto |
162 # (esp. needed when values are links) |
129 # (esp. needed when values are links) |
163 ): |
130 ): |
164 """display field to edit entity's `rtype` relation on click""" |
131 """display field to edit entity's `rtype` relation on click""" |
165 assert rtype |
132 assert rtype |
166 assert role in ('subject', 'object') |
133 assert role in ('subject', 'object'), '%s is not an acceptable role value' % role |
|
134 self.req.add_js('cubicweb.edition.js') |
|
135 self.req.add_css('cubicweb.form.css') |
167 if default is None: |
136 if default is None: |
168 default = xml_escape(self._cw._('<no value>')) |
137 default = xml_escape(self._cw._('<no value>')) |
169 schema = self._cw.vreg.schema |
138 schema = self._cw.vreg.schema |
170 entity = self.cw_rset.get_entity(row, col) |
139 entity = self.cw_rset.get_entity(row, col) |
171 rschema = schema.rschema(rtype) |
140 rschema = schema.rschema(rtype) |
172 lzone = self._build_landing_zone(landing_zone) |
141 lzone = self._build_landing_zone(landing_zone) |
173 # compute value, checking perms, build form |
142 # compute value, checking perms, build form |
174 if rschema.final: |
143 if rschema.final: |
175 onsubmit = ("return inlineValidateAttributeForm('%(rtype)s', '%(eid)s', '%(divid)s', " |
144 form = self._build_form(entity, rtype, role, 'edition', default, reload, lzone) |
176 "%(reload)s, '%(default)s');") |
|
177 form = self._build_form( |
|
178 entity, rtype, role, default, onsubmit, reload) |
|
179 if not self.should_edit_attribute(entity, rschema, role, form): |
145 if not self.should_edit_attribute(entity, rschema, role, form): |
180 self.w(entity.printable_value(rtype)) |
146 self.w(entity.printable_value(rtype)) |
181 return |
147 return |
182 value = entity.printable_value(rtype) or default |
148 value = entity.printable_value(rtype) or default |
183 self.attribute_form(lzone, value, form, |
149 self.relation_form(lzone, value, form, |
184 self._build_renderer(entity, rtype, role)) |
150 self._build_renderer(entity, rtype, role)) |
185 else: |
151 else: |
186 if rvid is None: |
152 if rvid is None: |
187 rvid = self._compute_best_vid(entity.e_schema, rschema, role) |
153 rvid = self._compute_best_vid(entity.e_schema, rschema, role) |
188 rset = entity.related(rtype, role) |
154 rset = entity.related(rtype, role) |
189 if rset: |
155 if rset: |
192 value = default |
158 value = default |
193 if not self.should_edit_relation(entity, rschema, role, rvid): |
159 if not self.should_edit_relation(entity, rschema, role, rvid): |
194 if rset: |
160 if rset: |
195 self.w(value) |
161 self.w(value) |
196 return |
162 return |
197 onsubmit = ("return inlineValidateRelationForm('%(rtype)s', '%(role)s', '%(eid)s', " |
163 form = self._build_form(entity, rtype, role, 'base', default, reload, lzone, |
198 "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');") |
164 dict(vid=rvid, lzone=lzone)) |
199 form = self._build_form( |
165 field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role) |
200 entity, rtype, role, default, onsubmit, reload, |
166 form.append_field(field) |
201 dict(vid=rvid, role=role, lzone=lzone)) |
|
202 self.relation_form(lzone, value, form, |
167 self.relation_form(lzone, value, form, |
203 self._build_renderer(entity, rtype, role)) |
168 self._build_renderer(entity, rtype, role)) |
204 |
169 |
205 def should_edit_attribute(self, entity, rschema, role, form): |
170 def should_edit_attribute(self, entity, rschema, role, form): |
206 rtype = str(rschema) |
171 rtype = str(rschema) |
207 ttype = rschema.targets(entity.__regid__, role)[0] |
172 ttype = rschema.targets(entity.id, role)[0] |
208 afs = uicfg.autoform_section.etype_get(entity.__regid__, rtype, role, ttype) |
173 afs = uicfg.autoform_section.etype_get(entity.id, rtype, role, ttype) |
209 if 'main_hidden' in afs or not entity.has_perm('update'): |
174 if 'main_hidden' in afs or not entity.has_perm('update'): |
210 self.w(entity.printable_value(rtype)) |
|
211 return False |
175 return False |
212 try: |
176 try: |
213 field = form.field_by_name(rtype, role) |
177 form.field_by_name(rtype, role) |
214 except FieldNotFound: |
178 except FieldNotFound: |
215 self.w(entity.printable_value(rtype)) |
|
216 return False |
179 return False |
217 return True |
180 return True |
218 |
181 |
219 def should_edit_relation(self, entity, rschema, role, rvid): |
182 def should_edit_relation(self, entity, rschema, role, rvid): |
220 if ((role == 'subject' and not rschema.has_perm(self._cw, 'add', |
183 if ((role == 'subject' and not rschema.has_perm(self._cw, 'add', |
221 fromeid=entity.eid)) |
184 fromeid=entity.eid)) |
222 or |
185 or |
223 (role == 'object' and not rschema.has_perm(self._cw, 'add', |
186 (role == 'object' and not rschema.has_perm(self._cw, 'add', |
224 toeid=entity.eid))): |
187 toeid=entity.eid))): |
225 self.wview(rvid, entity.related(str(rschema), role), 'null') |
|
226 return False |
188 return False |
227 return True |
189 return True |
228 |
|
229 def attribute_form(self, lzone, value, form, renderer): |
|
230 """div (class=field) |
|
231 +-xxx div |
|
232 | +-xxx div (class=editableField) |
|
233 | | +-landing zone |
|
234 | +-value-xxx div |
|
235 | +-value |
|
236 +-form-xxx div |
|
237 """ |
|
238 w = self.w |
|
239 w(u'<div class="field">') |
|
240 w(u'<div id="%s" style="display: inline">' % form.event_data['divid']) |
|
241 w(tags.div(lzone, klass='editableField', |
|
242 onclick=self._onclick % form.event_data)) |
|
243 w(u'<div id="value-%s" style="display: inline">%s</div>' % |
|
244 (form.event_data['divid'], value)) |
|
245 w(u'</div>') |
|
246 w(form.form_render(renderer=renderer)) |
|
247 w(u'</div>') |
|
248 |
190 |
249 def relation_form(self, lzone, value, form, renderer): |
191 def relation_form(self, lzone, value, form, renderer): |
250 """xxx-reledit div (class=field) |
192 """xxx-reledit div (class=field) |
251 +-xxx div (class="editableField") |
193 +-xxx div (class="editableField") |
252 | +-landing zone |
194 | +-landing zone |
253 +-value |
195 +-xxx-value div |
254 +-form-xxx div |
196 +-xxx-form div |
255 """ |
197 """ |
256 w = self.w |
198 w = self.w |
257 w(u'<div id="%s-reledit" class="field">' % form.event_data['divid']) |
199 divid = form.event_args['divid'] |
258 w(tags.div(lzone, klass='editableField', id=form.event_data['divid'], |
200 w(u'<div id="%s-reledit" class="field">' % form.event_args['divid']) |
259 onclick=self._onclick % form.event_data)) |
201 w(u'<div id="%s" class="editableField" onclick="%s" title="%s">' % ( |
260 w(value) |
202 divid, xml_escape(self._onclick % form.event_args), |
|
203 self.req._(self._landingzonemsg))) |
|
204 w(lzone) |
|
205 w(u'</div>') |
|
206 w(u'<div id="%s-value" class="editableFieldValue">%s</div>' % (divid, value)) |
261 w(form.form_render(renderer=renderer)) |
207 w(form.form_render(renderer=renderer)) |
262 w(u'</div>') |
208 w(u'</div>') |
263 |
209 |
|
210 def _compute_best_vid(self, eschema, rschema, role): |
|
211 if eschema.cardinality(rschema, role) in '+*': |
|
212 return self._many_rvid |
|
213 return self._one_rvid |
|
214 |
|
215 def _build_landing_zone(self, lzone): |
|
216 return lzone or self._defaultlandingzone % { |
|
217 'msg': xml_escape(self._cw._(self._landingzonemsg))} |
|
218 |
|
219 def _build_renderer(self, entity, rtype, role): |
|
220 return self._cw.vreg['formrenderers'].select( |
|
221 'base', self._cw, entity=entity, display_label=False, |
|
222 display_help=False, table_class='', |
|
223 button_bar_class='buttonbar', display_progress_div=False) |
|
224 |
|
225 def _build_args(self, entity, rtype, role, formid, default, reload, lzone, |
|
226 extradata=None): |
|
227 divid = '%s-%s-%s' % (rtype, role, entity.eid) |
|
228 event_args = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, |
|
229 'reload' : dumps(reload), 'default' : default, 'role' : role, 'vid' : u'', |
|
230 'lzone' : lzone} |
|
231 if extradata: |
|
232 event_args.update(extradata) |
|
233 return divid, event_args |
|
234 |
|
235 def _build_form(self, entity, rtype, role, formid, default, reload, lzone, |
|
236 extradata=None, **formargs): |
|
237 divid, event_args = self._build_args(entity, rtype, role, formid, default, |
|
238 reload, lzone, extradata) |
|
239 onsubmit = self._onsubmit % event_args |
|
240 cancelclick = self._cancelclick % (entity.eid, rtype, divid) |
|
241 form = self._cw.vreg['forms'].select( |
|
242 formid, self._cw, entity=entity, domid='%s-form' % divid, |
|
243 cssstyle='display: none', onsubmit=onsubmit, action='#', |
|
244 form_buttons=[SubmitButton(), Button(stdmsgs.BUTTON_CANCEL, |
|
245 onclick=cancelclick)], |
|
246 **formargs) |
|
247 form.event_args = event_args |
|
248 return form |
|
249 |
|
250 class DummyForm(object): |
|
251 __slots__ = ('event_args',) |
|
252 def form_render(self, **_args): |
|
253 return u'' |
|
254 def append_field(self, *args): |
|
255 pass |
264 |
256 |
265 class AutoClickAndEditFormView(ClickAndEditFormView): |
257 class AutoClickAndEditFormView(ClickAndEditFormView): |
266 """same as ClickAndEditFormView but checking if the view *should* be applied |
258 """same as ClickAndEditFormView but checking if the view *should* be applied |
267 by checking uicfg configuration and composite relation property. |
259 by checking uicfg configuration and composite relation property. |
268 """ |
260 """ |
269 __regid__ = 'reledit' |
261 __regid__ = 'reledit' |
|
262 _onclick = (u"loadInlineEditionForm(%(eid)s, '%(rtype)s', '%(role)s', " |
|
263 "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');") |
270 |
264 |
271 def should_edit_relation(self, entity, rschema, role, rvid): |
265 def should_edit_relation(self, entity, rschema, role, rvid): |
272 eschema = entity.e_schema |
266 eschema = entity.e_schema |
273 rtype = str(rschema) |
267 rtype = str(rschema) |
274 # XXX check autoform_section. what if 'generic'? |
268 # XXX check autoform_section. what if 'generic'? |