|
1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 Views & Templates |
|
4 ================= |
|
5 |
|
6 XXXFIXME TURN THIS INTO A CHAPTER |
|
7 |
|
8 Look at ``lax/skel/ginco/web/views/basetemplates.py`` and you will |
|
9 find the base templates used to generate HTML for your application. |
|
10 |
|
11 A page is composed as indicated on the schema below: |
|
12 |
|
13 .. image:: images/lax-book.06-main-template-layout.en.png |
|
14 |
|
15 In this section we will go through a couple of the primary templates |
|
16 you must be interested in, that is to say, the HTMLPageHeader, |
|
17 the HTMLPageFooter and the TheMainTemplate. |
|
18 |
|
19 |
|
20 HTMLPageHeader |
|
21 -------------- |
|
22 |
|
23 Let's use a different logo than the default one provided with LAX |
|
24 and customize our header. |
|
25 |
|
26 Change logo |
|
27 ~~~~~~~~~~~ |
|
28 |
|
29 The easiest way to use a different logo is to replace the existing |
|
30 ``logo.png`` in ``myapp/data`` by your prefered icon and refresh. |
|
31 By default all application will look for a ``logo.png`` to be |
|
32 rendered in the logo section. |
|
33 |
|
34 .. image:: images/lax-book.06-main-template-logo.en.png |
|
35 |
|
36 [ADD] |
|
37 customized external_resources in myapp/data cd crih for reference |
|
38 |
|
39 [WRITE ME] |
|
40 ADD how to use external_resources variables used in ginco/web/webconfig.py |
|
41 |
|
42 Customize header |
|
43 ~~~~~~~~~~~~~~~~ |
|
44 |
|
45 Let's now move the search box in the header and remove the login form |
|
46 from the header. We'll show how to move it to the left column of the application. |
|
47 |
|
48 Let's sat we do not want anymore the login menu to be in the header, but we |
|
49 prefer it to be in the left column just below the logo. As the left column is |
|
50 rendered by ``TheMainTemplate``, we will show how to do it in TheMainTemplate_. |
|
51 |
|
52 First, to remove the login menu, we just need to comment out the display of the |
|
53 login component such as follows: :: |
|
54 |
|
55 class MyHTMLPageHeader(HTMLPageHeader): |
|
56 |
|
57 def main_header(self, view): |
|
58 """build the top menu with authentification info and the rql box""" |
|
59 self.w(u'<table id="header"><tr>\n') |
|
60 self.w(u'<td id="firstcolumn">') |
|
61 self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w) |
|
62 self.w(u'</td>\n') |
|
63 # appliname and breadcrumbs |
|
64 self.w(u'<td id="headtext">') |
|
65 comp = self.vreg.select_component('appliname', self.req, self.rset) |
|
66 if comp and comp.propval('visible'): |
|
67 comp.dispatch(w=self.w) |
|
68 comp = self.vreg.select_component('breadcrumbs', self.req, self.rset, view=view) |
|
69 if comp and comp.propval('visible'): |
|
70 comp.dispatch(w=self.w, view=view) |
|
71 self.w(u'</td>') |
|
72 # logged user and help |
|
73 #self.w(u'<td>\n') |
|
74 #comp = self.vreg.select_component('loggeduserlink', self.req, self.rset) |
|
75 #comp.dispatch(w=self.w) |
|
76 #self.w(u'</td><td>') |
|
77 |
|
78 self.w(u'<td>') |
|
79 helpcomp = self.vreg.select_component('help', self.req, self.rset) |
|
80 if helpcomp: # may not be available if Card is not defined in the schema |
|
81 helpcomp.dispatch(w=self.w) |
|
82 self.w(u'</td>') |
|
83 # lastcolumn |
|
84 self.w(u'<td id="lastcolumn">') |
|
85 self.w(u'</td>\n') |
|
86 self.w(u'</tr></table>\n') |
|
87 self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', |
|
88 title=False, message=False) |
|
89 |
|
90 |
|
91 |
|
92 .. image:: images/lax-book.06-header-no-login.en.png |
|
93 |
|
94 Let's now move the search box in the top-right header area. To do so, we will |
|
95 first create a method to get the search box display and insert it in the header |
|
96 table. |
|
97 |
|
98 :: |
|
99 |
|
100 from ginco.web.views.basetemplates import HTMLPageHeader |
|
101 class MyHTMLPageHeader(HTMLPageHeader): |
|
102 def main_header(self, view): |
|
103 """build the top menu with authentification info and the rql box""" |
|
104 self.w(u'<table id="header"><tr>\n') |
|
105 self.w(u'<td id="firstcolumn">') |
|
106 self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w) |
|
107 self.w(u'</td>\n') |
|
108 # appliname and breadcrumbs |
|
109 self.w(u'<td id="headtext">') |
|
110 comp = self.vreg.select_component('appliname', self.req, self.rset) |
|
111 if comp and comp.propval('visible'): |
|
112 comp.dispatch(w=self.w) |
|
113 comp = self.vreg.select_component('breadcrumbs', self.req, self.rset, view=view) |
|
114 if comp and comp.propval('visible'): |
|
115 comp.dispatch(w=self.w, view=view) |
|
116 self.w(u'</td>') |
|
117 |
|
118 # logged user and help |
|
119 #self.w(u'<td>\n') |
|
120 #comp = self.vreg.select_component('loggeduserlink', self.req, self.rset) |
|
121 #comp.dispatch(w=self.w) |
|
122 #self.w(u'</td><td>') |
|
123 |
|
124 # search box |
|
125 self.w(u'<td>') |
|
126 self.get_searchbox(view, 'left') |
|
127 self.w(u'</td>') |
|
128 |
|
129 self.w(u'<td>') |
|
130 helpcomp = self.vreg.select_component('help', self.req, self.rset) |
|
131 if helpcomp: # may not be available if Card is not defined in the schema |
|
132 helpcomp.dispatch(w=self.w) |
|
133 self.w(u'</td>') |
|
134 # lastcolumn |
|
135 self.w(u'<td id="lastcolumn">') |
|
136 self.w(u'</td>\n') |
|
137 self.w(u'</tr></table>\n') |
|
138 self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', |
|
139 title=False, message=False) |
|
140 |
|
141 def get_searchbox(self, view, context): |
|
142 boxes = list(self.vreg.possible_vobjects('boxes', self.req, self.rset, |
|
143 view=view, context=context)) |
|
144 if boxes: |
|
145 for box in boxes: |
|
146 if box.id == 'search_box': |
|
147 box.dispatch(w=self.w, view=view) |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 HTMLPageFooter |
|
153 -------------- |
|
154 |
|
155 If you want to change the footer for example, look |
|
156 for HTMLPageFooter and override it in your views file as in: |
|
157 :: |
|
158 |
|
159 form ginco.web.views.basetemplates import HTMLPageFooter |
|
160 class MyHTMLPageFooter(HTMLPageFooter): |
|
161 def call(self, **kwargs): |
|
162 self.w(u'<div class="footer">') |
|
163 self.w(u'This website has been created with <a href="http://lax.logilab.org">LAX</a>.') |
|
164 self.w(u'</div>') |
|
165 |
|
166 Updating a view does not require any restart of the server. By reloading |
|
167 the page you can see your new page footer. |
|
168 |
|
169 |
|
170 TheMainTemplate |
|
171 --------------- |
|
172 .. _TheMainTemplate: |
|
173 |
|
174 The MainTemplate is a bit complex as it tries to accomodate many |
|
175 different cases. We are now about to go through it and cutomize entirely |
|
176 our application. |
|
177 |
|
178 TheMainTemplate is responsible for the general layout of the entire application. |
|
179 It defines the template of ``id = main`` that is used by the application. Is |
|
180 also defined in ``ginco/web/views/basetemplates.py`` another template that can |
|
181 be used based on TheMainTemplate called SimpleMainTemplate which does not have |
|
182 a top section. |
|
183 |
|
184 .. image:: images/lax-book.06-simple-main-template.en.png |
|
185 |
|
186 CSS changes |
|
187 ----------- |
|
188 |
|
189 We cannot modify the order in which the application is reading the CSS. In |
|
190 the case we want to create new CSS style, the best is to define it a in a new |
|
191 CSS located under ``myapp/data/``. |
|
192 |
|
193 If you want to modify an existing CSS styling property, you will have to use |
|
194 ``!important`` declaration to override the existing property. The application |
|
195 apply a higher priority on the default CSS and you can not change that. |
|
196 Customized CSS will not be read first. |
|
197 |
|
198 1 |
|
199 [TODO] |
|
200 Add login menu in left column |
|
201 |
|
202 |
|
203 [WRITE ME] |
|
204 |
|
205 * customize MainTemplate and show that everything in the user |
|
206 interface can be changed |
|
207 |
|
208 [TODO] |
|
209 Rajouter une section pour definir la terminologie utilisee. |
|
210 Dans ginco-doc rajouter une section pour erudi-ctl shell ou |
|
211 on liste les commandes dispos. |