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 _pvs = uicfg.primaryview_section |
|
28 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden') |
|
29 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden') |
|
30 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden') |
|
31 |
|
32 _abaa = uicfg.actionbox_appearsin_addmenu |
|
33 _abaa.tag_subject_of(('BaseTransition', 'condition', 'RQLExpression'), False) |
|
34 _abaa.tag_subject_of(('State', 'allowed_transition', 'BaseTransition'), False) |
|
35 _abaa.tag_object_of(('SubWorkflowExitPoint', 'destination_state', 'State'), |
|
36 False) |
|
37 _abaa.tag_object_of(('State', 'state_of', 'Workflow'), True) |
|
38 _abaa.tag_object_of(('Transition', 'transition_of', 'Workflow'), True) |
|
39 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True) |
|
40 |
|
41 _afs = uicfg.autoform_section |
|
42 _afs.tag_subject_of(('TrInfo', 'to_state', '*'), 'generated') |
|
43 _afs.tag_subject_of(('TrInfo', 'from_state', '*'), 'generated') |
|
44 _afs.tag_object_of(('State', 'allowed_transition', '*'), 'primary') |
|
45 |
27 |
46 |
28 |
47 # IWorkflowable views ######################################################### |
29 # IWorkflowable views ######################################################### |
48 |
30 |
49 class ChangeStateForm(forms.CompositeEntityForm): |
31 class ChangeStateForm(forms.CompositeEntityForm): |
168 yield self.build_action(self.req._('view history'), wfurl) |
150 yield self.build_action(self.req._('view history'), wfurl) |
169 |
151 |
170 |
152 |
171 # workflow entity types views ################################################## |
153 # workflow entity types views ################################################## |
172 |
154 |
173 class CellView(view.EntityView): |
155 _pvs = uicfg.primaryview_section |
174 id = 'cell' |
156 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden') |
175 __select__ = implements('TrInfo') |
157 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden') |
176 |
158 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden') |
177 def cell_call(self, row, col, cellvid=None): |
159 |
178 self.w(self.rset.get_entity(row, col).view('reledit', rtype='comment')) |
160 _abaa = uicfg.actionbox_appearsin_addmenu |
179 |
161 _abaa.tag_subject_of(('BaseTransition', 'condition', 'RQLExpression'), False) |
180 |
162 _abaa.tag_subject_of(('State', 'allowed_transition', 'BaseTransition'), False) |
181 class StateInContextView(view.EntityView): |
163 _abaa.tag_object_of(('SubWorkflowExitPoint', 'destination_state', 'State'), |
182 """convenience trick, State's incontext view should not be clickable""" |
164 False) |
183 id = 'incontext' |
165 _abaa.tag_object_of(('State', 'state_of', 'Workflow'), True) |
184 __select__ = implements('State') |
166 _abaa.tag_object_of(('BaseTransition', 'transition_of', 'Workflow'), False) |
185 |
167 _abaa.tag_object_of(('Transition', 'transition_of', 'Workflow'), True) |
186 def cell_call(self, row, col): |
168 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True) |
187 self.w(xml_escape(self.view('textincontext', self.rset, |
|
188 row=row, col=col))) |
|
189 |
|
190 |
169 |
191 class WorkflowPrimaryView(primary.PrimaryView): |
170 class WorkflowPrimaryView(primary.PrimaryView): |
192 __select__ = implements('Workflow') |
171 __select__ = implements('Workflow') |
193 |
172 |
194 def render_entity_attributes(self, entity): |
173 def render_entity_attributes(self, entity): |
195 self.w(entity.view('reledit', rtype='description')) |
174 self.w(entity.view('reledit', rtype='description')) |
196 self.w(u'<img src="%s" alt="%s"/>' % ( |
175 self.w(u'<img src="%s" alt="%s"/>' % ( |
197 xml_escape(entity.absolute_url(vid='wfgraph')), |
176 xml_escape(entity.absolute_url(vid='wfgraph')), |
198 xml_escape(self.req._('graphical workflow for %s') % entity.name))) |
177 xml_escape(self.req._('graphical workflow for %s') % entity.name))) |
|
178 |
|
179 |
|
180 class CellView(view.EntityView): |
|
181 id = 'cell' |
|
182 __select__ = implements('TrInfo') |
|
183 |
|
184 def cell_call(self, row, col, cellvid=None): |
|
185 self.w(self.rset.get_entity(row, col).view('reledit', rtype='comment')) |
|
186 |
|
187 |
|
188 class StateInContextView(view.EntityView): |
|
189 """convenience trick, State's incontext view should not be clickable""" |
|
190 id = 'incontext' |
|
191 __select__ = implements('State') |
|
192 |
|
193 def cell_call(self, row, col): |
|
194 self.w(xml_escape(self.view('textincontext', self.rset, |
|
195 row=row, col=col))) |
|
196 |
|
197 |
|
198 # workflow entity types edition ################################################ |
|
199 |
|
200 _afs = uicfg.autoform_section |
|
201 _afs.tag_subject_of(('TrInfo', 'to_state', '*'), 'generated') |
|
202 _afs.tag_subject_of(('TrInfo', 'from_state', '*'), 'generated') |
|
203 _afs.tag_object_of(('State', 'allowed_transition', '*'), 'primary') |
|
204 _afs.tag_subject_of(('State', 'allowed_transition', '*'), 'primary') |
|
205 |
|
206 def workflow_items_for_relation(req, wfeid, wfrelation, targetrelation): |
|
207 wf = req.entity_from_eid(wfeid) |
|
208 rschema = req.vreg.schema[targetrelation] |
|
209 return sorted((e.view('combobox'), e.eid) |
|
210 for e in getattr(wf, 'reverse_%s' % wfrelation) |
|
211 if rschema.has_perm(req, 'add', toeid=e.eid)) |
|
212 |
|
213 |
|
214 class TransitionEditionForm(autoform.AutomaticEntityForm): |
|
215 __select__ = entity_implements('Transition') |
|
216 |
|
217 def workflow_transition_for_relation(self, targetrelation): |
|
218 eids = self.edited_entity.linked_to('transition_of', 'subject') |
|
219 if eids: |
|
220 return workflow_items_for_relation(self.req, eids[0], 'state_of', |
|
221 targetrelation) |
|
222 return [] |
|
223 |
|
224 def subject_destination_state_vocabulary(self, rtype, limit=None): |
|
225 if not self.edited_entity.has_eid(): |
|
226 return self.workflow_states_for_relation('destination_state') |
|
227 return self.subject_relation_vocabulary(rtype, limit) |
|
228 |
|
229 def object_allowed_transition_vocabulary(self, rtype, limit=None): |
|
230 if not self.edited_entity.has_eid(): |
|
231 return self.workflow_states_for_relation('allowed_transition') |
|
232 return self.subject_relation_vocabulary(rtype, limit) |
|
233 |
|
234 |
|
235 class StateEditionForm(autoform.AutomaticEntityForm): |
|
236 __select__ = entity_implements('State') |
|
237 |
|
238 def subject_allowed_transition_vocabulary(self, rtype, limit=None): |
|
239 if not self.edited_entity.has_eid(): |
|
240 eids = self.edited_entity.linked_to('transition_of', 'subject') |
|
241 if eids: |
|
242 return workflow_items_for_relation(self.req, eids[0], 'transition_of', |
|
243 'allowed_transition') |
|
244 return [] |
199 |
245 |
200 |
246 |
201 # workflow images ############################################################## |
247 # workflow images ############################################################## |
202 |
248 |
203 class WorkflowDotPropsHandler(object): |
249 class WorkflowDotPropsHandler(object): |