ticket #787103, entity schema view enhancements
authorSandrine Ribeau <sandrine.ribeau@logilab.fr>
Thu, 25 Mar 2010 08:30:53 -0700
changeset 5233 673b63953e7a
parent 5232 78c1a531f7b3
child 5234 e2476d78b060
ticket #787103, entity schema view enhancements
i18n/en.po
i18n/es.po
i18n/fr.po
schemaviewer.py
server/test/unittest_rql2sql.py
web/data/cubicweb.schema.css
web/views/schema.py
--- a/i18n/en.po	Wed Mar 24 15:31:37 2010 -0700
+++ b/i18n/en.po	Thu Mar 25 08:30:53 2010 -0700
@@ -191,15 +191,15 @@
 msgid "AND"
 msgstr ""
 
-msgid "Add permissions"
-msgstr ""
-
 msgid "Any"
 msgstr ""
 
 msgid "Attributes"
 msgstr ""
 
+msgid "Attributes with non default permissions:"
+msgstr ""
+
 # schema pot file, generated on 2009-09-16 16:46:55
 #
 # singular and plural forms for each entity type
@@ -365,12 +365,12 @@
 msgid "Decimal_plural"
 msgstr "Decimal numbers"
 
-msgid "Delete permissions"
-msgstr ""
-
 msgid "Do you want to delete the following element(s) ?"
 msgstr ""
 
+msgid "Download schema as OWL"
+msgstr ""
+
 msgctxt "inlined:CWUser.use_email.subject"
 msgid "EmailAddress"
 msgstr "Email address"
@@ -384,6 +384,9 @@
 msgid "Entities"
 msgstr ""
 
+msgid "Entity types"
+msgstr ""
+
 msgid "ExternalUri"
 msgstr "External Uri"
 
@@ -411,6 +414,9 @@
 msgid "Help"
 msgstr ""
 
+msgid "Index"
+msgstr ""
+
 msgid "Instance"
 msgstr ""
 
@@ -513,6 +519,12 @@
 msgid "Password_plural"
 msgstr "Passwords"
 
+msgid "Permissions for entity types"
+msgstr ""
+
+msgid "Permissions for relations"
+msgstr ""
+
 msgid "Please note that this is only a shallow copy"
 msgstr ""
 
@@ -531,9 +543,6 @@
 msgid "RQLVocabularyConstraint"
 msgstr "RQL vocabulary constraint"
 
-msgid "Read permissions"
-msgstr ""
-
 msgid "Recipients:"
 msgstr ""
 
@@ -543,6 +552,9 @@
 msgid "Registry's content"
 msgstr ""
 
+msgid "Relation types"
+msgstr ""
+
 msgid "Relations"
 msgstr ""
 
@@ -699,9 +711,6 @@
 msgid "Unreachable objects"
 msgstr ""
 
-msgid "Update permissions"
-msgstr ""
-
 msgid "Used by:"
 msgstr ""
 
@@ -1201,7 +1210,7 @@
 msgid "attribute"
 msgstr ""
 
-msgid "attributes with modified permissions:"
+msgid "attributes permissions:"
 msgstr ""
 
 msgid "august"
@@ -1800,8 +1809,8 @@
 msgid "custom_workflow_object"
 msgstr "custom workflow of"
 
-msgid "cwetype-schema-image"
-msgstr "schema"
+msgid "cwetype-box"
+msgstr "box"
 
 msgid "cwetype-schema-permissions"
 msgstr "permissions"
@@ -1809,6 +1818,9 @@
 msgid "cwetype-schema-text"
 msgstr "description"
 
+msgid "cwetype-views"
+msgstr "views"
+
 msgid "cwetype-workflow"
 msgstr "workflow"
 
@@ -1839,6 +1851,9 @@
 msgid "default user workflow"
 msgstr ""
 
+msgid "default value"
+msgstr ""
+
 msgid "default workflow for an entity type"
 msgstr ""
 
@@ -2360,6 +2375,9 @@
 msgid "full text or RQL query"
 msgstr ""
 
+msgid "fulltext indexed"
+msgstr ""
+
 msgid "fulltext_container"
 msgstr "fulltext container"
 
@@ -2452,6 +2470,18 @@
 msgid "i18n_login_popup"
 msgstr "login"
 
+msgid "i18ncard_*"
+msgstr "0..n"
+
+msgid "i18ncard_+"
+msgstr "1..n"
+
+msgid "i18ncard_1"
+msgstr "1"
+
+msgid "i18ncard_?"
+msgstr "0..1"
+
 msgid "i18nprevnext_next"
 msgstr "next"
 
@@ -2523,9 +2553,6 @@
 msgid "incorrect value (%(value)s) for type \"%(type)s\""
 msgstr ""
 
-msgid "index"
-msgstr ""
-
 msgid "index this attribute's value in the plain text index"
 msgstr ""
 
@@ -2598,6 +2625,12 @@
 msgid "is"
 msgstr ""
 
+msgid "is object of:"
+msgstr ""
+
+msgid "is subject of:"
+msgstr ""
+
 msgid ""
 "is the subject/object entity of the relation composed of the other ? This "
 "implies that when the composite is deleted, composants are also deleted."
@@ -2933,8 +2966,8 @@
 msgid "object"
 msgstr ""
 
-msgid "object_plural:"
-msgstr "objects:"
+msgid "object type"
+msgstr ""
 
 msgid "october"
 msgstr ""
@@ -3018,12 +3051,6 @@
 msgid "permissions"
 msgstr ""
 
-msgid "permissions for entities"
-msgstr ""
-
-msgid "permissions for relations"
-msgstr ""
-
 msgid "permissions for this entity"
 msgstr ""
 
@@ -3146,6 +3173,9 @@
 msgid "relation add"
 msgstr ""
 
+msgid "relation direction"
+msgstr ""
+
 msgid "relation removal"
 msgstr ""
 
@@ -3167,9 +3197,6 @@
 msgid "relation_type_object"
 msgstr "relation definitions"
 
-msgid "relations"
-msgstr ""
-
 msgid "relations deleted"
 msgstr ""
 
@@ -3257,6 +3284,9 @@
 msgid "schema-image"
 msgstr "schema"
 
+msgid "schema-security"
+msgstr "permissions"
+
 msgid "schema-text"
 msgstr "description"
 
@@ -3445,12 +3475,12 @@
 msgid "subject"
 msgstr ""
 
+msgid "subject type"
+msgstr ""
+
 msgid "subject/object cardinality"
 msgstr ""
 
-msgid "subject_plural:"
-msgstr "subjects:"
-
 msgid "subworkflow"
 msgstr ""
 
--- a/i18n/es.po	Wed Mar 24 15:31:37 2010 -0700
+++ b/i18n/es.po	Thu Mar 25 08:30:53 2010 -0700
@@ -199,15 +199,15 @@
 msgid "AND"
 msgstr "Y"
 
-msgid "Add permissions"
-msgstr "Añadir autorizaciónes"
-
 msgid "Any"
 msgstr "Cualquiera"
 
 msgid "Attributes"
 msgstr "Atributos"
 
+msgid "Attributes with non default permissions:"
+msgstr ""
+
 # schema pot file, generated on 2009-09-16 16:46:55
 #
 # singular and plural forms for each entity type
@@ -373,12 +373,12 @@
 msgid "Decimal_plural"
 msgstr "Decimales"
 
-msgid "Delete permissions"
-msgstr "Autorización de suprimir"
-
 msgid "Do you want to delete the following element(s) ?"
 msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
 
+msgid "Download schema as OWL"
+msgstr ""
+
 msgctxt "inlined:CWUser.use_email.subject"
 msgid "EmailAddress"
 msgstr ""
@@ -392,6 +392,9 @@
 msgid "Entities"
 msgstr "Entidades"
 
+msgid "Entity types"
+msgstr ""
+
 msgid "ExternalUri"
 msgstr ""
 
@@ -419,6 +422,9 @@
 msgid "Help"
 msgstr ""
 
+msgid "Index"
+msgstr ""
+
 msgid "Instance"
 msgstr ""
 
@@ -521,6 +527,12 @@
 msgid "Password_plural"
 msgstr "Contraseñas"
 
+msgid "Permissions for entity types"
+msgstr ""
+
+msgid "Permissions for relations"
+msgstr ""
+
 msgid "Please note that this is only a shallow copy"
 msgstr "Recuerde que no es más que una copia superficial"
 
@@ -539,9 +551,6 @@
 msgid "RQLVocabularyConstraint"
 msgstr ""
 
-msgid "Read permissions"
-msgstr "Autorización de leer"
-
 msgid "Recipients:"
 msgstr "Destinatarios"
 
@@ -551,6 +560,9 @@
 msgid "Registry's content"
 msgstr ""
 
+msgid "Relation types"
+msgstr ""
+
 msgid "Relations"
 msgstr "Relaciones"
 
@@ -707,9 +719,6 @@
 msgid "Unreachable objects"
 msgstr ""
 
-msgid "Update permissions"
-msgstr "Autorización de modificar"
-
 msgid "Used by:"
 msgstr "Utilizado por :"
 
@@ -1226,8 +1235,8 @@
 msgid "attribute"
 msgstr "Atributo"
 
-msgid "attributes with modified permissions:"
-msgstr "atributos con autorizaciónes modificadas:"
+msgid "attributes permissions:"
+msgstr ""
 
 msgid "august"
 msgstr "Agosto"
@@ -1841,8 +1850,8 @@
 msgid "custom_workflow_object"
 msgstr ""
 
-msgid "cwetype-schema-image"
-msgstr "Esquema"
+msgid "cwetype-box"
+msgstr ""
 
 msgid "cwetype-schema-permissions"
 msgstr "Autorizaciónes"
@@ -1850,6 +1859,9 @@
 msgid "cwetype-schema-text"
 msgstr "Modelo de datos"
 
+msgid "cwetype-views"
+msgstr ""
+
 msgid "cwetype-workflow"
 msgstr "Workflow"
 
@@ -1880,6 +1892,9 @@
 msgid "default user workflow"
 msgstr ""
 
+msgid "default value"
+msgstr ""
+
 msgid "default workflow for an entity type"
 msgstr ""
 
@@ -2410,6 +2425,9 @@
 msgid "full text or RQL query"
 msgstr "Texto de búsqueda o demanda RQL"
 
+msgid "fulltext indexed"
+msgstr ""
+
 msgid "fulltext_container"
 msgstr "Contenedor de texto indexado"
 
@@ -2508,6 +2526,18 @@
 msgid "i18n_login_popup"
 msgstr "Identificarse"
 
+msgid "i18ncard_*"
+msgstr ""
+
+msgid "i18ncard_+"
+msgstr ""
+
+msgid "i18ncard_1"
+msgstr ""
+
+msgid "i18ncard_?"
+msgstr ""
+
 msgid "i18nprevnext_next"
 msgstr "Siguiente"
 
@@ -2581,9 +2611,6 @@
 msgid "incorrect value (%(value)s) for type \"%(type)s\""
 msgstr "valor %(value)s incorrecto para el tipo \"%(type)s\""
 
-msgid "index"
-msgstr "Indice"
-
 msgid "index this attribute's value in the plain text index"
 msgstr "Indexar el valor de este atributo en el índice de texto simple"
 
@@ -2657,6 +2684,12 @@
 msgid "is"
 msgstr "es"
 
+msgid "is object of:"
+msgstr "es objeto de"
+
+msgid "is subject of:"
+msgstr "es sujeto de"
+
 msgid ""
 "is the subject/object entity of the relation composed of the other ? This "
 "implies that when the composite is deleted, composants are also deleted."
@@ -3007,8 +3040,8 @@
 msgid "object"
 msgstr "objeto"
 
-msgid "object_plural:"
-msgstr "objetos:"
+msgid "object type"
+msgstr ""
 
 msgid "october"
 msgstr "octubre"
@@ -3091,12 +3124,6 @@
 msgid "permissions"
 msgstr ""
 
-msgid "permissions for entities"
-msgstr "autorizaciónes para entidades"
-
-msgid "permissions for relations"
-msgstr "autorizaciónes para relaciones"
-
 msgid "permissions for this entity"
 msgstr "Permisos para esta entidad"
 
@@ -3219,6 +3246,9 @@
 msgid "relation add"
 msgstr ""
 
+msgid "relation direction"
+msgstr ""
+
 msgid "relation removal"
 msgstr ""
 
@@ -3240,9 +3270,6 @@
 msgid "relation_type_object"
 msgstr "Definición"
 
-msgid "relations"
-msgstr "relaciones"
-
 msgid "relations deleted"
 msgstr "Relaciones eliminadas"
 
@@ -3334,6 +3361,9 @@
 msgid "schema-image"
 msgstr "esquema imagen"
 
+msgid "schema-security"
+msgstr ""
+
 msgid "schema-text"
 msgstr "esquema text"
 
@@ -3526,12 +3556,12 @@
 msgid "subject"
 msgstr "sujeto"
 
+msgid "subject type"
+msgstr ""
+
 msgid "subject/object cardinality"
 msgstr "cardinalidad sujeto/objeto"
 
-msgid "subject_plural:"
-msgstr "sujetos:"
-
 msgid "subworkflow"
 msgstr ""
 
--- a/i18n/fr.po	Wed Mar 24 15:31:37 2010 -0700
+++ b/i18n/fr.po	Thu Mar 25 08:30:53 2010 -0700
@@ -198,15 +198,15 @@
 msgid "AND"
 msgstr "ET"
 
-msgid "Add permissions"
-msgstr "Permissions d'ajouter"
-
 msgid "Any"
 msgstr "N'importe"
 
 msgid "Attributes"
 msgstr "Attributs"
 
+msgid "Attributes with non default permissions:"
+msgstr "Attributs ayant des permissions non-standard"
+
 # schema pot file, generated on 2009-09-16 16:46:55
 #
 # singular and plural forms for each entity type
@@ -384,12 +384,12 @@
 msgid "Decimal_plural"
 msgstr "Nombres décimaux"
 
-msgid "Delete permissions"
-msgstr "Permissions de supprimer"
-
 msgid "Do you want to delete the following element(s) ?"
 msgstr "Voulez-vous supprimer le(s) élément(s) suivant(s) ?"
 
+msgid "Download schema as OWL"
+msgstr "Télécharger le schéma au format OWL"
+
 msgctxt "inlined:CWUser.use_email.subject"
 msgid "EmailAddress"
 msgstr "Adresse électronique"
@@ -403,6 +403,9 @@
 msgid "Entities"
 msgstr "entités"
 
+msgid "Entity types"
+msgstr "Types d'entités"
+
 msgid "ExternalUri"
 msgstr "Uri externe"
 
@@ -430,6 +433,9 @@
 msgid "Help"
 msgstr "Aide"
 
+msgid "Index"
+msgstr ""
+
 msgid "Instance"
 msgstr "Instance"
 
@@ -532,6 +538,12 @@
 msgid "Password_plural"
 msgstr "Mots de passe"
 
+msgid "Permissions for entity types"
+msgstr "Permissions pour les types d'entités"
+
+msgid "Permissions for relations"
+msgstr "Permissions pour les relations"
+
 msgid "Please note that this is only a shallow copy"
 msgstr "Attention, cela n'effectue qu'une copie de surface"
 
@@ -550,9 +562,6 @@
 msgid "RQLVocabularyConstraint"
 msgstr "contrainte rql de vocabulaire"
 
-msgid "Read permissions"
-msgstr "Permissions de lire"
-
 msgid "Recipients:"
 msgstr "Destinataires :"
 
@@ -562,6 +571,9 @@
 msgid "Registry's content"
 msgstr "Contenu du registre"
 
+msgid "Relation types"
+msgstr "Types de relation"
+
 msgid "Relations"
 msgstr "Relations"
 
@@ -718,9 +730,6 @@
 msgid "Unreachable objects"
 msgstr "Objets inacessible"
 
-msgid "Update permissions"
-msgstr "Permissions de modifier"
-
 msgid "Used by:"
 msgstr "Utilisé par :"
 
@@ -1245,8 +1254,8 @@
 msgid "attribute"
 msgstr "attribut"
 
-msgid "attributes with modified permissions:"
-msgstr "attributs ayant des permissions modifiées :"
+msgid "attributes permissions:"
+msgstr ""
 
 msgid "august"
 msgstr "août"
@@ -1864,8 +1873,8 @@
 msgid "custom_workflow_object"
 msgstr "workflow de"
 
-msgid "cwetype-schema-image"
-msgstr "schéma"
+msgid "cwetype-box"
+msgstr "boîte"
 
 msgid "cwetype-schema-permissions"
 msgstr "permissions"
@@ -1873,6 +1882,9 @@
 msgid "cwetype-schema-text"
 msgstr "description"
 
+msgid "cwetype-views"
+msgstr "vues"
+
 msgid "cwetype-workflow"
 msgstr "workflow"
 
@@ -1903,6 +1915,9 @@
 msgid "default user workflow"
 msgstr "workflow par défaut des utilisateurs"
 
+msgid "default value"
+msgstr "valeur par défaut"
+
 msgid "default workflow for an entity type"
 msgstr "workflow par défaut pour un type d'entité"
 
@@ -2444,6 +2459,9 @@
 msgid "full text or RQL query"
 msgstr "texte à rechercher ou requête RQL"
 
+msgid "fulltext indexed"
+msgstr "indexation du texte"
+
 msgid "fulltext_container"
 msgstr "conteneur du texte indexé"
 
@@ -2545,6 +2563,18 @@
 msgid "i18n_login_popup"
 msgstr "s'authentifier"
 
+msgid "i18ncard_*"
+msgstr "0..n"
+
+msgid "i18ncard_+"
+msgstr "1..n"
+
+msgid "i18ncard_1"
+msgstr "1"
+
+msgid "i18ncard_?"
+msgstr "0..1"
+
 msgid "i18nprevnext_next"
 msgstr "suivant"
 
@@ -2618,9 +2648,6 @@
 msgid "incorrect value (%(value)s) for type \"%(type)s\""
 msgstr "valeur %(value)s incorrecte pour le type \"%(type)s\""
 
-msgid "index"
-msgstr "index"
-
 msgid "index this attribute's value in the plain text index"
 msgstr "indexer la valeur de cet attribut dans l'index plein texte"
 
@@ -2694,6 +2721,12 @@
 msgid "is"
 msgstr "de type"
 
+msgid "is object of:"
+msgstr "est object de"
+
+msgid "is subject of:"
+msgstr "est sujet de"
+
 msgid ""
 "is the subject/object entity of the relation composed of the other ? This "
 "implies that when the composite is deleted, composants are also deleted."
@@ -3041,8 +3074,8 @@
 msgid "object"
 msgstr "objet"
 
-msgid "object_plural:"
-msgstr "objets :"
+msgid "object type"
+msgstr "type de l'objet"
 
 msgid "october"
 msgstr "octobre"
@@ -3127,12 +3160,6 @@
 msgid "permissions"
 msgstr "permissions"
 
-msgid "permissions for entities"
-msgstr "permissions pour les entités"
-
-msgid "permissions for relations"
-msgstr "permissions pour les relations"
-
 msgid "permissions for this entity"
 msgstr "permissions pour cette entité"
 
@@ -3255,6 +3282,9 @@
 msgid "relation add"
 msgstr "ajout de relation"
 
+msgid "relation direction"
+msgstr "sens de la relation"
+
 msgid "relation removal"
 msgstr "suppression de relation"
 
@@ -3276,9 +3306,6 @@
 msgid "relation_type_object"
 msgstr "définition"
 
-msgid "relations"
-msgstr "relations"
-
 msgid "relations deleted"
 msgstr "relations supprimées"
 
@@ -3371,6 +3398,9 @@
 msgid "schema-image"
 msgstr "schéma"
 
+msgid "schema-security"
+msgstr "permissions"
+
 msgid "schema-text"
 msgstr "description"
 
@@ -3565,12 +3595,12 @@
 msgid "subject"
 msgstr "sujet"
 
+msgid "subject type"
+msgstr "type du sujet"
+
 msgid "subject/object cardinality"
 msgstr "cardinalité sujet/objet"
 
-msgid "subject_plural:"
-msgstr "sujets :"
-
 msgid "subworkflow"
 msgstr "sous-workflow"
 
@@ -4145,3 +4175,9 @@
 
 msgid "you should probably delete that property"
 msgstr "vous devriez probablement supprimer cette propriété"
+
+#~ msgid "Delete permissions"
+#~ msgstr "Permissions de supprimer"
+
+#~ msgid "attributes with modified permissions:"
+#~ msgstr "attributs ayant des permissions modifiées :"
--- a/schemaviewer.py	Wed Mar 24 15:31:37 2010 -0700
+++ b/schemaviewer.py	Thu Mar 25 08:30:53 2010 -0700
@@ -22,11 +22,8 @@
         self.req = req
         if req is not None:
             self.req.add_css('cubicweb.schema.css')
-            self._possible_views = req.vreg['views'].possible_views
             if not encoding:
                 encoding = req.encoding
-        else:
-            self._possible_views = lambda x: ()
         self.encoding = encoding
 
     def format_acls(self, schema, access_types):
@@ -98,11 +95,6 @@
     def rschema_link_url(self, rschema):
         return self.req.build_url('cwrtype/%s' % rschema)
 
-    def possible_views(self, etype):
-        rset = self.req.etype_rset(etype)
-        return [v for v in self._possible_views(self.req, rset)
-                if v.category != 'startupview']
-
     def stereotype(self, name):
         return Span((' <<%s>>' % name,), klass='stereotype')
 
@@ -113,9 +105,6 @@
         layout.append(Link(etype,'&#160;' , id=etype)) # anchor
         title = Link(self.eschema_link_url(eschema), etype)
         boxchild = [Section(children=(title, ' (%s)'% eschema.display_name(self.req)), klass='title')]
-        table = Table(cols=4, rheaders=1, klass='listing',
-                      children=self._entity_attributes_data(eschema))
-        boxchild.append(Section(children=(table,), klass='body'))
         data = []
         data.append(Section(children=boxchild, klass='box'))
         data.append(Section(children='', klass='vl'))
@@ -152,16 +141,6 @@
         data.append(Section(children=rels, klass='rels'))
         data.append(Section(children=t_vars, klass='vars'))
         layout.append(Section(children=data, klass='entityAttributes'))
-        if eschema.final: # stop here for final entities
-            return layout
-        _ = self.req._
-        if self.req.user.matching_groups('managers'):
-            # layout.append(self.format_acls(eschema, ('read', 'add', 'delete', 'update')))
-            # possible views for this entity type
-            views = [_(view.title) for view in self.possible_views(etype)]
-            layout.append(Section(children=(Table(cols=1, rheaders=1,
-                                                  children=[_('views')]+views),),
-                                  klass='views'))
         return layout
 
     def visit_relationschema(self, rschema, title=True):
--- a/server/test/unittest_rql2sql.py	Wed Mar 24 15:31:37 2010 -0700
+++ b/server/test/unittest_rql2sql.py	Thu Mar 25 08:30:53 2010 -0700
@@ -1209,6 +1209,10 @@
                     '''SELECT CAST(EXTRACT(MONTH from _P.cw_creation_date) AS INTEGER)
 FROM cw_Personne AS _P''')
 
+    def test_substring(self):
+        self._check("Any SUBSTRING(N, 1, 1) WHERE P nom N, P is Personne",
+                    '''SELECT SUBSTR(_P.cw_nom, 1, 1)
+FROM cw_Personne AS _P''')
 
     def test_parser_parse(self):
         for t in self._parse(PARSER):
@@ -1601,6 +1605,10 @@
 WHERE rel_concerne0.eid_from=_A.cw_eid AND rel_concerne0.eid_to=_N.cw_eid
 GROUP BY _A.cw_eid,rel_todo_by1.eid_to,rel_todo_by3.eid_to''')
 
+    def test_substring(self):
+        self._check("Any SUBSTRING(N, 1, 1) WHERE P nom N, P is Personne",
+                    '''SELECT SUBSTRING(_P.cw_nom, 1, 1)
+FROM cw_Personne AS _P''')
 
 class removeUnsusedSolutionsTC(TestCase):
     def test_invariant_not_varying(self):
--- a/web/data/cubicweb.schema.css	Wed Mar 24 15:31:37 2010 -0700
+++ b/web/data/cubicweb.schema.css	Thu Mar 25 08:30:53 2010 -0700
@@ -25,11 +25,14 @@
 div.acl{ 
   position: relative;
 /*  right: 20%;*/
-  float: right; 
-  width: 10%;
+  width: 25%;
   padding:0px 0px 0px 2em;
 }
 
+div.acl table tr,td{
+    padding: 2px 2px 2px 2px;
+}
+
 div.schema table {
   width : 100%;
 }
@@ -40,7 +43,6 @@
 }
 
 div.box div.title{
- border-bottom:1px solid black;
  padding:0.2em 0.2em;
  margin: 0 auto;
 }
@@ -67,7 +69,6 @@
 div.box{
  float:left;
  border:1px solid black;
- width:50%; 
 }
 
 div.vl{
--- a/web/views/schema.py	Wed Mar 24 15:31:37 2010 -0700
+++ b/web/views/schema.py	Thu Mar 25 08:30:53 2010 -0700
@@ -9,12 +9,13 @@
 
 from itertools import cycle
 
+from logilab.common.ureports import Section, Table
 from logilab.mtconverter import xml_escape
 from yams import BASE_TYPES, schema2dot as s2d
 from yams.buildobjs import DEFAULT_ATTRPERMS
 
 from cubicweb.selectors import (implements, yes, match_user_groups,
-                                has_related_entities)
+                                has_related_entities, anonymous_user)
 from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
                              WORKFLOW_TYPES, INTERNAL_TYPES)
 from cubicweb.schemaviewer import SchemaViewer
@@ -22,7 +23,7 @@
 from cubicweb import tags, uilib
 from cubicweb.web import action, facet, uicfg
 from cubicweb.web.views import TmpFileViewMixin
-from cubicweb.web.views import primary, baseviews, tabs, management
+from cubicweb.web.views import primary, baseviews, tabs, management, tableview
 
 ALWAYS_SKIP_TYPES = BASE_TYPES | SCHEMA_TYPES
 SKIP_TYPES  = (ALWAYS_SKIP_TYPES | META_RTYPES | SYSTEM_RTYPES | WORKFLOW_TYPES
@@ -189,21 +190,11 @@
             self.w(u'</div>')
 
 
-class SchemaUreportsView(StartupView):
-    __regid__ = 'schema-block'
-
-    def call(self):
-        viewer = SchemaViewer(self._cw)
-        layout = viewer.visit_schema(self._cw.vreg.schema, display_relations=True,
-                                     skiptypes=skip_types(self._cw))
-        self.w(uilib.ureport_as_html(layout))
-
-
 # CWAttribute / CWRelation #####################################################
 
 class CWRDEFPrimaryView(primary.PrimaryView):
     __select__ = implements('CWAttribute', 'CWRelation')
-    cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
+    cache_max_age = 60*60*2 # stawy in http cache for 2 hours by default
 
     def render_entity_title(self, entity):
         self.w(u'<h1><span class="etype">%s</span> %s</h1>'
@@ -211,6 +202,58 @@
                   xml_escape(entity.dc_long_title())))
 
 
+class CWAttributeConstraints(EntityView):
+    __regid__ = 'attr_constraints'
+    __select__ = implements('CWAttribute')
+
+    def cell_call(self, row, col):
+        entity = self.cw_rset.get_entity(row, col)
+        rschema = self._cw.vreg.schema.rschema(entity.rtype.name)
+        rdef = rschema.rdefs[(entity.stype.name, entity.otype.name)]
+        constraints = [xml_escape(str(c)) for c in getattr(rdef, 'constraints')]
+        self.w(u', '.join(constraints))
+
+
+class CWAttributeCellView(tableview.CellView):
+    """display attribute name only in a cell view, link to
+       cwattribute primary view"""
+    __select__ = tableview.CellView.__select__ & implements('CWAttribute')
+
+    def cell_call(self, row, col, cellvid=None):
+        """display attribute name only in a cell view, link to
+           cwattribute primary view"""
+        etype, val = self.cw_rset.description[row][col], self.cw_rset[row][col]
+        if val is not None and not self._cw.vreg.schema.eschema(etype).final:
+            e = self.cw_rset.get_entity(row, col)
+            if cellvid is not None and cellvid != 'incontext':
+                self.wview(cellvid, e.as_rset(), 'null')
+            else:
+                desc = uilib.cut(e.dc_description(), 50)
+                self.w(u'<a href="%s" title="%s">%s' % 
+                       (xml_escape(e.absolute_url()) ,xml_escape(desc),
+                        self.cell_content(e)))
+                self.w(u'</a>')
+        elif val is None:
+            # This is usually caused by a left outer join and in that case,
+            # regular views will most certainly fail if they don't have
+            # a real eid
+            self.wview('final', self.cw_rset, row=row, col=col)
+        else:
+            self.wview(cellvid or 'final', self.cw_rset, 'null', row=row, col=col)
+
+    def cell_content(self, entity):
+        return entity.relation_type[0].name
+
+
+class CWRelationCellView(CWAttributeCellView):
+    """display relation name and its translation only in a cell view, link to
+       cwrelation primary view"""
+    __select__ = tableview.CellView.__select__ & implements('CWRelation')
+
+    def cell_content(self, entity):
+        return u'%s (%s)' % (entity.relation_type[0].name,
+                             self._cw._(entity.relation_type[0].name))
+
 # CWEType ######################################################################
 
 class CWETypeOneLineView(baseviews.OneLineView):
@@ -226,99 +269,105 @@
             self.w(u'</em>')
 
 
-class CWETypePrimaryView(tabs.TabsMixin, primary.PrimaryView):
+class CWETypePrimaryView(tabs.TabbedPrimaryView):
     __select__ = implements('CWEType')
-    title = _('in memory entity schema')
-    main_related_section = False
-    tabs = [_('cwetype-schema-text'), _('cwetype-schema-image'),
-            _('cwetype-schema-permissions'), _('cwetype-workflow')]
-    default_tab = 'cwetype-schema-text'
-
-    def render_entity(self, entity):
-        self.render_entity_title(entity)
-        self.w(u'<div>%s</div>' % entity.description)
-        self.render_tabs(self.tabs, self.default_tab, entity)
+    tabs = [_('cwetype-text-tab'), _('cwetype-box-tab'), _('cwetype-workflow-tab'),
+            _('cwetype-views-tab'), _('cwetype-perm-tab')]
+    default_tab = 'cwetype-text-tab'
 
 
-class CWETypeSTextView(EntityView):
-    __regid__ = 'cwetype-schema-text'
-    __select__ = EntityView.__select__ & implements('CWEType')
+# register generated msgid
+_('i18ncard_1'), _('i18ncard_?'), _('i18ncard_+'), _('i18ncard_*')
+
+class CWETypeTextTab(tabs.PrimaryTab):
+    __regid__ = 'cwetype-text-tab'
+    __select__ = tabs.PrimaryTab.__select__ & implements('CWEType')
 
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
+    def render_entity_attributes(self, entity, siderelations=None):
+        self.w(u'<div>%s</div>' % xml_escape(entity.description or u''))
+        # entity schema image
+        url = entity.absolute_url(vid='schemagraph')
+        self.w(u'<img src="%s" alt="%s"/>' % (
+            xml_escape(url),
+            xml_escape(self._cw._('graphical schema for %s') % entity.name)))
+        # entity schema attributes
         self.w(u'<h2>%s</h2>' % _('Attributes'))
-        rset = self._cw.execute('Any N,F,D,I,J,DE,A '
+        rset = self._cw.execute('Any A,F,DE,D,C, I,J,A '
                                 'ORDERBY AA WHERE A is CWAttribute, '
                                 'A ordernum AA, A defaultval D, '
-                                'A description DE, '
+                                'A description DE, A cardinality C, '
                                 'A fulltextindexed I, A internationalizable J, '
                                 'A relation_type R, R name N, '
                                 'A to_entity O, O name F, '
                                 'A from_entity S, S eid %(x)s',
                                 {'x': entity.eid})
-        self.wview('editable-table', rset, 'null', displayfilter=True)
+        self.wview('table', rset, 'null',
+                   cellvids={4: 'attr_cardinality', 7: 'attr_constraints'},
+                   headers=(_(u'name'), _(u'type'), _(u'description'),
+                            _(u'default value'), _(u'required'),
+                            _(u'fulltext indexed'), _(u'internationalizable'),
+                            _(u'constraints')),
+                   mainindex=0)
+        # entity schema relations
         self.w(u'<h2>%s</h2>' % _('Relations'))
         rset = self._cw.execute(
-            'Any R,C,TT,K,D,A,RN,TTN ORDERBY RN '
+            'Any A, TT, "i18ncard_"+SUBSTRING(C, 1, 1),K,D,A,RN,TTN ORDERBY RN '
             'WHERE A is CWRelation, A description D, A composite K, '
             'A relation_type R, R name RN, A to_entity TT, TT name TTN, '
             'A cardinality C, A from_entity S, S eid %(x)s',
             {'x': entity.eid})
-        self.wview('editable-table', rset, 'null', displayfilter=True,
-                   displaycols=range(6), mainindex=5)
+        if rset:
+            self.w(u'<h5>%s %s</h5>' % (entity.name, _('is subject of:')))
+        self.wview('table', rset, 'null',
+                   cellvids={2: 'entity_relation_cardinality',},
+                   headers=(_(u'name'), _(u'object type'), _(u'cardinality'),
+                            _(u'composite'), _(u'description'),
+                            _(u'relation direction')),
+                   displaycols=range(5), mainindex=0)
+        self.w(u'<br/>')
         rset = self._cw.execute(
-            'Any R,C,TT,K,D,A,RN,TTN ORDERBY RN '
+            'Any A, TT, "i18ncard_"+SUBSTRING(C, 2, 1),K,D,A,RN,TTN ORDERBY RN '
             'WHERE A is CWRelation, A description D, A composite K, '
             'A relation_type R, R name RN, A from_entity TT, TT name TTN, '
             'A cardinality C, A to_entity O, O eid %(x)s',
             {'x': entity.eid})
-        self.wview('editable-table', rset, 'null', displayfilter=True,
-                   displaycols=range(6), mainindex=5)
+        if rset:
+            self.w(u'<h5>%s %s</h5>' % (entity.name, _('is object of:')))
+        self.wview('table', rset, 'null',
+                   cellvids={2: 'entity_relation_cardinality',},
+                   headers=(_(u'name'), _(u'subject type'), _(u'cardinality'),
+                            _(u'composite'), _(u'description'),
+                            _(u'relation direction')),
+                   displaycols=range(5), mainindex=0)
 
 
-class CWETypeSImageView(EntityView):
-    __regid__ = 'cwetype-schema-image'
-    __select__ = EntityView.__select__ & implements('CWEType')
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        url = entity.absolute_url(vid='schemagraph')
-        self.w(u'<img src="%s" alt="%s"/>' % (
-            xml_escape(url),
-            xml_escape(self._cw._('graphical schema for %s') % entity.name)))
-
-
-class CWETypeSPermView(EntityView):
-    __regid__ = 'cwetype-schema-permissions'
-    __select__ = EntityView.__select__ & implements('CWEType')
+class CWETypePermTab(EntityView, management.SecurityViewMixIn):
+    __regid__ = 'cwetype-perm-tab'
+    __select__ = EntityView.__select__ & implements('CWEType') & ~anonymous_user()
 
     def cell_call(self, row, col):
+        self._cw.add_css('cubicweb.acl.css')
         entity = self.cw_rset.get_entity(row, col)
-        _ = self._cw._
-        self.w(u'<h2>%s</h2>' % _('Add permissions'))
-        rset = self._cw.execute('Any P WHERE X add_permission P, '
-                                'X eid %(x)s',
-                                {'x': entity.eid})
-        self.wview('outofcontext', rset, 'null')
-        self.w(u'<h2>%s</h2>' % _('Read permissions'))
-        rset = self._cw.execute('Any P WHERE X read_permission P, '
-                                'X eid %(x)s',
-                                {'x': entity.eid})
-        self.wview('outofcontext', rset, 'null')
-        self.w(u'<h2>%s</h2>' % _('Update permissions'))
-        rset = self._cw.execute('Any P WHERE X update_permission P, '
-                                'X eid %(x)s',
-                                {'x': entity.eid})
-        self.wview('outofcontext', rset, 'null')
-        self.w(u'<h2>%s</h2>' % _('Delete permissions'))
-        rset = self._cw.execute('Any P WHERE X delete_permission P, '
-                                'X eid %(x)s',
-                                {'x': entity.eid})
-        self.wview('outofcontext', rset, 'null')
+        eschema = self._cw.vreg.schema.eschema(entity.name)
+        self.w(u'<a id="%s" href="cwetype/%s">' %  (eschema.type, eschema.type))
+        self.w(u'<h3 class="schema">%s (%s) ' % (eschema.type, _(eschema.type)))
+        self.w(u'</h3></a>')
+        self.w(u'<div style="margin: 0px 1.5em">')
+        self.schema_definition(eschema)
+        # display entity attributes only if they have some permissions modified
+        modified_attrs = []
+        self.w(u'<h4>%s</h4>' % _('attributes permissions:').capitalize())
+        for attr, etype in  eschema.attribute_definitions():
+            if attr not in META_RTYPES:
+                rdef = eschema.rdef(attr)
+                attrtype = str(rdef.rtype)
+                self.w(u'<h4 class="schema">%s (%s)</h4> ' % (attrtype, _(attrtype)))
+                self.schema_definition(rdef, link=False)
+        self.w(u'</div>')
 
 
-class CWETypeSWorkflowView(EntityView):
-    __regid__ = 'cwetype-workflow'
+class CWETypeWorkflowTab(EntityView):
+    __regid__ = 'cwetype-workflow-tab'
     __select__ = (EntityView.__select__ & implements('CWEType') &
                   has_related_entities('workflow_of', 'object'))
 
@@ -347,6 +396,37 @@
             wf.absolute_url(), self._cw._('more info about this workflow')))
 
 
+class CWETypeBoxTab(EntityView):
+    __regid__ = 'cwetype-box-tab'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        viewer = SchemaViewer(self._cw)
+        entity = self.cw_rset.get_entity(row, col)
+        eschema = self._cw.vreg.schema.eschema(entity.name)
+        layout = viewer.visit_entityschema(eschema)
+        self.w(uilib.ureport_as_html(layout))
+        self.w(u'<br class="clear"/>')
+
+
+class CWETypeViewsTab(EntityView):
+    __regid__ = 'cwetype-views-tab'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        entity = self.cw_rset.get_entity(row, col)
+        etype = entity.name
+        _ = self._cw._
+        # possible views for this entity type
+        views = [(_(view.title),) for view in self.possible_views(etype)]
+        self.wview('pyvaltable', pyvalue=views, headers=(_(u'views'),))
+
+    def possible_views(self, etype):
+        rset = self._cw.etype_rset(etype)
+        return [v for v in self._cw.vreg['views'].possible_views(self._cw, rset)
+                if v.category != 'startupview']
+
+
 # CWRType ######################################################################
 
 class CWRTypeSchemaView(primary.PrimaryView):
@@ -365,7 +445,6 @@
             self.w(tags.img(src=entity.absolute_url(vid='schemagraph'),
                             alt=msg))
 
-
 # schema images ###############################################################
 
 class RestrictedSchemaVisitorMixIn(object):
@@ -430,6 +509,25 @@
         s2d.schema2dot(outputfile=tmpfile, visitor=visitor)
 
 
+# final views #################################################################
+
+class CardinalityRequiredCellView(baseviews.FinalView):
+    __regid__ = 'attr_cardinality'
+
+    def cell_call(self, row, col):
+        value = self.cw_rset.rows[row][col]
+        if value is not None and value[0] == '1':
+            self.w(self._cw._(u'required'))
+
+class I18NCardinalityCellView(baseviews.FinalView):
+    __regid__ = 'entity_relation_cardinality'
+
+    def cell_call(self, row, col):
+        value = self.cw_rset.rows[row][col]
+        if value is not None:
+            self.w(self._cw._(value))
+
+
 # misc: facets, actions ########################################################
 
 class CWFinalFacet(facet.AttributeFacet):