|
1 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
3 # |
|
4 # This file is part of CubicWeb. |
|
5 # |
|
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
|
7 # terms of the GNU Lesser General Public License as published by the Free |
|
8 # Software Foundation, either version 2.1 of the License, or (at your option) |
|
9 # any later version. |
|
10 # |
|
11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
|
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
|
14 # details. |
|
15 # |
|
16 # You should have received a copy of the GNU Lesser General Public License along |
|
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
|
18 """This module contains the default index page and management view. |
|
19 |
|
20 .. autoclass:: IndexView |
|
21 .. autoclass:: ManageView |
|
22 """ |
|
23 |
|
24 __docformat__ = "restructuredtext en" |
|
25 from cubicweb import _ |
|
26 |
|
27 from logilab.common.textutils import unormalize |
|
28 from logilab.common.deprecation import deprecated |
|
29 from logilab.mtconverter import xml_escape |
|
30 |
|
31 from cubicweb.view import StartupView |
|
32 from cubicweb.predicates import match_user_groups, is_instance |
|
33 from cubicweb.schema import display_name |
|
34 from cubicweb.web import httpcache |
|
35 from cubicweb.web.views import uicfg |
|
36 |
|
37 class ManageView(StartupView): |
|
38 """:__regid__: *manage* |
|
39 |
|
40 The manage view, display some information about what's contained by your |
|
41 site and provides access to administration stuff such as user and groups |
|
42 management. |
|
43 |
|
44 Regarding the section displaying link to entity type, notice by default it |
|
45 won't display entity types which are related to another one using a |
|
46 mandatory (cardinality == 1) composite relation. |
|
47 |
|
48 You can still configure that behaviour manually using the |
|
49 `indexview_etype_section` as explained in :mod:`cubicweb.web.uicfg`. |
|
50 """ |
|
51 __regid__ = 'manage' |
|
52 title = _('manage') |
|
53 http_cache_manager = httpcache.EtagHTTPCacheManager |
|
54 add_etype_links = () |
|
55 skip_startup_views = set( ('index', 'manage', 'schema', 'owl', |
|
56 'systempropertiesform', 'propertiesform', |
|
57 'loggedout', 'login', |
|
58 'cw.users-and-groups-management', 'cw.groups-management', |
|
59 'cw.users-management', 'cw.sources-management', |
|
60 'siteinfo', 'info', 'registry', 'gc', |
|
61 'tree') ) |
|
62 |
|
63 def call(self, **kwargs): |
|
64 """The default view representing the instance's management""" |
|
65 self._cw.add_css('cubicweb.manageview.css') |
|
66 self.w(u'<h1>%s</h1>' % self._cw.property_value('ui.site-title')) |
|
67 self.entities() |
|
68 self.manage_actions() |
|
69 self.startup_views() |
|
70 |
|
71 def manage_actions(self): |
|
72 allactions = self._cw.vreg['actions'].possible_actions(self._cw) |
|
73 if allactions.get('manage'): |
|
74 self.w(u'<div class="hr"> </div>') |
|
75 self.w(u'<h2>%s</h2>\n' % self._cw._('Manage')) |
|
76 self.w(u'<ul class="manageActions">') |
|
77 for action in allactions['manage']: |
|
78 self.w(u'<li><a href="%s">%s</a></li>' % ( |
|
79 action.url(), self._cw._(action.title))) |
|
80 self.w(u'</ul>') |
|
81 |
|
82 def startup_views(self): |
|
83 views = [v for v in self._cw.vreg['views'].possible_views(self._cw, None) |
|
84 if v.category == 'startupview' |
|
85 and v.__regid__ not in self.skip_startup_views] |
|
86 if not views: |
|
87 return |
|
88 self.w(u'<div class="hr"> </div>') |
|
89 self.w(u'<h2>%s</h2>\n' % self._cw._('Startup views')) |
|
90 self.w(u'<ul class="startup">') |
|
91 for v in sorted(views, key=lambda x: self._cw._(x.title)): |
|
92 self.w('<li><a href="%s">%s</a></li>' % ( |
|
93 xml_escape(v.url()), xml_escape(self._cw._(v.title).capitalize()))) |
|
94 self.w(u'</ul>') |
|
95 |
|
96 def entities(self): |
|
97 schema = self._cw.vreg.schema |
|
98 eschemas = [eschema for eschema in schema.entities() |
|
99 if uicfg.indexview_etype_section.get(eschema) == 'application'] |
|
100 if eschemas: |
|
101 self.w(u'<div class="hr"> </div>') |
|
102 self.w(u'<h2>%s</h2>\n' % self._cw._('Browse by entity type')) |
|
103 self.w(u'<table class="startup">') |
|
104 self.entity_types_table(eschemas) |
|
105 self.w(u'</table>') |
|
106 |
|
107 def entity_types_table(self, eschemas): |
|
108 infos = sorted(self.entity_types(eschemas), |
|
109 key=lambda t: unormalize(t[0])) |
|
110 q, r = divmod(len(infos), 2) |
|
111 if r: |
|
112 infos.append( (None, ' ', ' ') ) |
|
113 infos = zip(infos[:q+r], infos[q+r:]) |
|
114 for (_, etypelink, addlink), (_, etypelink2, addlink2) in infos: |
|
115 self.w(u'<tr>\n') |
|
116 self.w(u'<td class="addcol">%s</td><td>%s</td>\n' % (addlink, etypelink)) |
|
117 self.w(u'<td class="addcol">%s</td><td>%s</td>\n' % (addlink2, etypelink2)) |
|
118 self.w(u'</tr>\n') |
|
119 |
|
120 def entity_types(self, eschemas): |
|
121 """return an iterator on formatted links to get a list of entities of |
|
122 each entity types |
|
123 """ |
|
124 req = self._cw |
|
125 for eschema in eschemas: |
|
126 if eschema.final or not eschema.may_have_permission('read', req): |
|
127 continue |
|
128 etype = eschema.type |
|
129 nb = req.execute('Any COUNT(X) WHERE X is %s' % etype)[0][0] |
|
130 if nb > 1: |
|
131 label = display_name(req, etype, 'plural') |
|
132 else: |
|
133 label = display_name(req, etype) |
|
134 nb = req.execute('Any COUNT(X) WHERE X is %s' % etype)[0][0] |
|
135 url = self._cw.build_url(etype) |
|
136 etypelink = u' <a href="%s">%s</a> (%d)' % ( |
|
137 xml_escape(url), label, nb) |
|
138 if eschema.has_perm(req, 'add'): |
|
139 yield (label, etypelink, self.add_entity_link(etype)) |
|
140 else: |
|
141 yield (label, etypelink, u'') |
|
142 |
|
143 def create_links(self): |
|
144 self.w(u'<ul class="createLink">') |
|
145 for etype in self.add_etype_links: |
|
146 eschema = self._cw.vreg.schema.eschema(etype) |
|
147 if eschema.has_perm(self._cw, 'add'): |
|
148 url = self._cw.vreg["etypes"].etype_class(etype).cw_create_url(self._cw) |
|
149 self.w(u'<li><a href="%s">%s</a></li>' % ( |
|
150 url, self._cw.__('New %s' % eschema).capitalize())) |
|
151 self.w(u'</ul>') |
|
152 |
|
153 def add_entity_link(self, etype): |
|
154 """creates a [+] link for adding an entity""" |
|
155 url = self._cw.vreg["etypes"].etype_class(etype).cw_create_url(self._cw) |
|
156 return u'[<a href="%s" title="%s">+</a>]' % ( |
|
157 xml_escape(url), self._cw.__('New %s' % etype)) |
|
158 |
|
159 |
|
160 |
|
161 class IndexView(ManageView): |
|
162 """:__regid__: *index* |
|
163 |
|
164 The default index view, that you'll get when accessing your site's root url. |
|
165 It's by default indentical to the |
|
166 :class:`~cubicweb.web.views.startup.ManageView`, but you'll usually want to |
|
167 customize this one. |
|
168 """ |
|
169 __regid__ = 'index' |
|
170 title = _('view_index') |
|
171 |
|
172 @deprecated('[3.11] display_folders method is deprecated, backport it if needed') |
|
173 def display_folders(self): |
|
174 return 'Folder' in self._cw.vreg.schema and self._cw.execute('Any COUNT(X) WHERE X is Folder')[0][0] |