26 from cubicweb import _ |
26 from cubicweb import _ |
27 from cubicweb.web import component |
27 from cubicweb.web import component |
28 from cubicweb.web.views import error |
28 from cubicweb.web.views import error |
29 from cubicweb.predicates import anonymous_user |
29 from cubicweb.predicates import anonymous_user |
30 |
30 |
|
31 |
31 class FourOhFour(error.FourOhFour): |
32 class FourOhFour(error.FourOhFour): |
32 __select__ = error.FourOhFour.__select__ & anonymous_user() |
33 __select__ = error.FourOhFour.__select__ & anonymous_user() |
33 |
34 |
34 def call(self): |
35 def call(self): |
35 self.w(u"<h1>%s</h1>" % self._cw._('this resource does not exist')) |
36 self.w(u"<h1>%s</h1>" % self._cw._('this resource does not exist')) |
36 self.w(u"<p>%s</p>" % self._cw._('have you tried to login?')) |
37 self.w(u"<p>%s</p>" % self._cw._('have you tried to login?')) |
37 |
38 |
38 |
39 |
39 class LoginBox(component.CtxComponent): |
40 class LoginBox(component.CtxComponent): |
40 """display a box containing links to all startup views""" |
41 """display a box containing links to all startup views""" |
41 __regid__ = 'sytweb.loginbox' |
42 __regid__ = 'sytweb.loginbox' |
42 __select__ = component.CtxComponent.__select__ & anonymous_user() |
43 __select__ = component.CtxComponent.__select__ & anonymous_user() |
43 |
44 |
44 title = _('Authenticate yourself') |
45 title = _('Authenticate yourself') |
45 order = 70 |
46 order = 70 |
46 |
47 |
47 def render_body(self, w): |
48 def render_body(self, w): |
48 cw = self._cw |
49 cw = self._cw |
49 form = cw.vreg['forms'].select('logform', cw) |
50 form = cw.vreg['forms'].select('logform', cw) |
50 form.render(w=w, table_class='', display_progress_div=False) |
51 form.render(w=w, table_class='', display_progress_div=False) |
51 |
52 |
52 The first class provides a new specific implementation of the default page you |
53 The first class provides a new specific implementation of the default page you |
53 get on 404 error, to display an adapted message to anonymous user. |
54 get on 404 error, to display an adapted message to anonymous user. |
54 |
55 |
55 .. Note:: |
56 .. Note:: |
84 |
85 |
85 .. sourcecode:: python |
86 .. sourcecode:: python |
86 |
87 |
87 from cubicweb.web.views import startup |
88 from cubicweb.web.views import startup |
88 |
89 |
|
90 |
89 class IndexView(startup.IndexView): |
91 class IndexView(startup.IndexView): |
90 def call(self, **kwargs): |
92 def call(self, **kwargs): |
91 self.w(u'<div>\n') |
93 self.w(u'<div>\n') |
92 if self._cw.cnx.session.anonymous_session: |
94 if self._cw.cnx.session.anonymous_session: |
93 self.w(u'<h4>%s</h4>\n' % self._cw._('Public Albums')) |
95 self.w(u'<h4>%s</h4>\n' % self._cw._('Public Albums')) |
94 else: |
96 else: |
95 self.w(u'<h4>%s</h4>\n' % self._cw._('Albums for %s') % self._cw.user.login) |
97 self.w(u'<h4>%s</h4>\n' % self._cw._('Albums for %s') % self._cw.user.login) |
96 self._cw.vreg['views'].select('tree', self._cw).render(w=self.w) |
98 self._cw.vreg['views'].select('tree', self._cw).render(w=self.w) |
97 self.w(u'</div>\n') |
99 self.w(u'</div>\n') |
|
100 |
98 |
101 |
99 def registration_callback(vreg): |
102 def registration_callback(vreg): |
100 vreg.register_all(globals().values(), __name__, (IndexView,)) |
103 vreg.register_all(globals().values(), __name__, (IndexView,)) |
101 vreg.register_and_replace(IndexView, startup.IndexView) |
104 vreg.register_and_replace(IndexView, startup.IndexView) |
102 |
105 |
103 As you can see, we override the default index view found in |
106 As you can see, we override the default index view found in |
104 `cubicweb.web.views.startup`, geting back nothing but its identifier and selector |
107 `cubicweb.web.views.startup`, geting back nothing but its identifier and selector |
105 since we override the top level view's `call` method. |
108 since we override the top level view's `call` method. |
106 |
109 |
147 we can see: |
150 we can see: |
148 |
151 |
149 .. sourcecode:: python |
152 .. sourcecode:: python |
150 |
153 |
151 class File(AnyEntity): |
154 class File(AnyEntity): |
152 """customized class for File entities""" |
155 """customized class for File entities""" |
153 __regid__ = 'File' |
156 __regid__ = 'File' |
154 fetch_attrs, cw_fetch_order = fetch_config(['data_name', 'title']) |
157 fetch_attrs, cw_fetch_order = fetch_config(['data_name', 'title']) |
155 |
158 |
156 |
159 |
157 By default, `fetch_config` will return a `cw_fetch_order` method that will order |
160 By default, `fetch_config` will return a `cw_fetch_order` method that will order |
158 on the first attribute in the list. So, we could expect to get files ordered by |
161 on the first attribute in the list. So, we could expect to get files ordered by |
159 their name. But we don't. What's up doc ? |
162 their name. But we don't. What's up doc ? |
173 |
176 |
174 from cubes.folder import entities as folder |
177 from cubes.folder import entities as folder |
175 |
178 |
176 class FolderITreeAdapter(folder.FolderITreeAdapter): |
179 class FolderITreeAdapter(folder.FolderITreeAdapter): |
177 |
180 |
178 def different_type_children(self, entities=True): |
181 def different_type_children(self, entities=True): |
179 rql = self.entity.cw_related_rql(self.tree_relation, |
182 rql = self.entity.cw_related_rql(self.tree_relation, |
180 self.parent_role, ('File',)) |
183 self.parent_role, ('File',)) |
181 rset = self._cw.execute(rql, {'x': self.entity.eid}) |
184 rset = self._cw.execute(rql, {'x': self.entity.eid}) |
182 if entities: |
185 if entities: |
183 return list(rset.entities()) |
186 return list(rset.entities()) |
184 return rset |
187 return rset |
185 |
188 |
186 def registration_callback(vreg): |
189 def registration_callback(vreg): |
187 vreg.register_and_replace(FolderITreeAdapter, folder.FolderITreeAdapter) |
190 vreg.register_and_replace(FolderITreeAdapter, folder.FolderITreeAdapter) |
188 |
191 |
189 As you can see, we simple inherit from the adapter defined in the `folder` cube, |
192 As you can see, we simple inherit from the adapter defined in the `folder` cube, |
190 then we override the `different_type_children` method to give a clue to the ORM's |
193 then we override the `different_type_children` method to give a clue to the ORM's |
191 `cw_related_rql` method, that is responsible to generate the rql to get entities |
194 `cw_related_rql` method, that is responsible to generate the rql to get entities |
192 related to the folder by the `filed_under` relation (the value of the |
195 related to the folder by the `filed_under` relation (the value of the |
214 from cubicweb.predicates import is_instance |
217 from cubicweb.predicates import is_instance |
215 from cubicweb.web.views import navigation |
218 from cubicweb.web.views import navigation |
216 |
219 |
217 |
220 |
218 class FileIPrevNextAdapter(navigation.IPrevNextAdapter): |
221 class FileIPrevNextAdapter(navigation.IPrevNextAdapter): |
219 __select__ = is_instance('File') |
222 __select__ = is_instance('File') |
220 |
223 |
221 def previous_entity(self): |
224 def previous_entity(self): |
222 rset = self._cw.execute('File F ORDERBY FDN DESC LIMIT 1 WHERE ' |
225 rset = self._cw.execute('File F ORDERBY FDN DESC LIMIT 1 WHERE ' |
223 'X filed_under FOLDER, F filed_under FOLDER, ' |
226 'X filed_under FOLDER, F filed_under FOLDER, ' |
224 'F data_name FDN, X data_name > FDN, X eid %(x)s', |
227 'F data_name FDN, X data_name > FDN, X eid %(x)s', |
225 {'x': self.entity.eid}) |
228 {'x': self.entity.eid}) |
226 if rset: |
229 if rset: |
227 return rset.get_entity(0, 0) |
230 return rset.get_entity(0, 0) |
228 |
231 |
229 def next_entity(self): |
232 def next_entity(self): |
230 rset = self._cw.execute('File F ORDERBY FDN ASC LIMIT 1 WHERE ' |
233 rset = self._cw.execute('File F ORDERBY FDN ASC LIMIT 1 WHERE ' |
231 'X filed_under FOLDER, F filed_under FOLDER, ' |
234 'X filed_under FOLDER, F filed_under FOLDER, ' |
232 'F data_name FDN, X data_name < FDN, X eid %(x)s', |
235 'F data_name FDN, X data_name < FDN, X eid %(x)s', |
233 {'x': self.entity.eid}) |
236 {'x': self.entity.eid}) |
234 if rset: |
237 if rset: |
235 return rset.get_entity(0, 0) |
238 return rset.get_entity(0, 0) |
236 |
239 |
237 |
240 |
238 The `IPrevNext` interface implemented by the adapter simply consist in the |
241 The `IPrevNext` interface implemented by the adapter simply consist in the |
239 `previous_entity` / `next_entity` methods, that should respectivly return the |
242 `previous_entity` / `next_entity` methods, that should respectivly return the |
240 previous / next entity or `None`. We make an RQL query to get files in the same |
243 previous / next entity or `None`. We make an RQL query to get files in the same |
277 .. sourcecode:: python |
280 .. sourcecode:: python |
278 |
281 |
279 from cubicweb.web.views import ibreadcrumbs |
282 from cubicweb.web.views import ibreadcrumbs |
280 |
283 |
281 class FileIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter): |
284 class FileIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter): |
282 __select__ = is_instance('File') |
285 __select__ = is_instance('File') |
283 |
286 |
284 def parent_entity(self): |
287 def parent_entity(self): |
285 if self.entity.filed_under: |
288 if self.entity.filed_under: |
286 return self.entity.filed_under[0] |
289 return self.entity.filed_under[0] |
287 |
290 |
288 In that case, we simply use attribute notation provided by the ORM to get the |
291 In that case, we simply use attribute notation provided by the ORM to get the |
289 folder in which the current file (e.g. `self.entity`) is located. |
292 folder in which the current file (e.g. `self.entity`) is located. |
290 |
293 |
291 .. Note:: |
294 .. Note:: |