merge
authorKatia Saurfelt <katia.saurfelt@logilab.fr>
Thu, 30 Apr 2009 14:55:08 +0200
changeset 1615 63c086a01772
parent 1614 d9d265df05f8 (diff)
parent 1600 5c68c50ca08f (current diff)
child 1617 ac8a4ce6a830
merge
i18n/es.po
--- a/i18n/en.po	Thu Apr 30 12:33:14 2009 +0200
+++ b/i18n/en.po	Thu Apr 30 14:55:08 2009 +0200
@@ -118,6 +118,10 @@
 msgid "%s software version of the database"
 msgstr ""
 
+#, python-format
+msgid "%s_perm"
+msgstr ""
+
 msgid "**"
 msgstr "0..n 0..n"
 
@@ -196,12 +200,6 @@
 msgid "Bytes_plural"
 msgstr "Bytes"
 
-msgid "Card"
-msgstr "Card"
-
-msgid "Card_plural"
-msgstr "Cards"
-
 msgid "Date"
 msgstr "Date"
 
@@ -332,9 +330,6 @@
 msgid "New Bookmark"
 msgstr "New bookmark"
 
-msgid "New Card"
-msgstr "New card"
-
 msgid "New ECache"
 msgstr ""
 
@@ -471,9 +466,6 @@
 msgid "This Bookmark"
 msgstr "This bookmark"
 
-msgid "This Card"
-msgstr "This card"
-
 msgid "This ECache"
 msgstr ""
 
@@ -596,11 +588,6 @@
 msgstr ""
 
 msgid ""
-"a card is a textual content used as documentation, reference, procedure "
-"reminder"
-msgstr ""
-
-msgid ""
 "a simple cache entity characterized by a name and a validity date. The "
 "target application is responsible for updating timestamp when necessary to "
 "invalidate the cache (typically in hooks). Also, checkout the AppRsetObject."
@@ -820,9 +807,6 @@
 msgid "add a Bookmark"
 msgstr "add a bookmark"
 
-msgid "add a Card"
-msgstr "add a card"
-
 msgid "add a ECache"
 msgstr ""
 
@@ -928,9 +912,6 @@
 msgid "am/pm calendar (year)"
 msgstr ""
 
-msgid "an abstract for this card"
-msgstr ""
-
 msgid "an electronic mail address associated to a short alias"
 msgstr ""
 
@@ -968,6 +949,9 @@
 msgid "attribute"
 msgstr ""
 
+msgid "attributes with modified permissions:"
+msgstr ""
+
 msgid "august"
 msgstr ""
 
@@ -1131,6 +1115,9 @@
 msgid "click on the box to cancel the deletion"
 msgstr ""
 
+msgid "close all"
+msgstr ""
+
 msgid "comment"
 msgstr ""
 
@@ -1236,12 +1223,6 @@
 msgid "constraints applying on this relation"
 msgstr ""
 
-msgid "content"
-msgstr ""
-
-msgid "content_format"
-msgstr "content format"
-
 msgid "contentnavigation"
 msgstr "contextual components"
 
@@ -1827,7 +1808,7 @@
 msgstr ""
 
 msgid "hide meta-data"
-msgstr ""
+msgstr "hide meta entities and relations"
 
 msgid "home"
 msgstr ""
@@ -1945,9 +1926,6 @@
 msgid "inlined"
 msgstr ""
 
-msgid "inlined view"
-msgstr ""
-
 msgid "internationalizable"
 msgstr ""
 
@@ -2168,6 +2146,18 @@
 msgid "navigation"
 msgstr ""
 
+msgid "navigation.combobox-limit"
+msgstr "\"related\" combo-box"
+
+msgid "navigation.page-size"
+msgstr "number of results"
+
+msgid "navigation.related-limit"
+msgstr "number of entities in the primary view "
+
+msgid "navigation.short-line-size"
+msgstr "short description"
+
 msgid "navtop"
 msgstr "page top"
 
@@ -2220,6 +2210,9 @@
 msgid "object"
 msgstr ""
 
+msgid "object_plural:"
+msgstr "objects:"
+
 msgid "october"
 msgstr ""
 
@@ -2235,6 +2228,9 @@
 msgid "only select queries are authorized"
 msgstr ""
 
+msgid "open all"
+msgstr ""
+
 msgid "order"
 msgstr ""
 
@@ -2278,6 +2274,12 @@
 msgid "permission"
 msgstr ""
 
+msgid "permissions for entities"
+msgstr ""
+
+msgid "permissions for relations"
+msgstr ""
+
 msgid "permissions for this entity"
 msgstr ""
 
@@ -2290,9 +2292,6 @@
 msgid "pkey"
 msgstr "key"
 
-msgid "planned_delivery"
-msgstr "planned delivery"
-
 msgid "please correct errors below"
 msgstr ""
 
@@ -2348,6 +2347,9 @@
 msgid "relation_type_object"
 msgstr "relation definitions"
 
+msgid "relations"
+msgstr ""
+
 msgid "relations deleted"
 msgstr ""
 
@@ -2357,9 +2359,6 @@
 msgid "remove this Bookmark"
 msgstr "remove this bookmark"
 
-msgid "remove this Card"
-msgstr "remove this card"
-
 msgid "remove this ECache"
 msgstr ""
 
@@ -2543,7 +2542,7 @@
 msgstr ""
 
 msgid "show meta-data"
-msgstr ""
+msgstr "show the complete schema"
 
 msgid "site configuration"
 msgstr ""
@@ -2597,6 +2596,9 @@
 msgid "subject/object cardinality"
 msgstr ""
 
+msgid "subject_plural:"
+msgstr "subjects:"
+
 msgid "sunday"
 msgstr ""
 
@@ -2606,9 +2608,6 @@
 msgid "symetric"
 msgstr ""
 
-msgid "synopsis"
-msgstr ""
-
 msgid "system entities"
 msgstr ""
 
@@ -2709,6 +2708,27 @@
 msgid "ui"
 msgstr ""
 
+msgid "ui.date-format"
+msgstr "date format"
+
+msgid "ui.datetime-format"
+msgstr "date and time format"
+
+msgid "ui.default-text-format"
+msgstr "text format"
+
+msgid "ui.fckeditor"
+msgstr "content editor"
+
+msgid "ui.float-format"
+msgstr "float format"
+
+msgid "ui.language"
+msgstr "language"
+
+msgid "ui.time-format"
+msgstr "time format"
+
 msgid "unaccessible"
 msgstr ""
 
@@ -2724,6 +2744,9 @@
 msgid "unknown property key"
 msgstr ""
 
+msgid "up"
+msgstr ""
+
 msgid "upassword"
 msgstr "password"
 
@@ -2850,9 +2873,6 @@
 "which is the preferred form."
 msgstr ""
 
-msgid "wikiid"
-msgstr "wiki identifier"
-
 #, python-format
 msgid "workflow for %s"
 msgstr ""
@@ -2871,3 +2891,30 @@
 
 msgid "you have been logged out"
 msgstr ""
+
+#~ msgid "Card"
+#~ msgstr "Card"
+
+#~ msgid "Card_plural"
+#~ msgstr "Cards"
+
+#~ msgid "New Card"
+#~ msgstr "New card"
+
+#~ msgid "This Card"
+#~ msgstr "This card"
+
+#~ msgid "add a Card"
+#~ msgstr "add a card"
+
+#~ msgid "content_format"
+#~ msgstr "content format"
+
+#~ msgid "planned_delivery"
+#~ msgstr "planned delivery"
+
+#~ msgid "remove this Card"
+#~ msgstr "remove this card"
+
+#~ msgid "wikiid"
+#~ msgstr "wiki identifier"
--- a/i18n/fr.po	Thu Apr 30 12:33:14 2009 +0200
+++ b/i18n/fr.po	Thu Apr 30 14:55:08 2009 +0200
@@ -123,6 +123,10 @@
 msgid "%s software version of the database"
 msgstr "version logicielle de la base pour %s"
 
+#, python-format
+msgid "%s_perm"
+msgstr ""
+
 msgid "**"
 msgstr "0..n 0..n"
 
@@ -201,12 +205,6 @@
 msgid "Bytes_plural"
 msgstr "Données binaires"
 
-msgid "Card"
-msgstr "Fiche"
-
-msgid "Card_plural"
-msgstr "Fiches"
-
 msgid "Date"
 msgstr "Date"
 
@@ -337,9 +335,6 @@
 msgid "New Bookmark"
 msgstr "Nouveau signet"
 
-msgid "New Card"
-msgstr "Nouvelle fiche"
-
 msgid "New ECache"
 msgstr "Nouveau cache applicatif"
 
@@ -476,9 +471,6 @@
 msgid "This Bookmark"
 msgstr "Ce signet"
 
-msgid "This Card"
-msgstr "Cette fiche"
-
 msgid "This ECache"
 msgstr "Ce cache applicatif"
 
@@ -617,13 +609,6 @@
 "transition et l'utilisateur courant."
 
 msgid ""
-"a card is a textual content used as documentation, reference, procedure "
-"reminder"
-msgstr ""
-"une fiche est un texte utilisé comme documentation, référence, rappel de "
-"procédure..."
-
-msgid ""
 "a simple cache entity characterized by a name and a validity date. The "
 "target application is responsible for updating timestamp when necessary to "
 "invalidate the cache (typically in hooks). Also, checkout the AppRsetObject."
@@ -843,9 +828,6 @@
 msgid "add a Bookmark"
 msgstr "ajouter un signet"
 
-msgid "add a Card"
-msgstr "ajouter une fiche"
-
 msgid "add a ECache"
 msgstr "ajouter un cache applicatif"
 
@@ -953,9 +935,6 @@
 msgid "am/pm calendar (year)"
 msgstr "calendrier am/pm (année)"
 
-msgid "an abstract for this card"
-msgstr "un résumé pour cette fiche"
-
 msgid "an electronic mail address associated to a short alias"
 msgstr "une addresse électronique associée à un alias"
 
@@ -995,6 +974,9 @@
 msgid "attribute"
 msgstr "attribut"
 
+msgid "attributes with modified permissions:"
+msgstr "attributs ayant des permissions modifiées :"
+
 msgid "august"
 msgstr "août"
 
@@ -1161,6 +1143,9 @@
 msgid "click on the box to cancel the deletion"
 msgstr "cliquer dans la zone d'édition pour annuler la suppression"
 
+msgid "close all"
+msgstr "tout fermer"
+
 msgid "comment"
 msgstr "commentaire"
 
@@ -1269,12 +1254,6 @@
 msgid "constraints applying on this relation"
 msgstr "contraintes s'appliquant à cette relation"
 
-msgid "content"
-msgstr "contenu"
-
-msgid "content_format"
-msgstr "format"
-
 msgid "contentnavigation"
 msgstr "composants contextuels"
 
@@ -1904,7 +1883,7 @@
 msgstr "cacher le filtre"
 
 msgid "hide meta-data"
-msgstr "cacher les méta-données"
+msgstr "cacher les entités et relations \"méta\""
 
 msgid "home"
 msgstr "maison"
@@ -2031,9 +2010,6 @@
 msgid "inlined"
 msgstr "mise en ligne"
 
-msgid "inlined view"
-msgstr "vue embarquée (en ligne)"
-
 msgid "internationalizable"
 msgstr "internationalisable"
 
@@ -2264,6 +2240,18 @@
 msgid "navigation"
 msgstr "navigation"
 
+msgid "navigation.combobox-limit"
+msgstr "nombre d'entités dans les listes déroulantes"
+
+msgid "navigation.page-size"
+msgstr "nombre de résultats"
+
+msgid "navigation.related-limit"
+msgstr "nombre d'entités dans la vue primaire"
+
+msgid "navigation.short-line-size"
+msgstr "description courtes"
+
 msgid "navtop"
 msgstr "haut de page du contenu principal"
 
@@ -2316,6 +2304,9 @@
 msgid "object"
 msgstr "objet"
 
+msgid "object_plural:"
+msgstr "objets :"
+
 msgid "october"
 msgstr "octobre"
 
@@ -2331,6 +2322,9 @@
 msgid "only select queries are authorized"
 msgstr "seules les requêtes de sélections sont autorisées"
 
+msgid "open all"
+msgstr "tout ouvrir"
+
 msgid "order"
 msgstr "ordre"
 
@@ -2375,6 +2369,12 @@
 msgid "permission"
 msgstr "permission"
 
+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é"
 
@@ -2387,9 +2387,6 @@
 msgid "pkey"
 msgstr "clé"
 
-msgid "planned_delivery"
-msgstr "livraison prévue"
-
 msgid "please correct errors below"
 msgstr "veuillez corriger les erreurs ci-dessous"
 
@@ -2445,6 +2442,9 @@
 msgid "relation_type_object"
 msgstr "définition"
 
+msgid "relations"
+msgstr ""
+
 msgid "relations deleted"
 msgstr "relations supprimées"
 
@@ -2454,9 +2454,6 @@
 msgid "remove this Bookmark"
 msgstr "supprimer ce signet"
 
-msgid "remove this Card"
-msgstr "supprimer cette fiche"
-
 msgid "remove this ECache"
 msgstr "supprimer ce cache applicatif"
 
@@ -2652,7 +2649,7 @@
 msgstr "afficher le filtre"
 
 msgid "show meta-data"
-msgstr "afficher les méta-données"
+msgstr "afficher le schéma complet"
 
 msgid "site configuration"
 msgstr "configuration du site"
@@ -2706,6 +2703,9 @@
 msgid "subject/object cardinality"
 msgstr "cardinalité sujet/objet"
 
+msgid "subject_plural:"
+msgstr "sujets :"
+
 msgid "sunday"
 msgstr "dimanche"
 
@@ -2715,9 +2715,6 @@
 msgid "symetric"
 msgstr "symétrique"
 
-msgid "synopsis"
-msgstr "synopsis"
-
 msgid "system entities"
 msgstr "entités systèmes"
 
@@ -2819,6 +2816,27 @@
 msgid "ui"
 msgstr "propriétés génériques de l'interface"
 
+msgid "ui.date-format"
+msgstr "format de date"
+
+msgid "ui.datetime-format"
+msgstr "format de date et de l'heure"
+
+msgid "ui.default-text-format"
+msgstr "format de texte"
+
+msgid "ui.fckeditor"
+msgstr "éditeur"
+
+msgid "ui.float-format"
+msgstr "format des flottants"
+
+msgid "ui.language"
+msgstr "langue"
+
+msgid "ui.time-format"
+msgstr "format de l'heure"
+
 msgid "unaccessible"
 msgstr "inaccessible"
 
@@ -2834,6 +2852,9 @@
 msgid "unknown property key"
 msgstr "clé de propriété inconnue"
 
+msgid "up"
+msgstr ""
+
 msgid "upassword"
 msgstr "mot de passe"
 
@@ -2971,9 +2992,6 @@
 "org et python-projects@lists.logilab.org), mettez cette propriété à vrai sur "
 "l'une d'entre-elle qui sera la forme canonique"
 
-msgid "wikiid"
-msgstr "identifiant wiki"
-
 #, python-format
 msgid "workflow for %s"
 msgstr "workflow pour %s"
@@ -3002,12 +3020,37 @@
 #~ msgid "%s, or without time: %s"
 #~ msgstr "%s, ou bien sans préciser d'heure: %s"
 
+#~ msgid "Card"
+#~ msgstr "Fiche"
+
+#~ msgid "Card_plural"
+#~ msgstr "Fiches"
+
 #~ msgid "Loading"
 #~ msgstr "chargement"
 
+#~ msgid "New Card"
+#~ msgstr "Nouvelle fiche"
+
 #~ msgid "Problem occured while setting new value"
 #~ msgstr "Un problème est survenu lors de la mise à jour"
 
+#~ msgid "This Card"
+#~ msgstr "Cette fiche"
+
+#~ msgid ""
+#~ "a card is a textual content used as documentation, reference, procedure "
+#~ "reminder"
+#~ msgstr ""
+#~ "une fiche est un texte utilisé comme documentation, référence, rappel de "
+#~ "procédure..."
+
+#~ msgid "add a Card"
+#~ msgstr "ajouter une fiche"
+
+#~ msgid "an abstract for this card"
+#~ msgstr "un résumé pour cette fiche"
+
 #~ msgid "and"
 #~ msgstr "et"
 
@@ -3017,6 +3060,12 @@
 #~ msgid "cancel edition"
 #~ msgstr "annuler l'édition"
 
+#~ msgid "content"
+#~ msgstr "contenu"
+
+#~ msgid "content_format"
+#~ msgstr "format"
+
 #~ msgid ""
 #~ "default language (look at the i18n directory of the application to see "
 #~ "available languages)"
@@ -3042,6 +3091,9 @@
 #~ msgid "incorrect value for type \"%s\""
 #~ msgstr "valeur incorrecte pour le type \"%s\""
 
+#~ msgid "inlined view"
+#~ msgstr "vue embarquée (en ligne)"
+
 #~ msgid "linked"
 #~ msgstr "lié"
 
@@ -3056,11 +3108,23 @@
 #~ msgid "owned by"
 #~ msgstr "appartient à"
 
+#~ msgid "planned_delivery"
+#~ msgstr "livraison prévue"
+
+#~ msgid "remove this Card"
+#~ msgstr "supprimer cette fiche"
+
 #~ msgid "see also"
 #~ msgstr "voir aussi"
 
 #~ msgid "status will change from %s to %s"
 #~ msgstr "l'état va passer de %s à %s"
 
+#~ msgid "synopsis"
+#~ msgstr "synopsis"
+
+#~ msgid "wikiid"
+#~ msgstr "identifiant wiki"
+
 #~ msgid "workflow history"
 #~ msgstr "historique du workflow"
--- a/schemaviewer.py	Thu Apr 30 12:33:14 2009 +0200
+++ b/schemaviewer.py	Thu Apr 30 14:55:08 2009 +0200
@@ -158,7 +158,7 @@
             return layout
         _ = self.req._
         if self.req.user.matching_groups('managers'):
-            layout.append(self.format_acls(eschema, ('read', 'add', 'delete', 'update')))
+            # 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,
--- a/server/sources/rql2sql.py	Thu Apr 30 12:33:14 2009 +0200
+++ b/server/sources/rql2sql.py	Thu Apr 30 14:55:08 2009 +0200
@@ -952,6 +952,8 @@
             if rel is not None:
                 rel._q_needcast = value
             return self.keyword_map[value]()
+        if constant.type == 'Boolean':
+            value = self.dbms_helper.boolean_value(value)
         if constant.type == 'Substitute':
             _id = constant.value
             if isinstance(_id, unicode):
--- a/web/data/cubicweb.acl.css	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/data/cubicweb.acl.css	Thu Apr 30 14:55:08 2009 +0200
@@ -9,19 +9,90 @@
 /* security edition form (views/management.py)                                */
 /******************************************************************************/
 
+h2.schema{
+ background : #ff7700;
+ color: #fff;
+ font-weight: bold;
+ padding : 0.1em 0.3em;
+}
+
+
+h3.schema{ 
+ font-weight: bold;
+}
+
+h4 a,
+h4 a:link,
+h4 a:visited{ 
+ color:#000;
+ }
+
 table.schemaInfo {
-  margin: 1ex 1em;
+  margin: 1em 0em;
   text-align: left;
   border: 1px solid black;
   border-collapse: collapse;
+  width:100%;
 }
 
 table.schemaInfo th,
 table.schemaInfo td {
-  padding: 0em 1em;
-  border: 1px solid black;
+  padding: .3em .5em;
+  border: 1px solid grey;
+  width:33%; 
+}
+
+
+table.schemaInfo tr th {   
+ padding: 0.2em 0px 0.2em 5px;
+ background-image:none;
+ background-color:#dfdfdf;
+}
+
+table.schemaInfo thead tr {
+  border: 1px solid #dfdfdf;
+} 
+
+table.schemaInfo td {
+  padding: 3px 10px 3px 5px; 
+
 }
 
+.users{ 
+ color : #00CC33;
+ font-weight: bold }
+
+.guests{ 
+ color :  #ff7700;
+ font-weight: bold;
+}
+
+.staff{  
+ color : #0083ab;
+ font-weight: bold;
+}
+
+.owners{ 
+ color : #8b0000;
+ font-weight: bold;
+}
+
+.discret,
+a.grey{ 
+ color:#666;
+}
+
+a.grey:hover{ 
+ color:#000;
+}
+
+.red{ 
+ color :  #ff7700;
+ }
+
+div#schema_security{ 
+ width:780px;
+ }
 /******************************************************************************/
 /* user groups edition form (views/euser.py)                                  */
 /******************************************************************************/
--- a/web/data/cubicweb.preferences.css	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/data/cubicweb.preferences.css	Thu Apr 30 14:55:08 2009 +0200
@@ -5,12 +5,46 @@
  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
  */
 
-.componentTitle{
+
+table.preferences td{ 
+ padding: 0 0.5em 1em;
+ }
+
+fieldset.preferences{  
+ border : 1px solid #CFCEB7;
+ margin:1em 0;
+ padding:0 1em 1em;
+}
+
+div.preffield {
+ margin-bottom: 0.8em ;
+}
+
+/*
+div.preffield label{ 
+ font-size:110%
+ }
+*/
+
+div.prefinput{ 
+ margin:.3em 0;
+}
+
+div.componentLink{ 
+ margin-top:0.3em;
+ }
+
+a.componentTitle{
  font-weight:bold;
- color: #ff7700;
- padding:0px 4px;
+ color: #000;
+ }
+
+a.componentTitle:visited{
+ color: #000;
 }
 
+
+
 h2.propertiesform a{
  display:block;
  margin: 10px 0px 6px 0px;
@@ -26,3 +60,56 @@
  background-color:#cfceb7;
  text-decoration:none;
 }
+
+div.prefinput select.changed,
+div.prefinput input.changed{ 
+ background:#eeedd9;
+ border: 1px solid #eeedd9;
+}
+
+div.prefinput select,
+div.prefinput input{ 
+ background:#fff;
+ border: 1px solid #CFCEB7;
+}
+
+.prefinput input.error {
+ background:transparent url(error.png) no-repeat scroll 100% 50% !important;
+}
+
+
+div.formsg{ 
+ font-weight:bold;
+ margin:0.5em 0px;
+ }
+
+
+div.formsg .critical{ 
+ color:red;
+ padding-left:20px;
+ background:#fff url(critical.png) no-repeat;
+ }
+
+div.formsg .message{ 
+ color : green;
+}
+
+.helper{
+  font-size: 96%;
+  color: #555544;
+  padding:0; 
+}
+
+div.prefinput .helper:hover {
+  color: #000;
+  cursor: default;
+}
+
+.error{ 
+ color:red;
+ padding-right:1em;
+ }
+
+div.openlink{ 
+ display:inline;
+ }
\ No newline at end of file
--- a/web/data/cubicweb.preferences.js	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/data/cubicweb.preferences.js	Thu Apr 30 14:55:08 2009 +0200
@@ -3,8 +3,177 @@
  * XXX whenever used outside of preferences, don't forget to
  *     move me in a more appropriate place
  */
-function toggle_and_remember_visibility(elemId, cookiename) {
+
+function toggleVisibility(elemId) {
+    _clearPreviousMessages();
     jqNode(elemId).toggleClass('hidden');
-    async_remote_exec('set_cookie', cookiename,
-                      jQuery('#' + elemId).attr('class'));
+}
+
+function closeFieldset(fieldsetid){
+    var linklabel = _('open all');
+    var linkhref = 'javascript:openFieldset("' +fieldsetid + '")'
+    _toggleFieldset(fieldsetid, 1, linklabel, linkhref)
+}
+
+function openFieldset(fieldsetid){
+    var linklabel = _('close all');
+    var linkhref = 'javascript:closeFieldset("'+ fieldsetid + '")'
+    _toggleFieldset(fieldsetid, 0, linklabel, linkhref)
+}
+
+
+function _toggleFieldset(fieldsetid, closeaction, linklabel, linkhref){
+    jQuery('#'+fieldsetid).find('div.openlink').each(function(){
+	    var link = A({'href' : "javascript:noop();",
+			  'onclick' : linkhref},
+			  linklabel)
+	    jQuery(this).empty().append(link);
+	});
+    jQuery('#'+fieldsetid).find('fieldset[id]').each(function(){
+	    var fieldset = jQuery(this);
+	    if(closeaction){
+		fieldset.addClass('hidden')
+	    }else{
+		fieldset.removeClass('hidden');
+		linkLabel = (_('open all'));
+	    }
+	});
+ 
+}
+
+function validatePrefsForm(formid){
+    var form = getNode(formid);
+    freezeFormButtons(formid);
+    try {
+	var d = _sendForm(formid, null);
+    } catch (ex) {
+	log('got exception', ex);
+	return false;
+    }
+    function _callback(result, req) {
+	_clearPreviousMessages();
+	_clearPreviousErrors(formid);
+	// success
+	if(result[0]){
+	    return submitSucces(formid)
+	}
+ 	// Failures
+	unfreezeFormButtons(formid);
+	var descr = result[1];
+        if (!isArrayLike(descr) || descr.length != 2) {
+	   log('got strange error :', descr);
+	   updateMessage(descr);
+	   return ;
+	}
+        _displayValidationerrors(formid, descr[0], descr[1]);
+	var dom = DIV({'class':'critical'},
+		      _("please correct errors below"));
+	jQuery(form).find('div.formsg').empty().append(dom);
+	updateMessage(_(""));
+	return false;
+    }
+    d.addCallback(_callback);
+    return false;
+}
+
+function submitSucces(formid){
+    var form = jQuery('#'+formid);
+    setCurrentValues(form);
+    var dom = DIV({'class':'message'},
+		  _("changes applied"));
+    jQuery(form).find('div.formsg').empty().append(dom);
+    jQuery(form).find('input').removeClass('changed');
+    checkValues(form, true);
+    return;
+}
+
+function _clearPreviousMessages() {
+    jQuery('div#appMsg').addClass('hidden');
+    jQuery('div.formsg').empty();
 }
+
+function _clearPreviousErrors(formid) {
+    jQuery('#' + formid + ' span.error').remove();
+}
+
+
+function checkValues(form, success){
+    var unfreezeButtons = false;
+    jQuery(form).find('select').each(function () { 
+	    unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+	});
+    jQuery(form).find('[type=text]').each(function () {
+	    unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+	});
+    jQuery(form).find('input[type=radio]').each(function () { 
+	    if (jQuery(this).attr('checked')){
+		unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+	    }
+     }); 
+   
+    if (unfreezeButtons){
+	unfreezeFormButtons(form.attr('id'));
+    }else{
+	if (!success){
+	    _clearPreviousMessages();
+	}
+	_clearPreviousErrors(form.attr('id'));
+	freezeFormButtons(form.attr('id'));
+    }
+}
+
+function _checkValue(input, unfreezeButtons){
+     var currentValueInput = jQuery("input[id=current-" + input.attr('name') + "]");
+     if (currentValueInput.attr('value') != input.attr('value')){
+	 input.addClass('changed');
+	 unfreezeButtons = true;
+     }else{
+	 input.removeClass('changed');
+	 jQuery("span[id=err-" + input.attr('id') + "]").remove();
+     }	
+     input.removeClass('error');
+     return unfreezeButtons
+}
+
+
+function setCurrentValues(form){
+    jQuery(form).find('input[id^=current-value]').each(function () { 
+	    var currentValueInput = jQuery(this);
+	    var name = currentValueInput.attr('id').split('-')[1];
+	    jQuery(form).find("[name=" + name + "]").each(function (){
+		    var input = jQuery(this);
+		    if(input.attr('type')=='radio'){
+			log(input.attr('name'));
+			if(input.attr('checked')){
+			    log(input.attr('value'));
+			    currentValueInput.attr('value', input.attr('value'));
+			    log(currentValueInput.attr('value').toString());
+			}
+		    }else{
+			currentValueInput.attr('value', input.attr('value'));
+		    }
+		});
+    });
+}
+
+
+function initEvents(){
+  jQuery('form').each(function() { 
+	  var form = jQuery(this);
+	  freezeFormButtons(form.attr('id'));
+	  form.find('input[type=text]').keyup(function(){  
+		  checkValues(form);	   
+          });
+	  form.find('input[type=radio]').change(function(){  
+		  checkValues(form);	   
+          });
+	  form.find('select').change(function(){  
+		  checkValues(form);	 
+          });
+    });
+}
+
+$(document).ready(function() {
+	initEvents();
+});
+
--- a/web/data/external_resources	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/data/external_resources	Thu Apr 30 14:55:08 2009 +0200
@@ -52,3 +52,4 @@
 DOWNLOAD_ICON = DATADIR/download.gif
 UPLOAD_ICON = DATADIR/upload.gif
 GMARKER_ICON = DATADIR/gmap_blue_marker.png
+UP_ICON = DATADIR/up.gif
Binary file web/data/up.gif has changed
--- a/web/views/management.py	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/views/management.py	Thu Apr 30 14:55:08 2009 +0200
@@ -13,14 +13,14 @@
 
 from cubicweb.common.utils import UStringIO
 from cubicweb.common.view import AnyRsetView, StartupView, EntityView
-from cubicweb.common.uilib import html_traceback, rest_traceback
+from cubicweb.common.uilib import html_traceback, rest_traceback, ajax_replace_url
 from cubicweb.common.selectors import (yes, one_line_rset,
                                        accept_rset, none_rset,
-                                       chainfirst, chainall)
+				       match_user_group,
+                                       chainfirst, chainall, )
 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
 from cubicweb.web.widgets import StaticComboBoxWidget
 from cubicweb.web.form import FormMixIn
-
 _ = unicode
 
 def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
@@ -36,8 +36,47 @@
         w(u'<input type="hidden" name="__message" value="%s"/>\n'
           % html_escape(msg))
 
+class SecurityViewMixIn(object):
+    """display security information for a given schema """
+    def schema_definition(self, eschema, link=True,  access_types=None):
+        w = self.w
+        _ = self.req._
+        if not access_types:
+            access_types = eschema.ACTIONS
+        w(u'<table class="schemaInfo">')
+        w(u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>' % ( 
+            _("permission"), _('granted to groups'), _('rql expressions')))
+        for access_type in access_types:
+            w(u'<tr>')
+            w(u'<td>%s</td>' % _('%s_perm' % access_type))
+            groups = eschema.get_groups(access_type)
+            l = []
+            groups = [(_(group), group) for group in groups]
+            for trad, group in sorted(groups):
+                if link:
+                    l.append(u'<a href="%s" class="%s">%s</a><br/>' % (
+                    self.build_url('egroup/%s' % group), group, trad))
+                else:
+                    l.append(u'<div class="%s">%s</div>' % (group, trad))
+            w(u'<td>%s</td>' % u''.join(l))
+            rqlexprs = eschema.get_rqlexprs(access_type)
+            w(u'<td>%s</td>' % u'<br/><br/>'.join(expr.expression for expr in rqlexprs))
+            w(u'</tr>\n')
+        w(u'</table>')
 
-class SecurityManagementView(EntityView):
+    def has_schema_modified_permissions(self, eschema, access_types):
+        """ return True if eschema's actual permissions are diffrents
+        from the default ones
+        """
+        for access_type in access_types:
+            if eschema.get_rqlexprs(access_type):
+                return True
+            if eschema.get_groups(access_type) != \
+                    frozenset(eschema.get_default_groups()[access_type]):
+                return True
+        return False
+
+class SecurityManagementView(EntityView, SecurityViewMixIn):
     """display security information for a given entity"""
     id = 'security'
     title = _('security')
@@ -54,7 +93,7 @@
              html_escape(entity.dc_title())))
         # first show permissions defined by the schema
         self.w('<h2>%s</h2>' % _('schema\'s permissions definitions'))
-        self.schema_definition(entity)
+        self.schema_definition(entity.e_schema)
         self.w('<h2>%s</h2>' % _('manage security'))
         # ownership information
         if self.schema.rschema('owned_by').has_perm(self.req, 'add',
@@ -70,26 +109,6 @@
             if reqpermschema.has_perm(self.req, 'add', fromeid=entity.eid):
                 self.require_permission_edit_form(entity)
 
-    def schema_definition(self, entity):
-        w = self.w
-        _ = self.req._
-        w(u'<table class="schemaInfo">')
-        w(u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>' % (
-            _("access type"), _('granted to groups'), _('rql expressions')))
-        for access_type in ('read', 'add', 'update', 'delete'):
-            w(u'<tr>')
-            w(u'<th>%s</th>' % self.req.__('%s_permission' % access_type))
-            groups = entity.e_schema.get_groups(access_type)
-            l = []
-            for group in groups:
-                l.append(u'<a href="%s">%s</a>' % (
-                    self.build_url('egroup/%s' % group), _(group)))
-            w(u'<td>%s</td>' % u', '.join(l))
-            rqlexprs = entity.e_schema.get_rqlexprs(access_type)
-            w(u'<td>%s</td>' % u'<br/>'.join(expr.expression for expr in rqlexprs))
-            w(u'</tr>\n')
-        w(u'</table>')
-
     def owned_by_edit_form(self, entity):
         self.w('<h3>%s</h3>' % self.req._('ownership'))
         begin_form(self.w, entity, 'security', msg= _('ownerships have been changed'))
@@ -286,15 +305,28 @@
 _('contentnavigation')
 
 
-def make_togglable_link(nodeid, label, cookiename):
+def make_togglable_link(nodeid, label):
     """builds a HTML link that switches the visibility & remembers it"""
-    action = u"javascript: toggle_and_remember_visibility('%s', '%s')" % \
-        (nodeid, cookiename)
+    action = u"javascript: toggleVisibility('%s')" % nodeid
     return u'<a href="%s">%s</a>' % (action, label)
 
 def css_class(someclass):
     return someclass and 'class="%s"' % someclass or ''
 
+### translations for SystemEpropertiesForm
+_('navigation.combobox-limit')
+_('navigation.page-size')
+_('navigation.related-limit')
+_('navigation.short-line-size')
+_('ui.date-format')
+_('ui.datetime-format')
+_('ui.default-text-format')
+_('ui.fckeditor')
+_('ui.float-format')
+_('ui.language')
+_('ui.time-format')
+_('open all')
+
 class SystemEpropertiesForm(FormMixIn, StartupView):
     controller = 'edit'
     id = 'systemepropertiesform'
@@ -326,7 +358,7 @@
 
     def call(self, **kwargs):
         """The default view representing the application's index"""
-        self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js'))
+        self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js', 'cubicweb.ajax.js'))
         self.req.add_css('cubicweb.preferences.css')
         vreg = self.vreg
         values = self.defined_keys
@@ -344,10 +376,11 @@
                 mainopts.setdefault(parts[0], []).append(key)
         # precompute form to consume error message
         for group, keys in mainopts.items():
-            mainopts[group] = self.form(keys, False)
+            mainopts[group] = self.form(group, keys, False)
+
         for group, objects in groupedopts.items():
             for oid, keys in objects.items():
-                groupedopts[group][oid] = self.form(keys, True)
+                groupedopts[group][oid] = self.form(group + '-' + oid, keys, True)
 
         w = self.w
         req = self.req
@@ -358,28 +391,35 @@
                                          for g, f in mainopts.iteritems()):
             status = css_class(self._group_status(group)) #'hidden' (collapsed), or '' (open) ?
             w(u'<h2 class="propertiesform">%s</h2>\n' %
-              (make_togglable_link('fieldset_' + group, label,
-                                   self._cookie_name(group))))
+            (make_togglable_link('fieldset_' + group, label.capitalize())))
             w(u'<div id="fieldset_%s" %s>' % (group, status))
-            w(u'<fieldset class="subentity">')
+            w(u'<fieldset class="preferences">')
             w(form)
             w(u'</fieldset></div>')
+
         for label, group, objects in sorted((_(g), g, o)
                                             for g, o in groupedopts.iteritems()):
             status = css_class(self._group_status(group))
             w(u'<h2 class="propertiesform">%s</h2>\n' %
-              (make_togglable_link('fieldset_' + group, label,
-                                   self._cookie_name(group))))
+              (make_togglable_link('fieldset_' + group, label.capitalize())))
             w(u'<div id="fieldset_%s" %s>' % (group, status))
-            for label, oid, form in sorted((self.req.__('%s_%s' % (group, o)), o, f)
-                                           for o, f in objects.iteritems()):
-                w(u'<fieldset class="subentity">')
-                w(u'<legend class="componentTitle">%s</legend>\n' % label)
+	    
+	    # create selection
+	    sorted_objects =  sorted((self.req.__('%s_%s' % (group, o)), o, f)
+                                           for o, f in objects.iteritems())
+	    for label, oid, form in sorted_objects:
+                w(u'''<div class="componentLink"><a href="javascript:noop();" onclick="javascript:toggleVisibility('field_%(oid)s_%(group)s')" class="componentTitle">%(label)s</a>''' % {'label':label, 'oid':oid, 'group':group})
+                w(u''' (<div class="openlink"><a href="javascript:noop();" onclick="javascript:closeFieldset('fieldset_%(group)s')">%(label)s</a></div>)'''
+                  % {'label':_('close all'), 'group':group})
+                w(u'</div>')
                 docmsgid = '%s_%s_description' % (group, oid)
                 doc = _(docmsgid)
                 if doc != docmsgid:
-                    w(u'<p class="description">%s</p>' % html_escape(doc))
-                w(form)
+                    w(u'<p class="helper">%s</p>' % html_escape(doc).capitalize())
+		    
+		w(u'<fieldset id="field_%(oid)s_%(group)s" class="%(group)s preferences">'
+                  % {'oid':oid, 'group':group})
+		w(form)
                 w(u'</fieldset>')
             w(u'</div>')
 
@@ -405,11 +445,12 @@
             entity['value'] = self.vreg.property_value(key)
         return entity
 
-    def form(self, keys, splitlabel=False):
+    def form(self, formid, keys, splitlabel=False):
         stream = UStringIO()
         w = stream.write
-        w(u'<form action="%s" method="post">\n' % self.build_url())
+	w(u'''<form action="%(url)s" id="%(formid)s" method="post" onsubmit="return validatePrefsForm('%(formid)s')" >\n''' % {'url' : self.build_url(), 'formid':formid})
         w(u'<fieldset>\n')
+	w(u'<div class="formsg"></div>')
         w(u'<input type="hidden" name="__errorurl" value="%s"/>\n'
           % html_escape(self.req.url()))
         w(u'<input type="hidden" name="__form_id" value="%s"/>\n' % self.id)
@@ -419,41 +460,37 @@
             w(u'<input type="hidden" name="__redirectparams" value="%s"/>\n'
               % html_escape(params))
         w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % path)
-        #w(u'<input type="hidden" name="__redirectrql" value=""/>\n')
+        w(u'<input type="hidden" name="__redirectrql" value=""/>\n')
         w(u'<input type="hidden" name="__message" value="%s"/>\n'
           % self.req._('changes applied'))
-        w(u'<table><tr><td>\n')
-
-        w(u'<table>\n')
-        for key in keys:
-            w(u'<tr>\n')
+	for key in keys:
             self.form_row(w, key, splitlabel)
-            w(u'</tr>\n')
-        w(u'</table>\n')
-        w(u'</td></tr><tr><td>\n')
         w(self.button_ok())
-        w(self.button_cancel())
-        w(u'</td></tr></table>\n')
         w(u'</fieldset>\n')
         w(u'</form>\n')
         return stream.getvalue()
-
+     
     def form_row(self, w, key, splitlabel):
-        entity = self.entity_for_key(key)
+	entity = self.entity_for_key(key)
         eid = entity.eid
-        if splitlabel:
-            w(u'<td class="label">%s</td>' % self.req._(key.split('.')[-1]))
+	if splitlabel:
+            w(u'<label>%s</label>' % self.req._(key.split('.')[-1]).capitalize())
         else:
-            w(u'<td class="label">%s</td>' % self.req._(key))
+            w(u'<label>%s</label>' % self.req._(key).capitalize())
+ 
         wdg = self.vreg.property_value_widget(key, req=self.req)
         error = wdg.render_error(entity)
-        w(u'<td class="%s">' % (error and 'error' or ''))
-        w(error)
+	w(u'<div class="preffield">\n')
+        w(u'%s' % wdg.render_help(entity))
+        w(u'<div class="prefinput">')
+        w(u'<span class="%s">%s</span>' % (error and 'error' or '', error))
         self.form_row_hiddens(w, entity, key)
-        w(wdg.edit_render(entity))
-        w(u'</td>\n')
-        w(u'<td>%s</td>' % wdg.render_help(entity))
-        return entity
+	w(wdg.edit_render(entity))
+        w(u'<input type="hidden" id="current-value:%(eid)s" value="%(value)s"/>'
+          % {'eid':entity.eid, 'value':wdg.current_display_value(entity)})
+	w(u'</div>')
+	w(u'</div>')
+	return entity
 
     def form_row_hiddens(self, w, entity, key):
         eid = entity.eid
@@ -462,13 +499,13 @@
         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('pkey', eid), key))
         w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('edits-pkey', eid), ''))
 
-
+        
 class EpropertiesForm(SystemEpropertiesForm):
     id = 'epropertiesform'
     title = _('preferences')
-    require_groups = ('users', 'managers') # we don't want guests to be able to come here
-    __selectors__ = chainfirst(none_rset,
-                               chainall(one_line_rset, accept_rset)),
+    require_groups = ('users',) # we don't want guests to be able to come here
+    __selectors__ = chainfirst(none_rset, 
+                               chainall( match_user_group, one_line_rset, accept_rset)),
     accepts = ('EUser',)
 
     @classmethod
@@ -493,19 +530,27 @@
     def eprops_rset(self):
         return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V,'
                                 'P for_user U, U eid %(x)s', {'x': self.user.eid})
+#     def form_row(self, w, key, splitlabel):
+# 	print 'user'
+
+class ManagerEpropertiesForm(EpropertiesForm):
+    title = _('preferences')
+    require_groups = ('managers',) 
+
 
     def form_row_hiddens(self, w, entity, key):
-        super(EpropertiesForm, self).form_row_hiddens(w, entity, key)
+        super(ManagerEpropertiesForm, self).form_row_hiddens(w, entity, key)
         # if user is in the managers group and the property is being created,
         # we have to set for_user explicitly
-        if not entity.has_eid() and self.user.matching_groups('managers'):
+        if not entity.has_eid():
             eid = entity.eid
             w(u'<input type="hidden" name="%s" value="%s"/>'
               % (eid_param('edits-for_user', eid), INTERNAL_FIELD_VALUE))
             w(u'<input type="hidden" name="%s" value="%s"/>'
               % (eid_param('for_user', eid), self.user.eid))
 
-
+#     def form_row(self, w, key, splitlabel):
+# 	print 'manager'
 
 
 class ProcessInformationView(StartupView):
--- a/web/views/startup.py	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/views/startup.py	Thu Apr 30 14:55:08 2009 +0200
@@ -11,8 +11,10 @@
 
 from cubicweb.common.uilib import ureport_as_html, unormalize, ajax_replace_url
 from cubicweb.common.view import StartupView
+from cubicweb.common.selectors import match_user_group
 from cubicweb.web.httpcache import EtagHTTPCacheManager
-
+from cubicweb.web.views.management import SecurityViewMixIn
+from copy import deepcopy
 _ = unicode
 
 
@@ -158,25 +160,134 @@
     def call(self):
         """display schema information"""
         self.req.add_js('cubicweb.ajax.js')
-        self.req.add_css('cubicweb.schema.css')
+        self.req.add_css(('cubicweb.schema.css','cubicweb.acl.css'))
         withmeta = int(self.req.form.get('withmeta', 0))
+        section = self.req.form.get('sec', '')
         self.w(u'<img src="%s" alt="%s"/>\n' % (
             html_escape(self.req.build_url('view', vid='schemagraph', withmeta=withmeta)),
             self.req._("graphical representation of the application'schema")))
         if withmeta:
             self.w(u'<div><a href="%s">%s</a></div>' % (
-                self.build_url('schema', withmeta=0),
+                html_escape(self.build_url('schema', withmeta=0, sec=section)),
                 self.req._('hide meta-data')))
         else:
             self.w(u'<div><a href="%s">%s</a></div>' % (
-                self.build_url('schema', withmeta=1),
+                html_escape(self.build_url('schema', withmeta=1, sec=section)),
                 self.req._('show meta-data')))
-        self.w(u'<div id="detailed_schema"><a href="%s">%s</a></div>' %
+        self.w(u'<a href="%s">%s</a><br/>' %
                (html_escape(ajax_replace_url('detailed_schema', '', 'schematext',
                                              skipmeta=int(not withmeta))),
                 self.req._('detailed schema view')))
+        if self.req.user.matching_groups('managers'):
+            self.w(u'<a href="%s">%s</a>' %
+                   (html_escape(ajax_replace_url('detailed_schema', '', 'schema_security',
+                                                 skipmeta=int(not withmeta))),
+                self.req._('security')))
+        self.w(u'<div id="detailed_schema">')
+        if section:
+            self.wview(section, None)
+        self.w(u'</div>')
+
+    
+class ManagerSchemaPermissionsView(StartupView, SecurityViewMixIn):
+    id = 'schema_security'
+    require_groups = ('managers',)
+
+    def call(self, display_relations=True,
+             skiprels=('is', 'is_instance_of', 'identity', 'owned_by', 'created_by')):
+        _ = self.req._
+        formparams = {}
+        formparams['sec'] = self.id
+        formparams['withmeta'] = int(self.req.form.get('withmeta', True))
+        schema = self.schema
+        # compute entities
+        entities = [eschema for eschema in schema.entities()
+                   if not eschema.is_final()]
+        if not formparams['withmeta']:
+            entities = [eschema for eschema in entities
+                        if not eschema.meta]
+        # compute relations
+        relations = []    
+        if display_relations:
+            relations = [rschema for rschema in schema.relations()
+                         if not (rschema.is_final() or rschema.type in skiprels)]
+            if not formparams['withmeta']:
+                relations = [rschema for rschema in relations
+                             if not rschema.meta]
+        # index
+        self.w(u'<div id="schema_security"><a id="index" href="index"/>')
+        self.w(u'<h2 class="schema">%s</h2>' % _('index').capitalize())
+        self.w(u'<h4>%s</h4>' %   _('Entities').capitalize())
+        ents = []
+        for eschema in sorted(entities):
+            url = html_escape(self.build_url('schema', **formparams) + '#' + eschema.type)
+            ents.append(u'<a class="grey" href="%s">%s</a> (%s)' % (url,  eschema.type, _(eschema.type)))
+        self.w('%s' %  ', '.join(ents))
+        self.w(u'<h4>%s</h4>' % (_('relations').capitalize()))
+        rels = []
+        for eschema in sorted(relations):
+            url = html_escape(self.build_url('schema', **formparams) + '#' + eschema.type)
+            rels.append(u'<a class="grey" href="%s">%s</a> (%s), ' %  (url , eschema.type, _(eschema.type)))
+        self.w('%s' %  ', '.join(ents))
+        # entities
+        self.display_entities(entities, formparams)
+        # relations
+        if relations:
+            self.display_relations(relations, formparams)
+        self.w(u'</div>')
+
+    def display_entities(self, entities, formparams):
+        _ = self.req._
+        self.w(u'<a id="entities" href="entities"/>')
+        self.w(u'<h2 class="schema">%s</h2>' % _('permissions for entities').capitalize())
+        for eschema in sorted(entities):
+            self.w(u'<a id="%s" href="%s"/>' %  (eschema.type, eschema.type))
+            self.w(u'<h3 class="schema">%s (%s) ' % (eschema.type, _(eschema.type)))
+            url = html_escape(self.build_url('schema', **formparams) + '#index')
+            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
+            self.w(u'</h3>')
+            self.w(u'<div style="margin: 0px 1.5em">')
+            self.schema_definition(eschema, link=False)
+
+            # display entity attributes only if they have some permissions modified
+            modified_attrs = []
+            for attr, etype in  eschema.attribute_definitions():
+                if self.has_schema_modified_permissions(attr, attr.ACTIONS):
+                    modified_attrs.append(attr)
+            if  modified_attrs:
+                self.w(u'<h4>%s</h4>' % _('attributes with modified permissions:').capitalize())
+                self.w(u'</div>')
+                self.w(u'<div style="margin: 0px 6em">')
+                for attr in  modified_attrs:
+                    self.w(u'<h4 class="schema">%s (%s)</h4> ' % (attr.type, _(attr.type)))
+                    self.schema_definition(attr, link=False)
+                self.w(u'</div>')
+            else:
+                self.w(u'</div>')
 
 
+    def display_relations(self, relations, formparams):
+        _ = self.req._
+        self.w(u'<a id="relations" href="relations"/>')
+        self.w(u'<h2 class="schema">%s </h2>' % _('permissions for relations').capitalize())
+        for rschema in sorted(relations):
+            self.w(u'<a id="%s" href="%s"/>' %  (rschema.type, rschema.type))
+            self.w(u'<h3 class="schema">%s (%s) ' % (rschema.type, _(rschema.type)))
+            url = html_escape(self.build_url('schema', **formparams) + '#index')
+            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
+            self.w(u'</h3>')
+            self.w(u'<div style="margin: 0px 1.5em">')
+            subjects = [str(subj) for subj in rschema.subjects()]
+            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (_('subject_plural:'),
+                                                ', '.join( [str(subj) for subj in rschema.subjects()]),
+                                                ', '.join( [_(str(subj)) for subj in rschema.subjects()])))
+            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (_('object_plural:'),
+                                                ', '.join( [str(obj) for obj in rschema.objects()]),
+                                                ', '.join( [_(str(obj)) for obj in rschema.objects()])))
+            self.schema_definition(rschema, link=False)
+            self.w(u'</div>')
+
+                
 class SchemaUreportsView(StartupView):
     id = 'schematext'
 
--- a/web/widgets.py	Thu Apr 30 12:33:14 2009 +0200
+++ b/web/widgets.py	Thu Apr 30 14:55:08 2009 +0200
@@ -145,14 +145,15 @@
     def render_help(self, entity):
         """render a help message about the (edited) field"""
         req = entity.req
-        help = [u'<br/>']
+        help = [u'<div class="helper">']
         descr = self.description or self.rschema.rproperty(self.subjtype, self.objtype, 'description')
         if descr:
-            help.append(u'<span class="helper">%s</span>' % req._(descr))
+            help.append(u'<span>%s</span>' % req._(descr))
         example = self.render_example(req)
         if example:
-            help.append(u'<span class="helper">(%s: %s)</span>'
+            help.append(u'<span>(%s: %s)</span>'
                         % (req._('sample format'), example))
+	help.append(u'</div>')
         return u'&nbsp;'.join(help)
     
     def render_example(self, req):
@@ -755,14 +756,15 @@
     def render_help(self, entity):
         """calendar popup widget"""
         req = entity.req
-        help = [ u'<br/>' ]
+        help = [ u'<div class="helper">' ]
         descr = self.rschema.rproperty(self.subjtype, self.objtype, 'description')
         if descr:
-            help.append('<span class="helper">%s</span>' % req._(descr))
+            help.append('<span>%s</span>' % req._(descr))
         example = self.render_example(req)
         if example:
-            help.append('<span class="helper">(%s: %s)</span>'
+            help.append('<span>(%s: %s)</span>'
                         % (req._('sample format'), example))
+	help.append(u'</div>')
         return u'&nbsp;'.join(help)
 
     def render_calendar_popup(self, entity):