14 from logilab.mtconverter import xml_escape |
14 from logilab.mtconverter import xml_escape |
15 from logilab.common.graph import escape, GraphGenerator, DotBackend |
15 from logilab.common.graph import escape, GraphGenerator, DotBackend |
16 |
16 |
17 from cubicweb import Unauthorized, view |
17 from cubicweb import Unauthorized, view |
18 from cubicweb.selectors import (implements, has_related_entities, one_line_rset, |
18 from cubicweb.selectors import (implements, has_related_entities, one_line_rset, |
19 relation_possible, match_form_params) |
19 relation_possible, match_form_params, |
|
20 entity_implements) |
20 from cubicweb.interfaces import IWorkflowable |
21 from cubicweb.interfaces import IWorkflowable |
21 from cubicweb.view import EntityView |
22 from cubicweb.view import EntityView |
22 from cubicweb.schema import display_name |
23 from cubicweb.schema import display_name |
23 from cubicweb.web import uicfg, stdmsgs, action, component, form, action |
24 from cubicweb.web import uicfg, stdmsgs, action, component, form, action |
24 from cubicweb.web import formfields as ff, formwidgets as fwdgs |
25 from cubicweb.web import formfields as ff, formwidgets as fwdgs |
25 from cubicweb.web.views import TmpFileViewMixin, forms, primary |
26 from cubicweb.web.views import TmpFileViewMixin, forms, primary, autoform |
26 |
27 |
27 _pvs = uicfg.primaryview_section |
28 _pvs = uicfg.primaryview_section |
28 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden') |
29 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden') |
29 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden') |
30 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden') |
30 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden') |
31 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden') |
48 |
49 |
49 class ChangeStateForm(forms.CompositeEntityForm): |
50 class ChangeStateForm(forms.CompositeEntityForm): |
50 __regid__ = 'changestate' |
51 __regid__ = 'changestate' |
51 |
52 |
52 form_renderer_id = 'base' # don't want EntityFormRenderer |
53 form_renderer_id = 'base' # don't want EntityFormRenderer |
53 form_buttons = [fwdgs.SubmitButton(stdmsgs.YES), |
54 form_buttons = [fwdgs.SubmitButton(), |
54 fwdgs.Button(stdmsgs.NO, cwaction='cancel')] |
55 fwdgs.Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')] |
55 |
56 |
56 |
57 |
57 class ChangeStateFormView(form.FormViewMixIn, view.EntityView): |
58 class ChangeStateFormView(form.FormViewMixIn, view.EntityView): |
58 __regid__ = 'statuschange' |
59 __regid__ = 'statuschange' |
59 title = _('status change') |
60 title = _('status change') |
167 yield self.build_action(self._cw._('view history'), wfurl) |
168 yield self.build_action(self._cw._('view history'), wfurl) |
168 |
169 |
169 |
170 |
170 # workflow entity types views ################################################## |
171 # workflow entity types views ################################################## |
171 |
172 |
|
173 _pvs = uicfg.primaryview_section |
|
174 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden') |
|
175 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden') |
|
176 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden') |
|
177 |
|
178 _abaa = uicfg.actionbox_appearsin_addmenu |
|
179 _abaa.tag_subject_of(('BaseTransition', 'condition', 'RQLExpression'), False) |
|
180 _abaa.tag_subject_of(('State', 'allowed_transition', 'BaseTransition'), False) |
|
181 _abaa.tag_object_of(('SubWorkflowExitPoint', 'destination_state', 'State'), |
|
182 False) |
|
183 _abaa.tag_object_of(('State', 'state_of', 'Workflow'), True) |
|
184 _abaa.tag_object_of(('BaseTransition', 'transition_of', 'Workflow'), False) |
|
185 _abaa.tag_object_of(('Transition', 'transition_of', 'Workflow'), True) |
|
186 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True) |
|
187 |
|
188 class WorkflowPrimaryView(primary.PrimaryView): |
|
189 __select__ = implements('Workflow') |
|
190 |
|
191 def render_entity_attributes(self, entity): |
|
192 self.w(entity.view('reledit', rtype='description')) |
|
193 self.w(u'<img src="%s" alt="%s"/>' % ( |
|
194 xml_escape(entity.absolute_url(vid='wfgraph')), |
|
195 xml_escape(self.req._('graphical workflow for %s') % entity.name))) |
|
196 |
|
197 |
172 class CellView(view.EntityView): |
198 class CellView(view.EntityView): |
173 __regid__ = 'cell' |
199 __regid__ = 'cell' |
174 __select__ = implements('TrInfo') |
200 __select__ = implements('TrInfo') |
175 |
201 |
176 def cell_call(self, row, col, cellvid=None): |
202 def cell_call(self, row, col, cellvid=None): |
185 def cell_call(self, row, col): |
211 def cell_call(self, row, col): |
186 self.w(xml_escape(self._cw.view('textincontext', self.cw_rset, |
212 self.w(xml_escape(self._cw.view('textincontext', self.cw_rset, |
187 row=row, col=col))) |
213 row=row, col=col))) |
188 |
214 |
189 |
215 |
190 class WorkflowPrimaryView(primary.PrimaryView): |
216 # workflow entity types edition ################################################ |
191 __select__ = implements('Workflow') |
217 |
192 |
218 _afs = uicfg.autoform_section |
193 def render_entity_attributes(self, entity): |
219 _afs.tag_subject_of(('TrInfo', 'to_state', '*'), 'generated') |
194 self.w(entity.view('reledit', rtype='description')) |
220 _afs.tag_subject_of(('TrInfo', 'from_state', '*'), 'generated') |
195 self.w(u'<img src="%s" alt="%s"/>' % ( |
221 _afs.tag_object_of(('State', 'allowed_transition', '*'), 'primary') |
196 xml_escape(entity.absolute_url(vid='wfgraph')), |
222 _afs.tag_subject_of(('State', 'allowed_transition', '*'), 'primary') |
197 xml_escape(self._cw._('graphical workflow for %s') % entity.name))) |
223 |
|
224 def workflow_items_for_relation(req, wfeid, wfrelation, targetrelation): |
|
225 wf = req.entity_from_eid(wfeid) |
|
226 rschema = req.vreg.schema[targetrelation] |
|
227 return sorted((e.view('combobox'), e.eid) |
|
228 for e in getattr(wf, 'reverse_%s' % wfrelation) |
|
229 if rschema.has_perm(req, 'add', toeid=e.eid)) |
|
230 |
|
231 |
|
232 class TransitionEditionForm(autoform.AutomaticEntityForm): |
|
233 __select__ = entity_implements('Transition') |
|
234 |
|
235 def workflow_states_for_relation(self, targetrelation): |
|
236 eids = self.edited_entity.linked_to('transition_of', 'subject') |
|
237 if eids: |
|
238 return workflow_items_for_relation(self.req, eids[0], 'state_of', |
|
239 targetrelation) |
|
240 return [] |
|
241 |
|
242 def subject_destination_state_vocabulary(self, rtype, limit=None): |
|
243 if not self.edited_entity.has_eid(): |
|
244 return self.workflow_states_for_relation('destination_state') |
|
245 return self.subject_relation_vocabulary(rtype, limit) |
|
246 |
|
247 def object_allowed_transition_vocabulary(self, rtype, limit=None): |
|
248 if not self.edited_entity.has_eid(): |
|
249 return self.workflow_states_for_relation('allowed_transition') |
|
250 return self.subject_relation_vocabulary(rtype, limit) |
|
251 |
|
252 |
|
253 class StateEditionForm(autoform.AutomaticEntityForm): |
|
254 __select__ = entity_implements('State') |
|
255 |
|
256 def subject_allowed_transition_vocabulary(self, rtype, limit=None): |
|
257 if not self.edited_entity.has_eid(): |
|
258 eids = self.edited_entity.linked_to('state_of', 'subject') |
|
259 if eids: |
|
260 return workflow_items_for_relation(self.req, eids[0], 'transition_of', |
|
261 'allowed_transition') |
|
262 return [] |
198 |
263 |
199 |
264 |
200 # workflow images ############################################################## |
265 # workflow images ############################################################## |
201 |
266 |
202 class WorkflowDotPropsHandler(object): |
267 class WorkflowDotPropsHandler(object): |