web/views/schema.py
changeset 5239 471554b842d2
parent 5236 13296aa038a9
child 5423 e15abfdcce38
equal deleted inserted replaced
5238:31c12863fd9d 5239:471554b842d2
    16 
    16 
    17 from cubicweb.selectors import (implements, yes, match_user_groups,
    17 from cubicweb.selectors import (implements, yes, match_user_groups,
    18                                 has_related_entities, authenticated_user)
    18                                 has_related_entities, authenticated_user)
    19 from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
    19 from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
    20                              WORKFLOW_TYPES, INTERNAL_TYPES)
    20                              WORKFLOW_TYPES, INTERNAL_TYPES)
    21 from cubicweb.schemaviewer import SchemaViewer
       
    22 from cubicweb.view import EntityView, StartupView
    21 from cubicweb.view import EntityView, StartupView
    23 from cubicweb import tags, uilib
    22 from cubicweb import tags, uilib
    24 from cubicweb.web import action, facet, uicfg
    23 from cubicweb.web import action, facet, uicfg, schemaviewer
    25 from cubicweb.web.views import TmpFileViewMixin
    24 from cubicweb.web.views import TmpFileViewMixin
    26 from cubicweb.web.views import primary, baseviews, tabs, tableview, iprogress
    25 from cubicweb.web.views import primary, baseviews, tabs, tableview, iprogress
    27 
    26 
    28 ALWAYS_SKIP_TYPES = BASE_TYPES | SCHEMA_TYPES
    27 ALWAYS_SKIP_TYPES = BASE_TYPES | SCHEMA_TYPES
    29 SKIP_TYPES  = (ALWAYS_SKIP_TYPES | META_RTYPES | SYSTEM_RTYPES | WORKFLOW_TYPES
    28 SKIP_TYPES  = (ALWAYS_SKIP_TYPES | META_RTYPES | SYSTEM_RTYPES | WORKFLOW_TYPES
    34     if int(req.form.get('skipmeta', True)):
    33     if int(req.form.get('skipmeta', True)):
    35         return SKIP_TYPES
    34         return SKIP_TYPES
    36     return ALWAYS_SKIP_TYPES
    35     return ALWAYS_SKIP_TYPES
    37 
    36 
    38 _pvs = uicfg.primaryview_section
    37 _pvs = uicfg.primaryview_section
       
    38 _pvdc = uicfg.primaryview_display_ctrl
       
    39 
    39 for _action in ('read', 'add', 'update', 'delete'):
    40 for _action in ('read', 'add', 'update', 'delete'):
    40     _pvs.tag_subject_of(('*', '%s_permission' % _action, '*'), 'hidden')
    41     _pvs.tag_subject_of(('*', '%s_permission' % _action, '*'), 'hidden')
    41     _pvs.tag_object_of(('*', '%s_permission' % _action, '*'), 'hidden')
    42     _pvs.tag_object_of(('*', '%s_permission' % _action, '*'), 'hidden')
    42 
    43 
    43 _pvs.tag_object_of(('Workflow', 'workflow_of', 'CWEType'), 'hidden')
    44 for _etype in ('CWEType', 'CWRType', 'CWAttribute', 'CWRelation'):
    44 _pvs.tag_subject_of(('CWEType', 'default_workflow', 'Workflow'), 'hidden')
    45     _pvdc.tag_attribute((_etype, 'description'), {'showlabel': False})
    45 
    46 
       
    47 _pvs.tag_attribute(('CWEType', 'name'), 'hidden')
       
    48 _pvs.tag_attribute(('CWEType', 'final'), 'hidden')
       
    49 _pvs.tag_object_of(('*', 'workflow_of', 'CWEType'), 'hidden')
       
    50 _pvs.tag_subject_of(('CWEType', 'default_workflow', '*'), 'hidden')
       
    51 _pvs.tag_object_of(('*', 'specializes', 'CWEType'), 'hidden')
       
    52 _pvs.tag_subject_of(('CWEType', 'specializes', '*'), 'hidden')
       
    53 _pvs.tag_object_of(('*', 'from_entity', 'CWEType'), 'hidden')
       
    54 _pvs.tag_object_of(('*', 'to_entity', 'CWEType'), 'hidden')
       
    55 
       
    56 _pvs.tag_attribute(('CWRType', 'name'), 'hidden')
       
    57 _pvs.tag_attribute(('CWRType', 'final'), 'hidden')
    46 _pvs.tag_object_of(('*', 'relation_type', 'CWRType'), 'hidden')
    58 _pvs.tag_object_of(('*', 'relation_type', 'CWRType'), 'hidden')
       
    59 
       
    60 _pvs.tag_subject_of(('CWAttribute', 'constrained_by', '*'), 'hidden')
       
    61 _pvs.tag_subject_of(('CWRelation', 'constrained_by', '*'), 'hidden')
       
    62 
    47 
    63 
    48 class SecurityViewMixIn(object):
    64 class SecurityViewMixIn(object):
    49     """mixin providing methods to display security information for a entity,
    65     """mixin providing methods to display security information for a entity,
    50     relation or relation definition schema
    66     relation or relation definition schema
    51     """
    67     """
    59             _("permission"), _('granted to groups'), _('rql expressions')))
    75             _("permission"), _('granted to groups'), _('rql expressions')))
    60         for action in erschema.ACTIONS:
    76         for action in erschema.ACTIONS:
    61             w(u'<tr><td>%s</td><td>' % _(action))
    77             w(u'<tr><td>%s</td><td>' % _(action))
    62             if permissions is None:
    78             if permissions is None:
    63                 groups = erschema.get_groups(action)
    79                 groups = erschema.get_groups(action)
       
    80                 rqlexprs = sorted(e.expression for e in erschema.get_rqlexprs(action))
    64             else:
    81             else:
    65                 groups = permissions[action][0]
    82                 groups = permissions[action][0]
       
    83                 rqlexprs = permissions[action][1]
    66             # XXX get group entity and call it's incontext view
    84             # XXX get group entity and call it's incontext view
    67             groups = [u'<a class="%s" href="%s">%s</a>' % (
    85             groups = [u'<a class="%s" href="%s">%s</a>' % (
    68                 group, self._cw.build_url('cwgroup/%s' % group), label)
    86                 group, self._cw.build_url('cwgroup/%s' % group), label)
    69                       for group, label in sorted((_(g), g) for g in groups)]
    87                       for group, label in sorted((_(g), g) for g in groups)]
    70             w(u'<br/>'.join(groups))
    88             w(u'<br/>'.join(groups))
    71             w(u'</td><td>')
    89             w(u'</td><td>')
    72             if permissions is None:
       
    73                 rqlexprs = sorted(e.expression for e in erschema.get_rqlexprs(action))
       
    74             else:
       
    75                 rqlexprs = permissions[action][1]
       
    76             w(u'<br/>'.join(rqlexprs))
    90             w(u'<br/>'.join(rqlexprs))
    77             w(u'</td></tr>\n')
    91             w(u'</td></tr>\n')
    78         w(u'</table>')
    92         w(u'</table>')
    79 
    93 
    80     def grouped_permissions_table(self, rschema):
    94     def grouped_permissions_table(self, rschema):
   106 
   120 
   107 
   121 
   108 # global schema view ###########################################################
   122 # global schema view ###########################################################
   109 
   123 
   110 class SchemaView(tabs.TabsMixin, StartupView):
   124 class SchemaView(tabs.TabsMixin, StartupView):
       
   125     """display schema information (graphically, listing tables...) in tabs"""
   111     __regid__ = 'schema'
   126     __regid__ = 'schema'
   112     title = _('instance schema')
   127     title = _('instance schema')
   113     tabs = [_('schema-description'), _('schema-image'), _('schema-security')]
   128     tabs = [_('schema-image'), _('schema-entity-types'),
   114     default_tab = 'schema-description'
   129             _('schema-relation-types'), _('schema-security')]
       
   130     default_tab = 'schema-image'
   115 
   131 
   116     def call(self):
   132     def call(self):
   117         """display schema information"""
       
   118         self.w(u'<h1>%s</h1>' % _('Schema of the data model'))
   133         self.w(u'<h1>%s</h1>' % _('Schema of the data model'))
   119         self.render_tabs(self.tabs, self.default_tab)
   134         self.render_tabs(self.tabs, self.default_tab)
   120 
   135 
   121 
   136 
   122 class SchemaImageTab(StartupView):
   137 class SchemaImageTab(StartupView):
   125     def call(self):
   140     def call(self):
   126         self.w(_(u'<div>This schema of the data model <em>excludes</em> the '
   141         self.w(_(u'<div>This schema of the data model <em>excludes</em> the '
   127                  u'meta-data, but you can also display a <a href="%s">complete '
   142                  u'meta-data, but you can also display a <a href="%s">complete '
   128                  u'schema with meta-data</a>.</div>')
   143                  u'schema with meta-data</a>.</div>')
   129                % xml_escape(self._cw.build_url('view', vid='schemagraph', skipmeta=0)))
   144                % xml_escape(self._cw.build_url('view', vid='schemagraph', skipmeta=0)))
       
   145         self.w(u'<div><a href="%s">%s</a></div>' %
       
   146                (self._cw.build_url('view', vid='owl'),
       
   147                 self._cw._(u'Download schema as OWL')))
   130         self.w(u'<img src="%s" alt="%s"/>\n' % (
   148         self.w(u'<img src="%s" alt="%s"/>\n' % (
   131             xml_escape(self._cw.build_url('view', vid='schemagraph', skipmeta=1)),
   149             xml_escape(self._cw.build_url('view', vid='schemagraph', skipmeta=1)),
   132             self._cw._("graphical representation of the instance'schema")))
   150             self._cw._("graphical representation of the instance'schema")))
   133 
   151 
   134 
   152 
   135 class SchemaDescriptionTab(StartupView):
   153 class SchemaETypeTab(StartupView):
   136     __regid__ = 'schema-description'
   154     __regid__ = 'schema-entity-types'
   137 
   155 
   138     def call(self):
   156     def call(self):
   139         rset = self._cw.execute('Any X ORDERBY N WHERE X is CWEType, X name N, '
   157         self.wview('table', self._cw.execute(
   140                                 'X final FALSE')
   158             'Any X ORDERBY N WHERE X is CWEType, X name N, X final FALSE'))
   141         self.wview('table', rset, displayfilter=True)
   159 
   142         rset = self._cw.execute('Any X ORDERBY N WHERE X is CWRType, X name N, '
   160 
   143                                 'X final FALSE')
   161 class SchemaRTypeTab(StartupView):
   144         self.wview('table', rset, displayfilter=True)
   162     __regid__ = 'schema-relation-types'
   145         owl_downloadurl = self._cw.build_url('view', vid='owl')
   163 
   146         self.w(u'<div><a href="%s">%s</a></div>' %
   164     def call(self):
   147                (owl_downloadurl, self._cw._(u'Download schema as OWL')))
   165         self.wview('table', self._cw.execute(
       
   166             'Any X ORDERBY N WHERE X is CWRType, X name N, X final FALSE'))
   148 
   167 
   149 
   168 
   150 class SchemaPermissionsTab(SecurityViewMixIn, StartupView):
   169 class SchemaPermissionsTab(SecurityViewMixIn, StartupView):
   151     __regid__ = 'schema-security'
   170     __regid__ = 'schema-security'
   152     __select__ = StartupView.__select__ & match_user_groups('managers')
   171     __select__ = StartupView.__select__ & match_user_groups('managers')
   153 
   172 
   154     def call(self, display_relations=True):
   173     def call(self, display_relations=True):
   155         self._cw.add_css('cubicweb.acl.css')
       
   156         skiptypes = skip_types(self._cw)
   174         skiptypes = skip_types(self._cw)
   157         schema = self._cw.vreg.schema
   175         schema = self._cw.vreg.schema
   158         # compute entities
   176         # compute entities
   159         entities = sorted(eschema for eschema in schema.entities()
   177         entities = sorted(eschema for eschema in schema.entities()
   160                           if not (eschema.final or eschema in skiptypes))
   178                           if not (eschema.final or eschema in skiptypes))
   265 
   283 
   266 class CWETypeDescriptionTab(tabs.PrimaryTab):
   284 class CWETypeDescriptionTab(tabs.PrimaryTab):
   267     __regid__ = 'cwetype-description'
   285     __regid__ = 'cwetype-description'
   268     __select__ = tabs.PrimaryTab.__select__ & implements('CWEType')
   286     __select__ = tabs.PrimaryTab.__select__ & implements('CWEType')
   269 
   287 
   270     def render_entity_attributes(self, entity, siderelations=None):
   288     def render_entity_attributes(self, entity):
       
   289         super(CWETypeDescriptionTab, self).render_entity_attributes(entity)
   271         _ = self._cw._
   290         _ = self._cw._
   272         self.w(u'<div>%s</div>' % xml_escape(entity.description or u''))
   291         # inheritance
       
   292         if entity.specializes:
       
   293             self.w(u'<div>%s' % _('Parent classes:'))
       
   294             self.wview('csv', entity.related('specializes', 'subject'))
       
   295             self.w(u'</div>')
       
   296         if entity.reverse_specializes:
       
   297             self.w(u'<div>%s' % _('Sub-classes:'))
       
   298             self.wview('csv', entity.related('specializes', 'object'))
       
   299             self.w(u'</div>')
   273         # entity schema image
   300         # entity schema image
   274         url = entity.absolute_url(vid='schemagraph')
       
   275         self.w(u'<img src="%s" alt="%s"/>' % (
   301         self.w(u'<img src="%s" alt="%s"/>' % (
   276             xml_escape(url),
   302             xml_escape(entity.absolute_url(vid='schemagraph')),
   277             xml_escape(_('graphical schema for %s') % entity.name)))
   303             xml_escape(_('graphical schema for %s') % entity.name)))
   278         # entity schema attributes
   304         # entity schema attributes
   279         self.w(u'<h2>%s</h2>' % _('Attributes'))
   305         self.w(u'<h2>%s</h2>' % _('CWAttribute_plural'))
   280         rset = self._cw.execute(
   306         rset = self._cw.execute(
   281             'Any A,F,D,C,I,J,A,DE ORDERBY AA WHERE A is CWAttribute, '
   307             'Any A,ON,D,C,A,DE,A, IDX,FTI,I18N,R,O,RN,S ORDERBY AA '
       
   308             'WHERE A is CWAttribute, A from_entity S, S eid %(x)s, '
   282             'A ordernum AA, A defaultval D, A description DE, A cardinality C, '
   309             'A ordernum AA, A defaultval D, A description DE, A cardinality C, '
   283             'A fulltextindexed I, A internationalizable J, '
   310             'A fulltextindexed FTI, A internationalizable I18N, A indexed IDX, '
   284             'A relation_type R, R name N, A to_entity O, O name F, '
   311             'A relation_type R, R name RN, A to_entity O, O name ON',
   285             'A from_entity S, S eid %(x)s',
       
   286             {'x': entity.eid})
   312             {'x': entity.eid})
   287         self.wview('table', rset, 'null',
   313         self.wview('table', rset, 'null',
   288                    cellvids={0: 'rdef-name-cell',
   314                    cellvids={0: 'rdef-name-cell',
   289                              3: 'etype-attr-cardinality-cell',
   315                              3: 'etype-attr-cardinality-cell',
   290                              6: 'rdef-constraints-cell'},
   316                              4: 'rdef-constraints-cell',
       
   317                              6: 'rdef-options-cell'},
   291                    headers=(_(u'name'), _(u'type'),
   318                    headers=(_(u'name'), _(u'type'),
   292                             _(u'default value'), _(u'required'),
   319                             _(u'default value'), _(u'required'),
   293                             _(u'fulltext indexed'), _(u'internationalizable'),
   320                             _(u'constraints'), _(u'description'), _('options')))
   294                             _(u'constraints'), _(u'description')),
       
   295                    mainindex=0)
       
   296         # entity schema relations
   321         # entity schema relations
   297         self.w(u'<h2>%s</h2>' % _('Relations'))
   322         self.w(u'<h2>%s</h2>' % _('CWRelation_plural'))
       
   323         cellvids = {0: 'rdef-name-cell',
       
   324                     2: 'etype-rel-cardinality-cell',
       
   325                     3: 'rdef-constraints-cell',
       
   326                     4: 'rdef-options-cell'}
       
   327         headers= [_(u'name'), _(u'object type'), _(u'cardinality'),
       
   328                   _(u'constraints'), _(u'options')]
   298         rset = self._cw.execute(
   329         rset = self._cw.execute(
   299             'Any A,TT,"i18ncard_"+SUBSTRING(C, 1, 1),K,A,TTN ORDERBY RN '
   330             'Any A,TT,"i18ncard_"+SUBSTRING(C,1,1),A,A, K,TTN,R,RN ORDERBY RN '
   300             'WHERE A is CWRelation, A composite K, A cardinality C, '
   331             'WHERE A is CWRelation, A from_entity S, S eid %(x)s, '
   301             'A relation_type R, R name RN, '
   332             'A composite K, A cardinality C, '
   302             'A to_entity TT, TT name TTN, A from_entity S, S eid %(x)s',
   333             'A relation_type R, R name RN, A to_entity TT, TT name TTN',
   303             {'x': entity.eid})
   334             {'x': entity.eid})
   304         if rset:
   335         if rset:
   305             self.w(u'<h5>%s %s</h5>' % (entity.name, _('is subject of:')))
   336             self.w(u'<h5>%s %s</h5>' % (entity.name, _('is subject of:')))
   306         self.wview('table', rset, 'null',
   337             self.wview('table', rset, cellvids=cellvids, headers=headers)
   307                    cellvids={0: 'rdef-name-cell',
       
   308                              2: 'etype-rel-cardinality-cell',
       
   309                              4: 'rdef-constraints-cell'},
       
   310                    headers=(_(u'name'), _(u'object type'), _(u'cardinality'),
       
   311                             _(u'composite'), _(u'constraints')),
       
   312                    displaycols=range(5))
       
   313         self.w(u'<br/>')
       
   314         rset = self._cw.execute(
   338         rset = self._cw.execute(
   315             'Any A,TT,"i18ncard_"+SUBSTRING(C, 2, 1),K,A,TTN ORDERBY RN '
   339             'Any A,TT,"i18ncard_"+SUBSTRING(C,1,1),A,A, K,TTN,R,RN ORDERBY RN '
   316             'WHERE A is CWRelation, A composite K, A cardinality C, '
   340             'WHERE A is CWRelation, A to_entity O, O eid %(x)s, '
   317             'A relation_type R, R name RN, '
   341             'A composite K, A cardinality C, '
   318             'A from_entity TT, TT name TTN, A to_entity O, O eid %(x)s',
   342             'A relation_type R, R name RN, A from_entity TT, TT name TTN',
   319             {'x': entity.eid})
   343             {'x': entity.eid})
   320         if rset:
   344         if rset:
       
   345             cellvids[0] = 'rdef-object-name-cell'
       
   346             headers[1] = _(u'subject type')
   321             self.w(u'<h5>%s %s</h5>' % (entity.name, _('is object of:')))
   347             self.w(u'<h5>%s %s</h5>' % (entity.name, _('is object of:')))
   322         self.wview('table', rset, 'null',
   348             self.wview('table', rset, cellvids=cellvids, headers=headers)
   323                    cellvids={0: 'rdef-object-name-cell',
       
   324                              2: 'etype-rel-cardinality-cell',
       
   325                              4: 'rdef-constraints-cell'},
       
   326                    headers=(_(u'name'), _(u'subject type'), _(u'cardinality'),
       
   327                             _(u'composite'), _(u'constraints')),
       
   328                    displaycols=range(5))
       
   329 
   349 
   330 
   350 
   331 class CWETypeAttributeCardinalityCell(baseviews.FinalView):
   351 class CWETypeAttributeCardinalityCell(baseviews.FinalView):
   332     __regid__ = 'etype-attr-cardinality-cell'
   352     __regid__ = 'etype-attr-cardinality-cell'
   333 
   353 
   348 class CWETypeBoxTab(EntityView):
   368 class CWETypeBoxTab(EntityView):
   349     __regid__ = 'cwetype-box'
   369     __regid__ = 'cwetype-box'
   350     __select__ = implements('CWEType')
   370     __select__ = implements('CWEType')
   351 
   371 
   352     def cell_call(self, row, col):
   372     def cell_call(self, row, col):
   353         viewer = SchemaViewer(self._cw)
   373         viewer = schemaviewer.SchemaViewer(self._cw)
   354         entity = self.cw_rset.get_entity(row, col)
   374         entity = self.cw_rset.get_entity(row, col)
   355         eschema = self._cw.vreg.schema.eschema(entity.name)
   375         eschema = self._cw.vreg.schema.eschema(entity.name)
   356         layout = viewer.visit_entityschema(eschema)
   376         layout = viewer.visit_entityschema(eschema)
   357         self.w(uilib.ureport_as_html(layout))
   377         self.w(uilib.ureport_as_html(layout))
   358         self.w(u'<br class="clear"/>')
   378         self.w(u'<br class="clear"/>')
   361 class CWETypePermTab(SecurityViewMixIn, EntityView):
   381 class CWETypePermTab(SecurityViewMixIn, EntityView):
   362     __regid__ = 'cwetype-permissions'
   382     __regid__ = 'cwetype-permissions'
   363     __select__ = implements('CWEType') & authenticated_user()
   383     __select__ = implements('CWEType') & authenticated_user()
   364 
   384 
   365     def cell_call(self, row, col):
   385     def cell_call(self, row, col):
   366         self._cw.add_css('cubicweb.acl.css')
       
   367         entity = self.cw_rset.get_entity(row, col)
   386         entity = self.cw_rset.get_entity(row, col)
   368         eschema = self._cw.vreg.schema.eschema(entity.name)
   387         eschema = self._cw.vreg.schema.eschema(entity.name)
       
   388         self.w(u'<h4>%s</h4>' % _('This entity type permissions:').capitalize())
       
   389         self.permissions_table(eschema)
   369         self.w(u'<div style="margin: 0px 1.5em">')
   390         self.w(u'<div style="margin: 0px 1.5em">')
   370         self.permissions_table(eschema)
   391         self.w(u'<h4>%s</h4>' % _('Attributes permissions:').capitalize())
   371         self.w(u'<h4>%s</h4>' % _('attributes permissions:').capitalize())
       
   372         for attr, etype in  eschema.attribute_definitions():
   392         for attr, etype in  eschema.attribute_definitions():
   373             if attr not in META_RTYPES:
   393             if attr not in META_RTYPES:
   374                 rdef = eschema.rdef(attr)
   394                 rdef = eschema.rdef(attr)
   375                 attrtype = str(rdef.rtype)
   395                 attrtype = str(rdef.rtype)
   376                 self.w(u'<h4 class="schema">%s (%s)</h4> ' % (attrtype, _(attrtype)))
   396                 self.w(u'<h4 class="schema">%s (%s)</h4> ' % (attrtype, _(attrtype)))
   407         self.w('<a href="%s">%s</a>' % (
   427         self.w('<a href="%s">%s</a>' % (
   408             wf.absolute_url(), self._cw._('more info about this workflow')))
   428             wf.absolute_url(), self._cw._('more info about this workflow')))
   409 
   429 
   410 
   430 
   411 class CWETypeViewsTab(EntityView):
   431 class CWETypeViewsTab(EntityView):
       
   432     """possible views for this entity type"""
   412     __regid__ = 'cwetype-views'
   433     __regid__ = 'cwetype-views'
   413     __select__ = EntityView.__select__ & implements('CWEType')
   434     __select__ = EntityView.__select__ & implements('CWEType')
   414 
   435 
   415     def cell_call(self, row, col):
   436     def cell_call(self, row, col):
   416         entity = self.cw_rset.get_entity(row, col)
   437         entity = self.cw_rset.get_entity(row, col)
   417         etype = entity.name
       
   418         _ = self._cw._
   438         _ = self._cw._
   419         # possible views for this entity type
   439         self.w('<div>%s</div>' % _('Non exhaustive list of views that may '
   420         views = [(_(view.title),) for view in self.possible_views(etype)]
   440                                    'apply to entities of this type'))
   421         self.wview('pyvaltable', pyvalue=sorted(views), headers=(_(u'views'),))
   441         views = [(view.content_type, view.__regid__, _(view.title))
       
   442                  for view in self.possible_views(entity.name)]
       
   443         self.wview('pyvaltable', pyvalue=sorted(views),
       
   444                    headers=(_(u'content type'), _(u'view identifier'),
       
   445                             _(u'view title')))
   422 
   446 
   423     def possible_views(self, etype):
   447     def possible_views(self, etype):
   424         rset = self._cw.etype_rset(etype)
   448         rset = self._cw.etype_rset(etype)
   425         return [v for v in self._cw.vreg['views'].possible_views(self._cw, rset)
   449         return [v for v in self._cw.vreg['views'].possible_views(self._cw, rset)
   426                 if v.category != 'startupview']
   450                 if v.category != 'startupview']
   448 
   472 
   449 class CWRTypeDescriptionTab(tabs.PrimaryTab):
   473 class CWRTypeDescriptionTab(tabs.PrimaryTab):
   450     __regid__ = 'cwrtype-description'
   474     __regid__ = 'cwrtype-description'
   451     __select__ = implements('CWRType')
   475     __select__ = implements('CWRType')
   452 
   476 
   453     def render_entity_attributes(self, entity, siderelations=None):
   477     def render_entity_attributes(self, entity):
       
   478         super(CWRTypeDescriptionTab, self).render_entity_attributes(entity)
   454         _ = self._cw._
   479         _ = self._cw._
   455         self.w(u'<div>%s</div>' % xml_escape(entity.description or u''))
   480         if not entity.final:
   456         rschema = self._cw.vreg.schema.rschema(entity.name)
       
   457         if not rschema.final:
       
   458             msg = _('graphical schema for %s') % entity.name
   481             msg = _('graphical schema for %s') % entity.name
   459             self.w(tags.img(src=entity.absolute_url(vid='schemagraph'),
   482             self.w(tags.img(src=entity.absolute_url(vid='schemagraph'),
   460                             alt=msg))
   483                             alt=msg))
   461         rset = self._cw.execute('Any R,C,CC,R WHERE R is CWRelation, '
   484         rset = self._cw.execute('Any R,C,R,R, RT WHERE '
   462                                 'R relation_type RT, RT eid %(x)s, '
   485                                 'R relation_type RT, RT eid %(x)s, '
   463                                 'R cardinality C, R composite CC',
   486                                 'R cardinality C', {'x': entity.eid})
   464                                 {'x': entity.eid})
       
   465         self.wview('table', rset, 'null',
   487         self.wview('table', rset, 'null',
   466                    headers=(_(u'relation'),  _(u'cardinality'), _(u'composite'),
   488                    headers=(_(u'relation'),  _(u'cardinality'), _(u'constraints'),
   467                             _(u'constraints')),
   489                             _(u'options')),
   468                    cellvids={3: 'rdef-constraints-cell'})
   490                    cellvids={2: 'rdef-constraints-cell',
       
   491                              3: 'rdef-options-cell'})
   469 
   492 
   470 
   493 
   471 class CWRTypePermTab(SecurityViewMixIn, EntityView):
   494 class CWRTypePermTab(SecurityViewMixIn, EntityView):
   472     __regid__ = 'cwrtype-permissions'
   495     __regid__ = 'cwrtype-permissions'
   473     __select__ = implements('CWRType') & authenticated_user()
   496     __select__ = implements('CWRType') & authenticated_user()
   474 
   497 
   475     def cell_call(self, row, col):
   498     def cell_call(self, row, col):
   476         self._cw.add_css('cubicweb.acl.css')
       
   477         entity = self.cw_rset.get_entity(row, col)
   499         entity = self.cw_rset.get_entity(row, col)
   478         rschema = self._cw.vreg.schema.rschema(entity.name)
   500         rschema = self._cw.vreg.schema.rschema(entity.name)
   479         self.grouped_permissions_table(rschema)
   501         self.grouped_permissions_table(rschema)
   480 
   502 
   481 
   503 
   482 # CWAttribute / CWRelation #####################################################
   504 # CWAttribute / CWRelation #####################################################
   483 
   505 
   484 class CWRDEFPrimaryView(tabs.TabbedPrimaryView):
   506 class RDEFPrimaryView(tabs.TabbedPrimaryView):
   485     __select__ = implements('CWRelation', 'CWAttribute')
   507     __select__ = implements('CWRelation', 'CWAttribute')
   486     tabs = [_('cwrdef-description'), _('cwrdef-permissions')]
   508     tabs = [_('rdef-description'), _('rdef-permissions')]
   487     default_tab = 'cwrdef-description'
   509     default_tab = 'rdef-description'
   488 
   510 
   489 class CWRDEFDescriptionTab(tabs.PrimaryTab):
   511 
   490     __regid__ = 'cwrdef-description'
   512 class RDEFDescriptionTab(tabs.PrimaryTab):
       
   513     __regid__ = 'rdef-description'
   491     __select__ = implements('CWRelation', 'CWAttribute')
   514     __select__ = implements('CWRelation', 'CWAttribute')
   492 
   515 
   493 class CWRDEFPermTab(SecurityViewMixIn, EntityView):
   516     def render_entity_attributes(self, entity):
   494     __regid__ = 'cwrdef-permissions'
   517         super(RDEFDescriptionTab, self).render_entity_attributes(entity)
       
   518         rdef = entity.yams_schema()
       
   519         if rdef.constraints:
       
   520             self.w(u'<h4>%s</h4>' % self._cw._('constrained_by'))
       
   521             self.w(entity.view('rdef-constraints-cell'))
       
   522 
       
   523 
       
   524 class RDEFPermTab(SecurityViewMixIn, EntityView):
       
   525     __regid__ = 'rdef-permissions'
   495     __select__ = implements('CWRelation', 'CWAttribute') & authenticated_user()
   526     __select__ = implements('CWRelation', 'CWAttribute') & authenticated_user()
   496 
   527 
   497     def cell_call(self, row, col):
   528     def cell_call(self, row, col):
   498         entity = self.cw_rset.get_entity(row, col)
   529         self.permissions_table(self.cw_rset.get_entity(row, col).yams_schema())
   499         rschema = self._cw.vreg.schema.rschema(entity.rtype.name)
   530 
   500         rdef = rschema.rdefs[(entity.stype.name, entity.otype.name)]
   531 
   501         self.permissions_table(rdef)
   532 class RDEFNameView(tableview.CellView):
   502 
       
   503 
       
   504 class CWRDEFNameView(tableview.CellView):
       
   505     """display relation name and its translation only in a cell view, link to
   533     """display relation name and its translation only in a cell view, link to
   506     relation definition's primary view (for use in entity type relations table
   534     relation definition's primary view (for use in entity type relations table
   507     for instance)
   535     for instance)
   508     """
   536     """
   509     __regid__ = 'rdef-name-cell'
   537     __regid__ = 'rdef-name-cell'
   510     __select__ = implements('CWRelation', 'CWAttribute')
   538     __select__ = implements('CWRelation', 'CWAttribute')
   511 
   539 
   512     def cell_call(self, row, col):
   540     def cell_call(self, row, col):
   513         entity = self.cw_rset.get_entity(row, col)
   541         entity = self.cw_rset.get_entity(row, col)
   514         rtype = entity.relation_type[0].name
   542         rtype = entity.relation_type[0].name
   515         # XXX use contect entity + pgettext
   543         # XXX use context entity + pgettext
   516         self.w(u'<a href="%s">%s</a> (%s)' % (
   544         self.w(u'<a href="%s">%s</a> (%s)' % (
   517             entity.absolute_url(), rtype, self._cw._(rtype)))
   545             entity.absolute_url(), rtype, self._cw._(rtype)))
   518 
   546 
   519 class CWRDEFObjectNameView(tableview.CellView):
   547 class RDEFObjectNameView(tableview.CellView):
   520     """same as CWRDEFNameView but when the context is the object entity
   548     """same as RDEFNameView but when the context is the object entity
   521     """
   549     """
   522     __regid__ = 'rdef-object-name-cell'
   550     __regid__ = 'rdef-object-name-cell'
   523     __select__ = implements('CWRelation', 'CWAttribute')
   551     __select__ = implements('CWRelation', 'CWAttribute')
   524 
   552 
   525     def cell_call(self, row, col):
   553     def cell_call(self, row, col):
   526         entity = self.cw_rset.get_entity(row, col)
   554         entity = self.cw_rset.get_entity(row, col)
   527         rtype = entity.relation_type[0].name
   555         rtype = entity.relation_type[0].name
   528         # XXX use contect entity + pgettext
   556         # XXX use context entity + pgettext
   529         self.w(u'<a href="%s">%s</a> (%s)' % (
   557         self.w(u'<a href="%s">%s</a> (%s)' % (
   530             entity.absolute_url(), rtype, self._cw.__(rtype + '_object')))
   558             entity.absolute_url(), rtype, self._cw.__(rtype + '_object')))
   531 
   559 
   532 class CWRDEFConstraintsCell(EntityView):
   560 class RDEFConstraintsCell(EntityView):
   533     __regid__ = 'rdef-constraints-cell'
   561     __regid__ = 'rdef-constraints-cell'
   534     __select__ = implements('CWAttribute', 'CWRelation')
   562     __select__ = implements('CWAttribute', 'CWRelation')
   535 
   563 
   536     def cell_call(self, row, col):
   564     def cell_call(self, row, col):
   537         entity = self.cw_rset.get_entity(row, col)
   565         entity = self.cw_rset.get_entity(row, col)
   538         rschema = self._cw.vreg.schema.rschema(entity.rtype.name)
   566         rschema = self._cw.vreg.schema.rschema(entity.rtype.name)
   539         rdef = rschema.rdefs[(entity.stype.name, entity.otype.name)]
   567         rdef = rschema.rdefs[(entity.stype.name, entity.otype.name)]
   540         constraints = [xml_escape(str(c)) for c in getattr(rdef, 'constraints')]
   568         constraints = [xml_escape(str(c)) for c in getattr(rdef, 'constraints')]
   541         self.w(u'<br/>'.join(constraints))
   569         self.w(u'<br/>'.join(constraints))
       
   570 
       
   571 class CWAttributeOptionsCell(EntityView):
       
   572     __regid__ = 'rdef-options-cell'
       
   573     __select__ = implements('CWAttribute')
       
   574 
       
   575     def cell_call(self, row, col):
       
   576         entity = self.cw_rset.get_entity(row, col)
       
   577         options = []
       
   578         if entity.indexed:
       
   579             options.append(self._cw._('indexed'))
       
   580         if entity.fulltextindexed:
       
   581             options.append(self._cw._('fulltextindexed'))
       
   582         if entity.internationalizable:
       
   583             options.append(self._cw._('internationalizable'))
       
   584         self.w(u','.join(options))
       
   585 
       
   586 class CWRelationOptionsCell(EntityView):
       
   587     __regid__ = 'rdef-options-cell'
       
   588     __select__ = implements('CWRelation',)
       
   589 
       
   590     def cell_call(self, row, col):
       
   591         entity = self.cw_rset.get_entity(row, col)
       
   592         rtype = entity.rtype
       
   593         options = []
       
   594         if rtype.symmetric:
       
   595             options.append(self._cw._('symmetric'))
       
   596         if rtype.inlined:
       
   597             options.append(self._cw._('inlined'))
       
   598         if rtype.fulltext_container:
       
   599             options.append('%s=%s' % (self._cw._('fulltext_container'),
       
   600                                       self._cw._(rtype.fulltext_container)))
       
   601         if entity.composite:
       
   602             options.append('%s=%s' % (self._cw._('composite'),
       
   603                                       self._cw._(entity.composite)))
       
   604         self.w(u','.join(options))
   542 
   605 
   543 
   606 
   544 # schema images ###############################################################
   607 # schema images ###############################################################
   545 
   608 
   546 class RestrictedSchemaVisitorMixIn(object):
   609 class RestrictedSchemaVisitorMixIn(object):