Merge lp:~openerp-dev/openerp-web/7.0-module-tutorial-xmo into lp:openerp-web/7.0
- 7.0-module-tutorial-xmo
- Merge into 7.0
Proposed by
Xavier (Open ERP)
Status: | Rejected |
---|---|
Rejected by: | Xavier (Open ERP) |
Proposed branch: | lp:~openerp-dev/openerp-web/7.0-module-tutorial-xmo |
Merge into: | lp:openerp-web/7.0 |
Diff against target: |
1537 lines (+882/-283) 49 files modified
addons/web/doc/conf.py (+5/-1) addons/web/doc/module.rst (+195/-36) addons/web/doc/module/0 (+17/-0) addons/web/doc/module/10 (+13/-0) addons/web/doc/module/11 (+11/-0) addons/web/doc/module/12 (+28/-0) addons/web/doc/module/14 (+17/-0) addons/web/doc/module/15 (+19/-0) addons/web/doc/module/16 (+25/-0) addons/web/doc/module/17 (+52/-0) addons/web/doc/module/18 (+19/-0) addons/web/doc/module/19 (+52/-0) addons/web/doc/module/2 (+12/-0) addons/web/doc/module/20 (+64/-0) addons/web/doc/module/21 (+27/-0) addons/web/doc/module/22 (+6/-0) addons/web/doc/module/23 (+14/-0) addons/web/doc/module/24 (+10/-0) addons/web/doc/module/25 (+55/-0) addons/web/doc/module/26 (+38/-0) addons/web/doc/module/27 (+28/-0) addons/web/doc/module/28 (+13/-0) addons/web/doc/module/29 (+37/-0) addons/web/doc/module/3 (+9/-0) addons/web/doc/module/4 (+11/-0) addons/web/doc/module/5 (+11/-0) addons/web/doc/module/6 (+29/-0) addons/web/doc/module/8 (+14/-0) addons/web/doc/module/9 (+21/-0) addons/web/doc/module/__openerp__.py (+0/-7) addons/web/doc/module/__openerp__.py.1.diff (+0/-11) addons/web/doc/module/__openerp__.py.2.diff (+0/-11) addons/web/doc/module/__openerp__.py.3.diff (+0/-12) addons/web/doc/module/__openerp__.py.4.diff (+0/-13) addons/web/doc/module/__openerp__.py.5.diff (+0/-14) addons/web/doc/module/series (+27/-0) addons/web/doc/module/static/src/css/web_example.css (+0/-6) addons/web/doc/module/static/src/css/web_example.css.1.diff (+0/-17) addons/web/doc/module/static/src/js/first_module.js (+0/-2) addons/web/doc/module/static/src/js/first_module.js.1.diff (+0/-8) addons/web/doc/module/static/src/js/first_module.js.2.diff (+0/-11) addons/web/doc/module/static/src/js/first_module.js.3.diff (+0/-18) addons/web/doc/module/static/src/js/first_module.js.4.diff (+0/-15) addons/web/doc/module/static/src/js/first_module.js.5.diff (+0/-23) addons/web/doc/module/static/src/js/first_module.js.6.diff (+0/-55) addons/web/doc/module/static/src/xml/web_example.xml (+0/-11) addons/web/doc/module/web_example.xml (+0/-11) addons/web/doc/testing.rst (+2/-0) addons/web/doc/widget.rst (+1/-1) |
To merge this branch: | bzr merge lp:~openerp-dev/openerp-web/7.0-module-tutorial-xmo |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Core Team | Pending | ||
Review via email: mp+148709@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 3739. By Xavier (Open ERP)
-
[WIP] testing in module guide
- 3740. By Xavier (Open ERP)
-
[IMP] final section of the module guide
Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote : | # |
Unmerged revisions
- 3740. By Xavier (Open ERP)
-
[IMP] final section of the module guide
- 3739. By Xavier (Open ERP)
-
[WIP] testing in module guide
- 3738. By Xavier (Open ERP)
-
[ADD] sync-on-start tutoring
- 3737. By Xavier (Open ERP)
-
[IMP] replace ad-hoc patch display by patchqueue
- 3736. By Xavier (Open ERP)
-
[IMP] web module tutorial: start adding RPC stuff
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'addons/web/doc/conf.py' | |||
2 | --- addons/web/doc/conf.py 2013-01-17 09:27:22 +0000 | |||
3 | +++ addons/web/doc/conf.py 2013-02-18 15:08:21 +0000 | |||
4 | @@ -27,7 +27,11 @@ | |||
5 | 27 | 27 | ||
6 | 28 | # Add any Sphinx extension module names here, as strings. They can be extensions | 28 | # Add any Sphinx extension module names here, as strings. They can be extensions |
7 | 29 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. | 29 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. |
9 | 30 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode'] | 30 | extensions = [ |
10 | 31 | 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', | ||
11 | 32 | 'sphinx.ext.todo', 'sphinx.ext.viewcode', | ||
12 | 33 | 'patchqueue' | ||
13 | 34 | ] | ||
14 | 31 | 35 | ||
15 | 32 | # Add any paths that contain templates here, relative to this directory. | 36 | # Add any paths that contain templates here, relative to this directory. |
16 | 33 | templates_path = ['_templates'] | 37 | templates_path = ['_templates'] |
17 | 34 | 38 | ||
18 | === modified file 'addons/web/doc/module.rst' | |||
19 | --- addons/web/doc/module.rst 2013-01-17 09:27:22 +0000 | |||
20 | +++ addons/web/doc/module.rst 2013-02-18 15:08:21 +0000 | |||
21 | @@ -1,5 +1,7 @@ | |||
22 | 1 | .. _module: | 1 | .. _module: |
23 | 2 | 2 | ||
24 | 3 | .. queue:: module/series | ||
25 | 4 | |||
26 | 3 | Building an OpenERP Web module | 5 | Building an OpenERP Web module |
27 | 4 | ============================== | 6 | ============================== |
28 | 5 | 7 | ||
29 | @@ -19,8 +21,7 @@ | |||
30 | 19 | ├── __init__.py | 21 | ├── __init__.py |
31 | 20 | └── __openerp__.py | 22 | └── __openerp__.py |
32 | 21 | 23 | ||
35 | 22 | .. literalinclude:: module/__openerp__.py | 24 | .. patch:: |
34 | 23 | :language: python | ||
36 | 24 | 25 | ||
37 | 25 | This is a sufficient minimal declaration of a valid OpenERP module. | 26 | This is a sufficient minimal declaration of a valid OpenERP module. |
38 | 26 | 27 | ||
39 | @@ -41,8 +42,7 @@ | |||
40 | 41 | is the extent of it. You should also change the dependency to list | 42 | is the extent of it. You should also change the dependency to list |
41 | 42 | ``web``: | 43 | ``web``: |
42 | 43 | 44 | ||
45 | 44 | .. literalinclude:: module/__openerp__.py.1.diff | 45 | .. patch:: |
44 | 45 | :language: diff | ||
46 | 46 | 46 | ||
47 | 47 | .. note:: | 47 | .. note:: |
48 | 48 | 48 | ||
49 | @@ -67,15 +67,13 @@ | |||
50 | 67 | ``static/src/js``, to have room for e.g. other file types, or | 67 | ``static/src/js``, to have room for e.g. other file types, or |
51 | 68 | third-party libraries. | 68 | third-party libraries. |
52 | 69 | 69 | ||
55 | 70 | .. literalinclude:: module/static/src/js/first_module.js | 70 | .. patch:: |
54 | 71 | :language: javascript | ||
56 | 72 | 71 | ||
57 | 73 | The client won't load any file unless specified, thus the new file | 72 | The client won't load any file unless specified, thus the new file |
58 | 74 | should be listed in the module's manifest file, under a new key ``js`` | 73 | should be listed in the module's manifest file, under a new key ``js`` |
59 | 75 | (a list of file names, or glob patterns): | 74 | (a list of file names, or glob patterns): |
60 | 76 | 75 | ||
63 | 77 | .. literalinclude:: module/__openerp__.py.2.diff | 76 | .. patch:: |
62 | 78 | :language: diff | ||
64 | 79 | 77 | ||
65 | 80 | At this point, if the module is installed and the client reloaded the | 78 | At this point, if the module is installed and the client reloaded the |
66 | 81 | message should appear in your browser's development console. | 79 | message should appear in your browser's development console. |
67 | @@ -100,8 +98,7 @@ | |||
68 | 100 | client (such as making RPC requests to the server). This is done by | 98 | client (such as making RPC requests to the server). This is done by |
69 | 101 | providing a `javascript module`_: | 99 | providing a `javascript module`_: |
70 | 102 | 100 | ||
73 | 103 | .. literalinclude:: module/static/src/js/first_module.js.1.diff | 101 | .. patch:: |
72 | 104 | :language: diff | ||
74 | 105 | 102 | ||
75 | 106 | If you reload the client, you'll see a message in the console exactly | 103 | If you reload the client, you'll see a message in the console exactly |
76 | 107 | as previously. The differences, though invisible at this point, are: | 104 | as previously. The differences, though invisible at this point, are: |
77 | @@ -122,17 +119,12 @@ | |||
78 | 122 | 119 | ||
79 | 123 | First, the action declaration: | 120 | First, the action declaration: |
80 | 124 | 121 | ||
86 | 125 | .. literalinclude:: module/__openerp__.py.3.diff | 122 | .. patch:: |
82 | 126 | :language: diff | ||
83 | 127 | |||
84 | 128 | .. literalinclude:: module/web_example.xml | ||
85 | 129 | :language: xml | ||
87 | 130 | 123 | ||
88 | 131 | then set up the :doc:`client action hook <client_action>` to register | 124 | then set up the :doc:`client action hook <client_action>` to register |
89 | 132 | a function (for now): | 125 | a function (for now): |
90 | 133 | 126 | ||
93 | 134 | .. literalinclude:: module/static/src/js/first_module.js.2.diff | 127 | .. patch:: |
92 | 135 | :language: diff | ||
94 | 136 | 128 | ||
95 | 137 | Updating the module (in order to load the XML description) and | 129 | Updating the module (in order to load the XML description) and |
96 | 138 | re-starting the server should display a new menu *Example Client | 130 | re-starting the server should display a new menu *Example Client |
97 | @@ -148,8 +140,7 @@ | |||
98 | 148 | its :js:func:`~openerp.web.Widget.start` to add some content to its | 140 | its :js:func:`~openerp.web.Widget.start` to add some content to its |
99 | 149 | DOM: | 141 | DOM: |
100 | 150 | 142 | ||
103 | 151 | .. literalinclude:: module/static/src/js/first_module.js.3.diff | 143 | .. patch:: |
102 | 152 | :language: diff | ||
104 | 153 | 144 | ||
105 | 154 | after reloading the client (to update the javascript file), instead of | 145 | after reloading the client (to update the javascript file), instead of |
106 | 155 | printing to the console the menu item clears the whole screen and | 146 | printing to the console the menu item clears the whole screen and |
107 | @@ -159,15 +150,13 @@ | |||
108 | 159 | <widget-dom_root>` we can now see how to add a stylesheet to a module: | 150 | <widget-dom_root>` we can now see how to add a stylesheet to a module: |
109 | 160 | first create the stylesheet file: | 151 | first create the stylesheet file: |
110 | 161 | 152 | ||
113 | 162 | .. literalinclude:: module/static/src/css/web_example.css | 153 | .. patch:: |
112 | 163 | :language: css | ||
114 | 164 | 154 | ||
115 | 165 | then add a reference to the stylesheet in the module's manifest (which | 155 | then add a reference to the stylesheet in the module's manifest (which |
116 | 166 | will require restarting the OpenERP Server to see the changes, as | 156 | will require restarting the OpenERP Server to see the changes, as |
117 | 167 | usual): | 157 | usual): |
118 | 168 | 158 | ||
121 | 169 | .. literalinclude:: module/__openerp__.py.4.diff | 159 | .. patch:: |
120 | 170 | :language: diff | ||
122 | 171 | 160 | ||
123 | 172 | the text displayed by the menu item should now be huge, and | 161 | the text displayed by the menu item should now be huge, and |
124 | 173 | white-on-black (instead of small and black-on-white). From there on, | 162 | white-on-black (instead of small and black-on-white). From there on, |
125 | @@ -204,22 +193,16 @@ | |||
126 | 204 | 193 | ||
127 | 205 | Adding a template file is similar to adding a style sheet: | 194 | Adding a template file is similar to adding a style sheet: |
128 | 206 | 195 | ||
134 | 207 | .. literalinclude:: module/static/src/xml/web_example.xml | 196 | .. patch:: |
130 | 208 | :language: xml | ||
131 | 209 | |||
132 | 210 | .. literalinclude:: module/__openerp__.py.5.diff | ||
133 | 211 | :language: diff | ||
135 | 212 | 197 | ||
136 | 213 | The template can then easily be hooked in the widget: | 198 | The template can then easily be hooked in the widget: |
137 | 214 | 199 | ||
140 | 215 | .. literalinclude:: module/static/src/js/first_module.js.4.diff | 200 | .. patch:: |
139 | 216 | :language: diff | ||
141 | 217 | 201 | ||
142 | 218 | And finally the CSS can be altered to style the new (and more complex) | 202 | And finally the CSS can be altered to style the new (and more complex) |
143 | 219 | template-generated DOM, rather than the code-generated one: | 203 | template-generated DOM, rather than the code-generated one: |
144 | 220 | 204 | ||
147 | 221 | .. literalinclude:: module/static/src/css/web_example.css.1.diff | 205 | .. patch:: |
146 | 222 | :language: diff | ||
148 | 223 | 206 | ||
149 | 224 | .. note:: | 207 | .. note:: |
150 | 225 | 208 | ||
151 | @@ -238,15 +221,13 @@ | |||
152 | 238 | our stopwatch watch. First hook some events on the buttons to toggle | 221 | our stopwatch watch. First hook some events on the buttons to toggle |
153 | 239 | the widget's state: | 222 | the widget's state: |
154 | 240 | 223 | ||
157 | 241 | .. literalinclude:: module/static/src/js/first_module.js.5.diff | 224 | .. patch:: |
156 | 242 | :language: diff | ||
158 | 243 | 225 | ||
159 | 244 | This demonstrates the use of the "events hash" and event delegation to | 226 | This demonstrates the use of the "events hash" and event delegation to |
160 | 245 | declaratively handle events on the widget's DOM. And already changes | 227 | declaratively handle events on the widget's DOM. And already changes |
161 | 246 | the button displayed in the UI. Then comes some actual logic: | 228 | the button displayed in the UI. Then comes some actual logic: |
162 | 247 | 229 | ||
165 | 248 | .. literalinclude:: module/static/src/js/first_module.js.6.diff | 230 | .. patch:: |
164 | 249 | :language: diff | ||
166 | 250 | 231 | ||
167 | 251 | * An initializer (the ``init`` method) is introduced to set-up a few | 232 | * An initializer (the ``init`` method) is introduced to set-up a few |
168 | 252 | internal variables: ``_start`` will hold the start of the timer (as | 233 | internal variables: ``_start`` will hold the start of the timer (as |
169 | @@ -273,6 +254,184 @@ | |||
170 | 273 | Starting and stopping the watch now works, and correctly tracks time | 254 | Starting and stopping the watch now works, and correctly tracks time |
171 | 274 | since having started the watch, neatly formatted. | 255 | since having started the watch, neatly formatted. |
172 | 275 | 256 | ||
173 | 257 | Burning through the skies | ||
174 | 258 | ------------------------- | ||
175 | 259 | |||
176 | 260 | All work so far has been "local" outside of the original impetus | ||
177 | 261 | provided by the client action: the widget is self-contained and, once | ||
178 | 262 | started, does not communicate with anything outside itself. Not only | ||
179 | 263 | that, but it has no persistence: if the user leaves the stopwatch | ||
180 | 264 | screen (to go and see his inbox, or do some well-deserved accounting, | ||
181 | 265 | for instance) whatever was being timed will be lost. | ||
182 | 266 | |||
183 | 267 | To prevent this irremediable loss, we can use OpenERP's support for | ||
184 | 268 | storing data as a model, allowing so that we don't lose our data and | ||
185 | 269 | can later retrieve, query and manipulate it. First let's create a | ||
186 | 270 | basic OpenERP model in which our data will be stored: | ||
187 | 271 | |||
188 | 272 | .. patch:: | ||
189 | 273 | |||
190 | 274 | then let's add saving times to the database every time the stopwatch | ||
191 | 275 | is stopped, using :js:class:`the "high-level" Model API | ||
192 | 276 | <openerp.web.Model.call>`: | ||
193 | 277 | |||
194 | 278 | .. patch:: | ||
195 | 279 | |||
196 | 280 | A look at the "Network" tab of your preferred browser's developer | ||
197 | 281 | tools while playing with the stopwatch will show that the save | ||
198 | 282 | (creation) request is indeed sent (and replied to, even though we're | ||
199 | 283 | ignoring the response at this point). | ||
200 | 284 | |||
201 | 285 | These saved data should now be loaded and displayed when first opening | ||
202 | 286 | the action, so the user can see his previously recorded times. This is | ||
203 | 287 | done by overloading the model's ``start`` method: the purpose of | ||
204 | 288 | :js:func:`~openerp.base.Widget.start()` is to perform *asynchronous* | ||
205 | 289 | initialization steps, so the rest of the web client knows to "wait" | ||
206 | 290 | and gets a readiness signal. In this case, it will fetch the data | ||
207 | 291 | recorded previously using the :js:class:`~openerp.web.Query` interface | ||
208 | 292 | and add this data to an ordered list added to the widget's template: | ||
209 | 293 | |||
210 | 294 | .. patch:: | ||
211 | 295 | |||
212 | 296 | And for consistency's sake (so that the display a user leaves is | ||
213 | 297 | pretty much the same as the one he comes back to), newly created | ||
214 | 298 | records should also automatically be added to the list: | ||
215 | 299 | |||
216 | 300 | .. patch:: | ||
217 | 301 | |||
218 | 302 | Note that we're only displaying the record once we know it's been | ||
219 | 303 | saved from the database (the ``create`` call has returned without | ||
220 | 304 | error). | ||
221 | 305 | |||
222 | 306 | Mic check, is this working? | ||
223 | 307 | --------------------------- | ||
224 | 308 | |||
225 | 309 | So far, features have been implemented, code has been worked and | ||
226 | 310 | tentatively tried. However, there is no guarantee they will *keep | ||
227 | 311 | working* as new changes are performed, new features added, … | ||
228 | 312 | |||
229 | 313 | The original author (you, dear reader) could keep a notebook with a | ||
230 | 314 | list of workflows to check, to ensure everything keeps working. And | ||
231 | 315 | follow the notebook day after day, every time something is changed in | ||
232 | 316 | the module. | ||
233 | 317 | |||
234 | 318 | That gets repetitive after a while. And computers are good at doing | ||
235 | 319 | repetitive stuff, as long as you tell them how to do it. | ||
236 | 320 | |||
237 | 321 | So let's add test to the module, so that in the future the computer | ||
238 | 322 | can take care of ensuring what works today keeps working tomorrow. | ||
239 | 323 | |||
240 | 324 | .. note:: | ||
241 | 325 | |||
242 | 326 | Here we're writing tests after having implemented the widget. This | ||
243 | 327 | may or may not work, we may need to alter bits and pieces of code | ||
244 | 328 | to get them in a testable state. An other testing methodology is | ||
245 | 329 | :abbr:`TDD (Test-Driven Development)` where the tests are written | ||
246 | 330 | first, and the code necessary to make these tests pass is written | ||
247 | 331 | afterwards. | ||
248 | 332 | |||
249 | 333 | Both methods have their opponents and detractors, advantages and | ||
250 | 334 | inconvenients. Pick the one you prefer. | ||
251 | 335 | |||
252 | 336 | The first step of :doc:`testing` is to set up the basic testing | ||
253 | 337 | structure: | ||
254 | 338 | |||
255 | 339 | 1. Creating a javascript file | ||
256 | 340 | |||
257 | 341 | .. patch:: | ||
258 | 342 | |||
259 | 343 | 2. Containing a test section (and a few tests to make sure the tests | ||
260 | 344 | are correctly run) | ||
261 | 345 | |||
262 | 346 | .. patch:: | ||
263 | 347 | |||
264 | 348 | 3. Then declaring the test file in the module's manifest | ||
265 | 349 | |||
266 | 350 | .. patch:: | ||
267 | 351 | |||
268 | 352 | 4. And finally — after restarting OpenERP — navigating to the test | ||
269 | 353 | runner at ``/web/tests`` and selecting your soon-to-be-tested | ||
270 | 354 | module: | ||
271 | 355 | |||
272 | 356 | .. image:: module/testing_0.png | ||
273 | 357 | :align: center | ||
274 | 358 | |||
275 | 359 | the testing result do indeed match the test. | ||
276 | 360 | |||
277 | 361 | The simplest tests to write are for synchronous pure | ||
278 | 362 | functions. Synchronous means no RPC call or any other such thing | ||
279 | 363 | (e.g. ``setTimeout``), only direct data processing, and pure means no | ||
280 | 364 | side-effect: the function takes some input, manipulates it and yields | ||
281 | 365 | an output. | ||
282 | 366 | |||
283 | 367 | In our widget, only ``format_time`` fits the bill: it takes a duration | ||
284 | 368 | (in milliseconds) and returns an ``hours:minutes:second`` formatting | ||
285 | 369 | of it. Let's test it: | ||
286 | 370 | |||
287 | 371 | .. patch:: | ||
288 | 372 | |||
289 | 373 | This series of simple tests passes with no issue. The next easy-ish | ||
290 | 374 | test type is to test basic DOM alterations from provided input, such | ||
291 | 375 | as (for our widget) updating the counter or displaying a record to the | ||
292 | 376 | records list: while it's not pure (it alters the DOM "in-place") it | ||
293 | 377 | has well-delimited side-effects and these side-effects come solely | ||
294 | 378 | from the provided input. | ||
295 | 379 | |||
296 | 380 | Because these methods alter the widget's DOM, the widget needs a | ||
297 | 381 | DOM. Looking up :doc:`a widget's lifecycle <widget>`, the widget | ||
298 | 382 | really only gets its DOM when adding it to the document. However a | ||
299 | 383 | side-effect of this is to :js:func:`~openerp.web.Widget.start` it, | ||
300 | 384 | which for us means going to query the user's times. | ||
301 | 385 | |||
302 | 386 | We don't have any records to get in our test, and we don't want to | ||
303 | 387 | test the initialization yet! So let's cheat a bit: we can manually | ||
304 | 388 | :js:func:`set a widget's DOM <openerp.web.Widget.setElement>`, let's | ||
305 | 389 | create a basic DOM matching what each method expects then call the | ||
306 | 390 | method: | ||
307 | 391 | |||
308 | 392 | .. patch:: | ||
309 | 393 | |||
310 | 394 | The next group of patches (in terms of setup/complexity) is RPC tests: | ||
311 | 395 | testing components/methods which perform network calls (RPC | ||
312 | 396 | requests). In our module, ``start`` and ``watch_stop`` are in that | ||
313 | 397 | case: ``start`` fetches the user's recorded times and ``watch_stop`` | ||
314 | 398 | creates a new record with the current watch. | ||
315 | 399 | |||
316 | 400 | By default, tests don't allow RPC requests and will generate an error | ||
317 | 401 | when trying to perform one: | ||
318 | 402 | |||
319 | 403 | .. image:: module/testing_1.png | ||
320 | 404 | :align: center | ||
321 | 405 | |||
322 | 406 | To allow them, the test case (or the test suite) has to explicitly opt | ||
323 | 407 | into :js:attr:`rpc support <TestOptions.rpc>` by adding the ``rpc: | ||
324 | 408 | 'mock'`` option to the test case, and providing its own "rpc | ||
325 | 409 | responses": | ||
326 | 410 | |||
327 | 411 | .. patch:: | ||
328 | 412 | |||
329 | 413 | .. note:: | ||
330 | 414 | |||
331 | 415 | By defaut, tests cases don't load templates either. We had not | ||
332 | 416 | needed to perform any template rendering before here, so we must | ||
333 | 417 | now enable templates loading via :js:attr:`the corresponding | ||
334 | 418 | option <TestOptions.templates>`. | ||
335 | 419 | |||
336 | 420 | Our final test requires altering the module's code: asynchronous tests | ||
337 | 421 | use :doc:`deferred </async>` to know when a test ends and the other | ||
338 | 422 | one can start (otherwise test content will execute non-linearly and | ||
339 | 423 | the assertions of a test will be executed during the next test or | ||
340 | 424 | worse), but although ``watch_stop`` performs an asynchronous | ||
341 | 425 | ``create`` operation it doesn't return a deferred we can synchronize | ||
342 | 426 | on. We simply need to return its result: | ||
343 | 427 | |||
344 | 428 | .. patch:: | ||
345 | 429 | |||
346 | 430 | This makes no difference to the original code, but allows us to write | ||
347 | 431 | our test: | ||
348 | 432 | |||
349 | 433 | .. patch:: | ||
350 | 434 | |||
351 | 276 | .. [#DOM-building] they are not alternative solutions: they work very | 435 | .. [#DOM-building] they are not alternative solutions: they work very |
352 | 277 | well together. Templates are used to build "just | 436 | well together. Templates are used to build "just |
353 | 278 | DOM", sub-widgets are used to build DOM subsections | 437 | DOM", sub-widgets are used to build DOM subsections |
354 | 279 | 438 | ||
355 | === added file 'addons/web/doc/module/0' | |||
356 | --- addons/web/doc/module/0 1970-01-01 00:00:00 +0000 | |||
357 | +++ addons/web/doc/module/0 2013-02-18 15:08:21 +0000 | |||
358 | @@ -0,0 +1,17 @@ | |||
359 | 1 | # HG changeset patch | ||
360 | 2 | # Parent 0000000000000000000000000000000000000000 | ||
361 | 3 | |||
362 | 4 | diff --git a/__init__.py b/__init__.py | ||
363 | 5 | new file mode 100644 | ||
364 | 6 | diff --git a/__openerp__.py b/__openerp__.py | ||
365 | 7 | new file mode 100644 | ||
366 | 8 | --- /dev/null | ||
367 | 9 | +++ b/__openerp__.py | ||
368 | 10 | @@ -0,0 +1,7 @@ | ||
369 | 11 | +# __openerp__.py | ||
370 | 12 | +{ | ||
371 | 13 | + 'name': "Web Example", | ||
372 | 14 | + 'description': "Basic example of a (future) web module", | ||
373 | 15 | + 'category': 'Hidden', | ||
374 | 16 | + 'depends': ['base'], | ||
375 | 17 | +} | ||
376 | 0 | 18 | ||
377 | === added file 'addons/web/doc/module/10' | |||
378 | --- addons/web/doc/module/10 1970-01-01 00:00:00 +0000 | |||
379 | +++ addons/web/doc/module/10 2013-02-18 15:08:21 +0000 | |||
380 | @@ -0,0 +1,13 @@ | |||
381 | 1 | # HG changeset patch | ||
382 | 2 | # Parent 72d9d59a93fcee06ba28cf0b98a1075331dcc8f4 | ||
383 | 3 | diff --git a/static/src/css/web_example.css b/static/src/css/web_example.css | ||
384 | 4 | new file mode 100644 | ||
385 | 5 | --- /dev/null | ||
386 | 6 | +++ b/static/src/css/web_example.css | ||
387 | 7 | @@ -0,0 +1,6 @@ | ||
388 | 8 | +.openerp .oe_web_example { | ||
389 | 9 | + color: white; | ||
390 | 10 | + background-color: black; | ||
391 | 11 | + height: 100%; | ||
392 | 12 | + font-size: 400%; | ||
393 | 13 | +} | ||
394 | 0 | 14 | ||
395 | === added file 'addons/web/doc/module/11' | |||
396 | --- addons/web/doc/module/11 1970-01-01 00:00:00 +0000 | |||
397 | +++ addons/web/doc/module/11 2013-02-18 15:08:21 +0000 | |||
398 | @@ -0,0 +1,11 @@ | |||
399 | 1 | # HG changeset patch | ||
400 | 2 | # Parent 3ed382d9a8fe64fbb8e2bf4045e3fcd5c74c92bc | ||
401 | 3 | diff --git a/__openerp__.py b/__openerp__.py | ||
402 | 4 | --- a/__openerp__.py | ||
403 | 5 | +++ b/__openerp__.py | ||
404 | 6 | @@ -6,4 +6,5 @@ | ||
405 | 7 | 'depends': ['web'], | ||
406 | 8 | 'data': ['web_example.xml'], | ||
407 | 9 | 'js': ['static/src/js/first_module.js'], | ||
408 | 10 | + 'css': ['static/src/css/web_example.css'], | ||
409 | 11 | } | ||
410 | 0 | 12 | ||
411 | === added file 'addons/web/doc/module/12' | |||
412 | --- addons/web/doc/module/12 1970-01-01 00:00:00 +0000 | |||
413 | +++ addons/web/doc/module/12 2013-02-18 15:08:21 +0000 | |||
414 | @@ -0,0 +1,28 @@ | |||
415 | 1 | # HG changeset patch | ||
416 | 2 | # Parent 43f21611dacb7c2b2f3810baeeef359ad7c329f0 | ||
417 | 3 | |||
418 | 4 | diff --git a/__openerp__.py b/__openerp__.py | ||
419 | 5 | --- a/__openerp__.py | ||
420 | 6 | +++ b/__openerp__.py | ||
421 | 7 | @@ -7,4 +7,5 @@ | ||
422 | 8 | 'data': ['web_example.xml'], | ||
423 | 9 | 'js': ['static/src/js/first_module.js'], | ||
424 | 10 | 'css': ['static/src/css/web_example.css'], | ||
425 | 11 | + 'qweb': ['static/src/xml/web_example.xml'], | ||
426 | 12 | } | ||
427 | 13 | diff --git a/static/src/xml/web_example.xml b/static/src/xml/web_example.xml | ||
428 | 14 | new file mode 100644 | ||
429 | 15 | --- /dev/null | ||
430 | 16 | +++ b/static/src/xml/web_example.xml | ||
431 | 17 | @@ -0,0 +1,11 @@ | ||
432 | 18 | +<templates> | ||
433 | 19 | +<div t-name="web_example.action" class="oe_web_example oe_web_example_stopped"> | ||
434 | 20 | + <h4 class="oe_web_example_timer">00:00:00</h4> | ||
435 | 21 | + <p class="oe_web_example_start"> | ||
436 | 22 | + <button type="button">Start</button> | ||
437 | 23 | + </p> | ||
438 | 24 | + <p class="oe_web_example_stop"> | ||
439 | 25 | + <button type="button">Stop</button> | ||
440 | 26 | + </p> | ||
441 | 27 | +</div> | ||
442 | 28 | +</templates> | ||
443 | 0 | 29 | ||
444 | === added file 'addons/web/doc/module/14' | |||
445 | --- addons/web/doc/module/14 1970-01-01 00:00:00 +0000 | |||
446 | +++ addons/web/doc/module/14 2013-02-18 15:08:21 +0000 | |||
447 | @@ -0,0 +1,17 @@ | |||
448 | 1 | # HG changeset patch | ||
449 | 2 | # Parent ae3b427c96b532794a65357b3f075129cc991276 | ||
450 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
451 | 4 | --- a/static/src/js/first_module.js | ||
452 | 5 | +++ b/static/src/js/first_module.js | ||
453 | 6 | @@ -2,10 +2,6 @@ | ||
454 | 7 | openerp.web_example = function (instance) { | ||
455 | 8 | instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
456 | 9 | instance.web_example.Action = instance.web.Widget.extend({ | ||
457 | 10 | - className: 'oe_web_example', | ||
458 | 11 | - start: function () { | ||
459 | 12 | - this.$el.text("Hello, world!"); | ||
460 | 13 | - return this._super(); | ||
461 | 14 | - } | ||
462 | 15 | + template: 'web_example.action' | ||
463 | 16 | }); | ||
464 | 17 | }; | ||
465 | 0 | 18 | ||
466 | === added file 'addons/web/doc/module/15' | |||
467 | --- addons/web/doc/module/15 1970-01-01 00:00:00 +0000 | |||
468 | +++ addons/web/doc/module/15 2013-02-18 15:08:21 +0000 | |||
469 | @@ -0,0 +1,19 @@ | |||
470 | 1 | # HG changeset patch | ||
471 | 2 | # Parent e2d2e1a4cc2d2496aebeb05d94768384427c9e8b | ||
472 | 3 | diff --git a/static/src/css/web_example.css b/static/src/css/web_example.css | ||
473 | 4 | --- a/static/src/css/web_example.css | ||
474 | 5 | +++ b/static/src/css/web_example.css | ||
475 | 6 | @@ -2,5 +2,12 @@ | ||
476 | 7 | color: white; | ||
477 | 8 | background-color: black; | ||
478 | 9 | height: 100%; | ||
479 | 10 | - font-size: 400%; | ||
480 | 11 | } | ||
481 | 12 | +.openerp .oe_web_example h4 { | ||
482 | 13 | + margin: 0; | ||
483 | 14 | + font-size: 200%; | ||
484 | 15 | +} | ||
485 | 16 | +.openerp .oe_web_example.oe_web_example_started .oe_web_example_start button, | ||
486 | 17 | +.openerp .oe_web_example.oe_web_example_stopped .oe_web_example_stop button { | ||
487 | 18 | + display: none | ||
488 | 19 | +} | ||
489 | 0 | 20 | ||
490 | === added file 'addons/web/doc/module/16' | |||
491 | --- addons/web/doc/module/16 1970-01-01 00:00:00 +0000 | |||
492 | +++ addons/web/doc/module/16 2013-02-18 15:08:21 +0000 | |||
493 | @@ -0,0 +1,25 @@ | |||
494 | 1 | # HG changeset patch | ||
495 | 2 | # Parent 2645d7a09dcba7f6d6074a33252c16c03c56fdf3 | ||
496 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
497 | 4 | --- a/static/src/js/first_module.js | ||
498 | 5 | +++ b/static/src/js/first_module.js | ||
499 | 6 | @@ -2,6 +2,18 @@ | ||
500 | 7 | openerp.web_example = function (instance) { | ||
501 | 8 | instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
502 | 9 | instance.web_example.Action = instance.web.Widget.extend({ | ||
503 | 10 | - template: 'web_example.action' | ||
504 | 11 | + template: 'web_example.action', | ||
505 | 12 | + events: { | ||
506 | 13 | + 'click .oe_web_example_start button': 'watch_start', | ||
507 | 14 | + 'click .oe_web_example_stop button': 'watch_stop' | ||
508 | 15 | + }, | ||
509 | 16 | + watch_start: function () { | ||
510 | 17 | + this.$el.addClass('oe_web_example_started') | ||
511 | 18 | + .removeClass('oe_web_example_stopped'); | ||
512 | 19 | + }, | ||
513 | 20 | + watch_stop: function () { | ||
514 | 21 | + this.$el.removeClass('oe_web_example_started') | ||
515 | 22 | + .addClass('oe_web_example_stopped'); | ||
516 | 23 | + }, | ||
517 | 24 | }); | ||
518 | 25 | }; | ||
519 | 0 | 26 | ||
520 | === added file 'addons/web/doc/module/17' | |||
521 | --- addons/web/doc/module/17 1970-01-01 00:00:00 +0000 | |||
522 | +++ addons/web/doc/module/17 2013-02-18 15:08:21 +0000 | |||
523 | @@ -0,0 +1,52 @@ | |||
524 | 1 | # HG changeset patch | ||
525 | 2 | # Parent 2921a545adc3406d3139be7951f3225e94493466 | ||
526 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
527 | 4 | --- a/static/src/js/first_module.js | ||
528 | 5 | +++ b/static/src/js/first_module.js | ||
529 | 6 | @@ -7,13 +7,46 @@ openerp.web_example = function (instance | ||
530 | 7 | 'click .oe_web_example_start button': 'watch_start', | ||
531 | 8 | 'click .oe_web_example_stop button': 'watch_stop' | ||
532 | 9 | }, | ||
533 | 10 | + init: function () { | ||
534 | 11 | + this._super.apply(this, arguments); | ||
535 | 12 | + this._start = null; | ||
536 | 13 | + this._watch = null; | ||
537 | 14 | + }, | ||
538 | 15 | + update_counter: function () { | ||
539 | 16 | + var h, m, s; | ||
540 | 17 | + // Subtracting javascript dates returns the difference in milliseconds | ||
541 | 18 | + var diff = new Date() - this._start; | ||
542 | 19 | + s = diff / 1000; | ||
543 | 20 | + m = Math.floor(s / 60); | ||
544 | 21 | + s -= 60*m; | ||
545 | 22 | + h = Math.floor(m / 60); | ||
546 | 23 | + m -= 60*h; | ||
547 | 24 | + this.$('.oe_web_example_timer').text( | ||
548 | 25 | + _.str.sprintf("%02d:%02d:%02d", h, m, s)); | ||
549 | 26 | + }, | ||
550 | 27 | watch_start: function () { | ||
551 | 28 | this.$el.addClass('oe_web_example_started') | ||
552 | 29 | .removeClass('oe_web_example_stopped'); | ||
553 | 30 | + this._start = new Date(); | ||
554 | 31 | + // Update the UI to the current time | ||
555 | 32 | + this.update_counter(); | ||
556 | 33 | + // Update the counter at 30 FPS (33ms/frame) | ||
557 | 34 | + this._watch = setInterval( | ||
558 | 35 | + this.proxy('update_counter'), | ||
559 | 36 | + 33); | ||
560 | 37 | }, | ||
561 | 38 | watch_stop: function () { | ||
562 | 39 | + clearInterval(this._watch); | ||
563 | 40 | + this.update_counter(); | ||
564 | 41 | + this._start = this._watch = null; | ||
565 | 42 | this.$el.removeClass('oe_web_example_started') | ||
566 | 43 | .addClass('oe_web_example_stopped'); | ||
567 | 44 | }, | ||
568 | 45 | + destroy: function () { | ||
569 | 46 | + if (this._watch) { | ||
570 | 47 | + clearInterval(this._watch); | ||
571 | 48 | + } | ||
572 | 49 | + this._super(); | ||
573 | 50 | + } | ||
574 | 51 | }); | ||
575 | 52 | }; | ||
576 | 0 | 53 | ||
577 | === added file 'addons/web/doc/module/18' | |||
578 | --- addons/web/doc/module/18 1970-01-01 00:00:00 +0000 | |||
579 | +++ addons/web/doc/module/18 2013-02-18 15:08:21 +0000 | |||
580 | @@ -0,0 +1,19 @@ | |||
581 | 1 | # HG changeset patch | ||
582 | 2 | # Parent e0cc13c2b2ec4d6f6bfdb033b189a32e44106f2e | ||
583 | 3 | diff --git a/__init__.py b/__init__.py | ||
584 | 4 | --- a/__init__.py | ||
585 | 5 | +++ b/__init__.py | ||
586 | 6 | @@ -0,0 +1,13 @@ | ||
587 | 7 | +# __init__.py | ||
588 | 8 | +from openerp.osv import orm, fields | ||
589 | 9 | + | ||
590 | 10 | + | ||
591 | 11 | +class Times(orm.Model): | ||
592 | 12 | + _name = 'web_example.stopwatch' | ||
593 | 13 | + | ||
594 | 14 | + _columns = { | ||
595 | 15 | + 'time': fields.integer("Time", required=True, | ||
596 | 16 | + help="Measured time in milliseconds"), | ||
597 | 17 | + 'user_id': fields.many2one('res.users', "User", required=True, | ||
598 | 18 | + help="User who registered the measurement") | ||
599 | 19 | + } | ||
600 | 0 | 20 | ||
601 | === added file 'addons/web/doc/module/19' | |||
602 | --- addons/web/doc/module/19 1970-01-01 00:00:00 +0000 | |||
603 | +++ addons/web/doc/module/19 2013-02-18 15:08:21 +0000 | |||
604 | @@ -0,0 +1,52 @@ | |||
605 | 1 | # HG changeset patch | ||
606 | 2 | # Parent 05797cc75b49634e640f44b24347f2905b464022 | ||
607 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
608 | 4 | --- a/static/src/js/first_module.js | ||
609 | 5 | +++ b/static/src/js/first_module.js | ||
610 | 6 | @@ -12,11 +12,13 @@ openerp.web_example = function (instance | ||
611 | 7 | this._start = null; | ||
612 | 8 | this._watch = null; | ||
613 | 9 | }, | ||
614 | 10 | - update_counter: function () { | ||
615 | 11 | + current: function () { | ||
616 | 12 | + // Subtracting javascript dates returns the difference in milliseconds | ||
617 | 13 | + return new Date() - this._start; | ||
618 | 14 | + }, | ||
619 | 15 | + update_counter: function (time) { | ||
620 | 16 | var h, m, s; | ||
621 | 17 | - // Subtracting javascript dates returns the difference in milliseconds | ||
622 | 18 | - var diff = new Date() - this._start; | ||
623 | 19 | - s = diff / 1000; | ||
624 | 20 | + s = time / 1000; | ||
625 | 21 | m = Math.floor(s / 60); | ||
626 | 22 | s -= 60*m; | ||
627 | 23 | h = Math.floor(m / 60); | ||
628 | 24 | @@ -29,18 +31,24 @@ openerp.web_example = function (instance | ||
629 | 25 | .removeClass('oe_web_example_stopped'); | ||
630 | 26 | this._start = new Date(); | ||
631 | 27 | // Update the UI to the current time | ||
632 | 28 | - this.update_counter(); | ||
633 | 29 | + this.update_counter(this.current()); | ||
634 | 30 | // Update the counter at 30 FPS (33ms/frame) | ||
635 | 31 | - this._watch = setInterval( | ||
636 | 32 | - this.proxy('update_counter'), | ||
637 | 33 | + this._watch = setInterval(function () { | ||
638 | 34 | + this.update_counter(this.current()); | ||
639 | 35 | + }.bind(this), | ||
640 | 36 | 33); | ||
641 | 37 | }, | ||
642 | 38 | watch_stop: function () { | ||
643 | 39 | clearInterval(this._watch); | ||
644 | 40 | - this.update_counter(); | ||
645 | 41 | + var time = this.current(); | ||
646 | 42 | + this.update_counter(time); | ||
647 | 43 | this._start = this._watch = null; | ||
648 | 44 | this.$el.removeClass('oe_web_example_started') | ||
649 | 45 | .addClass('oe_web_example_stopped'); | ||
650 | 46 | + new instance.web.Model('web_example.stopwatch').call('create', [{ | ||
651 | 47 | + user_id: instance.session.uid, | ||
652 | 48 | + time: time, | ||
653 | 49 | + }]); | ||
654 | 50 | }, | ||
655 | 51 | destroy: function () { | ||
656 | 52 | if (this._watch) { | ||
657 | 0 | 53 | ||
658 | === added file 'addons/web/doc/module/2' | |||
659 | --- addons/web/doc/module/2 1970-01-01 00:00:00 +0000 | |||
660 | +++ addons/web/doc/module/2 2013-02-18 15:08:21 +0000 | |||
661 | @@ -0,0 +1,12 @@ | |||
662 | 1 | # HG changeset patch | ||
663 | 2 | # Parent 8a986919a3e22cd7cca51210820c09d4545dc60d | ||
664 | 3 | diff --git a/__openerp__.py b/__openerp__.py | ||
665 | 4 | --- a/__openerp__.py | ||
666 | 5 | +++ b/__openerp__.py | ||
667 | 6 | @@ -3,5 +3,5 @@ | ||
668 | 7 | 'name': "Web Example", | ||
669 | 8 | 'description': "Basic example of a (future) web module", | ||
670 | 9 | 'category': 'Hidden', | ||
671 | 10 | - 'depends': ['base'], | ||
672 | 11 | + 'depends': ['web'], | ||
673 | 12 | } | ||
674 | 0 | 13 | ||
675 | === added file 'addons/web/doc/module/20' | |||
676 | --- addons/web/doc/module/20 1970-01-01 00:00:00 +0000 | |||
677 | +++ addons/web/doc/module/20 2013-02-18 15:08:21 +0000 | |||
678 | @@ -0,0 +1,64 @@ | |||
679 | 1 | Index: web_example/static/src/js/first_module.js | ||
680 | 2 | =================================================================== | ||
681 | 3 | --- web_example.orig/static/src/js/first_module.js | ||
682 | 4 | +++ web_example/static/src/js/first_module.js | ||
683 | 5 | @@ -11,20 +11,36 @@ openerp.web_example = function (instance | ||
684 | 6 | this._super.apply(this, arguments); | ||
685 | 7 | this._start = null; | ||
686 | 8 | this._watch = null; | ||
687 | 9 | + this.model = new instance.web.Model('web_example.stopwatch'); | ||
688 | 10 | + }, | ||
689 | 11 | + start: function () { | ||
690 | 12 | + var display = this.display_record.bind(this); | ||
691 | 13 | + return this.model.query() | ||
692 | 14 | + .filter([['user_id', '=', instance.session.uid]]) | ||
693 | 15 | + .all().done(function (records) { | ||
694 | 16 | + _(records).each(display); | ||
695 | 17 | + }); | ||
696 | 18 | }, | ||
697 | 19 | current: function () { | ||
698 | 20 | // Subtracting javascript dates returns the difference in milliseconds | ||
699 | 21 | return new Date() - this._start; | ||
700 | 22 | }, | ||
701 | 23 | - update_counter: function (time) { | ||
702 | 24 | + display_record: function (record) { | ||
703 | 25 | + $('<li>') | ||
704 | 26 | + .text(this.format_time(record.time)) | ||
705 | 27 | + .appendTo(this.$('.oe_web_example_saved')); | ||
706 | 28 | + }, | ||
707 | 29 | + format_time: function (time) { | ||
708 | 30 | var h, m, s; | ||
709 | 31 | s = time / 1000; | ||
710 | 32 | m = Math.floor(s / 60); | ||
711 | 33 | s -= 60*m; | ||
712 | 34 | h = Math.floor(m / 60); | ||
713 | 35 | m -= 60*h; | ||
714 | 36 | - this.$('.oe_web_example_timer').text( | ||
715 | 37 | - _.str.sprintf("%02d:%02d:%02d", h, m, s)); | ||
716 | 38 | + return _.str.sprintf("%02d:%02d:%02d", h, m, s); | ||
717 | 39 | + }, | ||
718 | 40 | + update_counter: function (time) { | ||
719 | 41 | + this.$('.oe_web_example_timer').text(this.format_time(time)); | ||
720 | 42 | }, | ||
721 | 43 | watch_start: function () { | ||
722 | 44 | this.$el.addClass('oe_web_example_started') | ||
723 | 45 | @@ -45,7 +61,7 @@ openerp.web_example = function (instance | ||
724 | 46 | this._start = this._watch = null; | ||
725 | 47 | this.$el.removeClass('oe_web_example_started') | ||
726 | 48 | .addClass('oe_web_example_stopped'); | ||
727 | 49 | - new instance.web.Model('web_example.stopwatch').call('create', [{ | ||
728 | 50 | + this.model.call('create', [{ | ||
729 | 51 | user_id: instance.session.uid, | ||
730 | 52 | time: time, | ||
731 | 53 | }]); | ||
732 | 54 | Index: web_example/static/src/xml/web_example.xml | ||
733 | 55 | =================================================================== | ||
734 | 56 | --- web_example.orig/static/src/xml/web_example.xml | ||
735 | 57 | +++ web_example/static/src/xml/web_example.xml | ||
736 | 58 | @@ -7,5 +7,6 @@ | ||
737 | 59 | <p class="oe_web_example_stop"> | ||
738 | 60 | <button type="button">Stop</button> | ||
739 | 61 | </p> | ||
740 | 62 | + <ol class="oe_web_example_saved"></ol> | ||
741 | 63 | </div> | ||
742 | 64 | </templates> | ||
743 | 0 | 65 | ||
744 | === added file 'addons/web/doc/module/21' | |||
745 | --- addons/web/doc/module/21 1970-01-01 00:00:00 +0000 | |||
746 | +++ addons/web/doc/module/21 2013-02-18 15:08:21 +0000 | |||
747 | @@ -0,0 +1,27 @@ | |||
748 | 1 | Index: web_example/static/src/js/first_module.js | ||
749 | 2 | =================================================================== | ||
750 | 3 | --- web_example.orig/static/src/js/first_module.js | ||
751 | 4 | +++ web_example/static/src/js/first_module.js | ||
752 | 5 | @@ -55,16 +55,20 @@ openerp.web_example = function (instance | ||
753 | 6 | 33); | ||
754 | 7 | }, | ||
755 | 8 | watch_stop: function () { | ||
756 | 9 | + var self = this; | ||
757 | 10 | clearInterval(this._watch); | ||
758 | 11 | var time = this.current(); | ||
759 | 12 | this.update_counter(time); | ||
760 | 13 | this._start = this._watch = null; | ||
761 | 14 | this.$el.removeClass('oe_web_example_started') | ||
762 | 15 | .addClass('oe_web_example_stopped'); | ||
763 | 16 | - this.model.call('create', [{ | ||
764 | 17 | + var record = { | ||
765 | 18 | user_id: instance.session.uid, | ||
766 | 19 | time: time, | ||
767 | 20 | - }]); | ||
768 | 21 | + }; | ||
769 | 22 | + this.model.call('create', [record]).done(function () { | ||
770 | 23 | + self.display_record(record); | ||
771 | 24 | + }); | ||
772 | 25 | }, | ||
773 | 26 | destroy: function () { | ||
774 | 27 | if (this._watch) { | ||
775 | 0 | 28 | ||
776 | === added file 'addons/web/doc/module/22' | |||
777 | --- addons/web/doc/module/22 1970-01-01 00:00:00 +0000 | |||
778 | +++ addons/web/doc/module/22 2013-02-18 15:08:21 +0000 | |||
779 | @@ -0,0 +1,6 @@ | |||
780 | 1 | Index: web_example/static/src/tests/timer.js | ||
781 | 2 | =================================================================== | ||
782 | 3 | --- /dev/null | ||
783 | 4 | +++ web_example/static/src/tests/timer.js | ||
784 | 5 | @@ -0,0 +1 @@ | ||
785 | 6 | + | ||
786 | 0 | 7 | ||
787 | === added file 'addons/web/doc/module/23' | |||
788 | --- addons/web/doc/module/23 1970-01-01 00:00:00 +0000 | |||
789 | +++ addons/web/doc/module/23 2013-02-18 15:08:21 +0000 | |||
790 | @@ -0,0 +1,14 @@ | |||
791 | 1 | Index: web_example/static/src/tests/timer.js | ||
792 | 2 | =================================================================== | ||
793 | 3 | --- web_example.orig/static/src/tests/timer.js | ||
794 | 4 | +++ web_example/static/src/tests/timer.js | ||
795 | 5 | @@ -1 +1,8 @@ | ||
796 | 6 | - | ||
797 | 7 | +openerp.testing.section('timer', function (test) { | ||
798 | 8 | + test('successful test', function () { | ||
799 | 9 | + ok(true, "should work"); | ||
800 | 10 | + }); | ||
801 | 11 | + test('unsuccessful test', function () { | ||
802 | 12 | + ok(false, "shoud fail"); | ||
803 | 13 | + }); | ||
804 | 14 | +}); | ||
805 | 0 | 15 | ||
806 | === added file 'addons/web/doc/module/24' | |||
807 | --- addons/web/doc/module/24 1970-01-01 00:00:00 +0000 | |||
808 | +++ addons/web/doc/module/24 2013-02-18 15:08:21 +0000 | |||
809 | @@ -0,0 +1,10 @@ | |||
810 | 1 | Index: web_example/__openerp__.py | ||
811 | 2 | =================================================================== | ||
812 | 3 | --- web_example.orig/__openerp__.py | ||
813 | 4 | +++ web_example/__openerp__.py | ||
814 | 5 | @@ -8,4 +8,5 @@ | ||
815 | 6 | 'js': ['static/src/js/first_module.js'], | ||
816 | 7 | 'css': ['static/src/css/web_example.css'], | ||
817 | 8 | 'qweb': ['static/src/xml/web_example.xml'], | ||
818 | 9 | + 'test': ['static/src/tests/timer.js'], | ||
819 | 10 | } | ||
820 | 0 | 11 | ||
821 | === added file 'addons/web/doc/module/25' | |||
822 | --- addons/web/doc/module/25 1970-01-01 00:00:00 +0000 | |||
823 | +++ addons/web/doc/module/25 2013-02-18 15:08:21 +0000 | |||
824 | @@ -0,0 +1,55 @@ | |||
825 | 1 | Index: web_example/static/src/tests/timer.js | ||
826 | 2 | =================================================================== | ||
827 | 3 | --- web_example.orig/static/src/tests/timer.js | ||
828 | 4 | +++ web_example/static/src/tests/timer.js | ||
829 | 5 | @@ -1,8 +1,45 @@ | ||
830 | 6 | openerp.testing.section('timer', function (test) { | ||
831 | 7 | - test('successful test', function () { | ||
832 | 8 | - ok(true, "should work"); | ||
833 | 9 | - }); | ||
834 | 10 | - test('unsuccessful test', function () { | ||
835 | 11 | - ok(false, "shoud fail"); | ||
836 | 12 | + test('format_time', function (instance) { | ||
837 | 13 | + var w = new instance.web_example.Action(); | ||
838 | 14 | + | ||
839 | 15 | + strictEqual( | ||
840 | 16 | + w.format_time(0), | ||
841 | 17 | + '00:00:00'); | ||
842 | 18 | + strictEqual( | ||
843 | 19 | + w.format_time(543), | ||
844 | 20 | + '00:00:00', | ||
845 | 21 | + "should round sub-second times down to zero"); | ||
846 | 22 | + strictEqual( | ||
847 | 23 | + w.format_time(5340), | ||
848 | 24 | + '00:00:05', | ||
849 | 25 | + "should floor sub-second extents to the previous second"); | ||
850 | 26 | + strictEqual( | ||
851 | 27 | + w.format_time(60000), | ||
852 | 28 | + '00:01:00'); | ||
853 | 29 | + strictEqual( | ||
854 | 30 | + w.format_time(3600000), | ||
855 | 31 | + '01:00:00'); | ||
856 | 32 | + strictEqual( | ||
857 | 33 | + w.format_time(86400000), | ||
858 | 34 | + '24:00:00'); | ||
859 | 35 | + strictEqual( | ||
860 | 36 | + w.format_time(604800000), | ||
861 | 37 | + '168:00:00'); | ||
862 | 38 | + | ||
863 | 39 | + strictEqual( | ||
864 | 40 | + w.format_time(22733958), | ||
865 | 41 | + '06:18:53'); | ||
866 | 42 | + strictEqual( | ||
867 | 43 | + w.format_time(41676639), | ||
868 | 44 | + '11:34:36'); | ||
869 | 45 | + strictEqual( | ||
870 | 46 | + w.format_time(57802094), | ||
871 | 47 | + '16:03:22'); | ||
872 | 48 | + strictEqual( | ||
873 | 49 | + w.format_time(73451828), | ||
874 | 50 | + '20:24:11'); | ||
875 | 51 | + strictEqual( | ||
876 | 52 | + w.format_time(84092336), | ||
877 | 53 | + '23:21:32'); | ||
878 | 54 | }); | ||
879 | 55 | }); | ||
880 | 0 | 56 | ||
881 | === added file 'addons/web/doc/module/26' | |||
882 | --- addons/web/doc/module/26 1970-01-01 00:00:00 +0000 | |||
883 | +++ addons/web/doc/module/26 2013-02-18 15:08:21 +0000 | |||
884 | @@ -0,0 +1,38 @@ | |||
885 | 1 | Index: web_example/static/src/tests/timer.js | ||
886 | 2 | =================================================================== | ||
887 | 3 | --- web_example.orig/static/src/tests/timer.js | ||
888 | 4 | +++ web_example/static/src/tests/timer.js | ||
889 | 5 | @@ -42,4 +42,33 @@ openerp.testing.section('timer', functio | ||
890 | 6 | w.format_time(84092336), | ||
891 | 7 | '23:21:32'); | ||
892 | 8 | }); | ||
893 | 9 | + test('update_counter', function (instance, $fixture) { | ||
894 | 10 | + var w = new instance.web_example.Action(); | ||
895 | 11 | + // $fixture is a DOM tree whose content gets cleaned up before | ||
896 | 12 | + // each test, so we can add whatever we need to it | ||
897 | 13 | + $fixture.append('<div class="oe_web_example_timer">'); | ||
898 | 14 | + // Then set it on the widget | ||
899 | 15 | + w.setElement($fixture); | ||
900 | 16 | + | ||
901 | 17 | + // Update the counter with a known value | ||
902 | 18 | + w.update_counter(22733958); | ||
903 | 19 | + // And check the DOM matches | ||
904 | 20 | + strictEqual($fixture.text(), '06:18:53'); | ||
905 | 21 | + | ||
906 | 22 | + w.update_counter(73451828) | ||
907 | 23 | + strictEqual($fixture.text(), '20:24:11'); | ||
908 | 24 | + }); | ||
909 | 25 | + test('display_record', function (instance, $fixture) { | ||
910 | 26 | + var w = new instance.web_example.Action(); | ||
911 | 27 | + $fixture.append('<ol class="oe_web_example_saved">') | ||
912 | 28 | + w.setElement($fixture); | ||
913 | 29 | + | ||
914 | 30 | + w.display_record({time: 41676639}); | ||
915 | 31 | + w.display_record({time: 84092336}); | ||
916 | 32 | + | ||
917 | 33 | + var $lis = $fixture.find('li'); | ||
918 | 34 | + strictEqual($lis.length, 2, "should have printed 2 records"); | ||
919 | 35 | + strictEqual($lis[0].textContent, '11:34:36'); | ||
920 | 36 | + strictEqual($lis[1].textContent, '23:21:32'); | ||
921 | 37 | + }); | ||
922 | 38 | }); | ||
923 | 0 | 39 | ||
924 | === added file 'addons/web/doc/module/27' | |||
925 | --- addons/web/doc/module/27 1970-01-01 00:00:00 +0000 | |||
926 | +++ addons/web/doc/module/27 2013-02-18 15:08:21 +0000 | |||
927 | @@ -0,0 +1,28 @@ | |||
928 | 1 | Index: web_example/static/src/tests/timer.js | ||
929 | 2 | =================================================================== | ||
930 | 3 | --- web_example.orig/static/src/tests/timer.js | ||
931 | 4 | +++ web_example/static/src/tests/timer.js | ||
932 | 5 | @@ -71,4 +71,23 @@ openerp.testing.section('timer', functio | ||
933 | 6 | strictEqual($lis[0].textContent, '11:34:36'); | ||
934 | 7 | strictEqual($lis[1].textContent, '23:21:32'); | ||
935 | 8 | }); | ||
936 | 9 | + test('start', {templates: true, rpc: 'mock', asserts: 3}, function (instance, $fixture, mock) { | ||
937 | 10 | + // Rather odd-looking shortcut for search+read in a single RPC call | ||
938 | 11 | + mock('/web/dataset/search_read', function () { | ||
939 | 12 | + // ignore parameters, just return a pair of records. | ||
940 | 13 | + return {records: [ | ||
941 | 14 | + {time: 22733958}, | ||
942 | 15 | + {time: 84092336} | ||
943 | 16 | + ]}; | ||
944 | 17 | + }); | ||
945 | 18 | + | ||
946 | 19 | + var w = new instance.web_example.Action(); | ||
947 | 20 | + return w.appendTo($fixture) | ||
948 | 21 | + .then(function () { | ||
949 | 22 | + var $lis = $fixture.find('li'); | ||
950 | 23 | + strictEqual($lis.length, 2); | ||
951 | 24 | + strictEqual($lis[0].textContent, '06:18:53'); | ||
952 | 25 | + strictEqual($lis[1].textContent, '23:21:32'); | ||
953 | 26 | + }); | ||
954 | 27 | + }); | ||
955 | 28 | }); | ||
956 | 0 | 29 | ||
957 | === added file 'addons/web/doc/module/28' | |||
958 | --- addons/web/doc/module/28 1970-01-01 00:00:00 +0000 | |||
959 | +++ addons/web/doc/module/28 2013-02-18 15:08:21 +0000 | |||
960 | @@ -0,0 +1,13 @@ | |||
961 | 1 | Index: web_example/static/src/js/first_module.js | ||
962 | 2 | =================================================================== | ||
963 | 3 | --- web_example.orig/static/src/js/first_module.js | ||
964 | 4 | +++ web_example/static/src/js/first_module.js | ||
965 | 5 | @@ -66,7 +66,7 @@ openerp.web_example = function (instance | ||
966 | 6 | user_id: instance.session.uid, | ||
967 | 7 | time: time, | ||
968 | 8 | }; | ||
969 | 9 | - this.model.call('create', [record]).done(function () { | ||
970 | 10 | + return this.model.call('create', [record]).done(function () { | ||
971 | 11 | self.display_record(record); | ||
972 | 12 | }); | ||
973 | 13 | }, | ||
974 | 0 | 14 | ||
975 | === added file 'addons/web/doc/module/29' | |||
976 | --- addons/web/doc/module/29 1970-01-01 00:00:00 +0000 | |||
977 | +++ addons/web/doc/module/29 2013-02-18 15:08:21 +0000 | |||
978 | @@ -0,0 +1,37 @@ | |||
979 | 1 | Index: web_example/static/src/tests/timer.js | ||
980 | 2 | =================================================================== | ||
981 | 3 | --- web_example.orig/static/src/tests/timer.js | ||
982 | 4 | +++ web_example/static/src/tests/timer.js | ||
983 | 5 | @@ -90,4 +90,32 @@ openerp.testing.section('timer', functio | ||
984 | 6 | strictEqual($lis[1].textContent, '23:21:32'); | ||
985 | 7 | }); | ||
986 | 8 | }); | ||
987 | 9 | + test('watch_stop', {templates: true, rpc: 'mock', asserts: 3}, function (instance, $fix, mock) { | ||
988 | 10 | + var created = false; | ||
989 | 11 | + mock('web_example.stopwatch:create', function (args, kwargs) { | ||
990 | 12 | + created = true; | ||
991 | 13 | + // return a fake id (unused) | ||
992 | 14 | + return 42; | ||
993 | 15 | + }); | ||
994 | 16 | + mock('/web/dataset/search_read', function () { | ||
995 | 17 | + return {records: []}; | ||
996 | 18 | + }); | ||
997 | 19 | + | ||
998 | 20 | + var w = new instance.web_example.Action(); | ||
999 | 21 | + return w.appendTo($fix) | ||
1000 | 22 | + .then(function () { | ||
1001 | 23 | + // Virtual start point 5s before 'now' | ||
1002 | 24 | + w._start = new Date() - 5000; | ||
1003 | 25 | + return w.watch_stop(); | ||
1004 | 26 | + }) | ||
1005 | 27 | + .done(function () { | ||
1006 | 28 | + ok(created, "should have called create()"); | ||
1007 | 29 | + strictEqual($fix.find('.oe_web_example_timer').text(), | ||
1008 | 30 | + '00:00:05', | ||
1009 | 31 | + "should have updated the timer"); | ||
1010 | 32 | + strictEqual($fix.find('li')[0].textContent, | ||
1011 | 33 | + '00:00:05', | ||
1012 | 34 | + "should have added the new time to the list"); | ||
1013 | 35 | + }); | ||
1014 | 36 | + }); | ||
1015 | 37 | }); | ||
1016 | 0 | 38 | ||
1017 | === added file 'addons/web/doc/module/3' | |||
1018 | --- addons/web/doc/module/3 1970-01-01 00:00:00 +0000 | |||
1019 | +++ addons/web/doc/module/3 2013-02-18 15:08:21 +0000 | |||
1020 | @@ -0,0 +1,9 @@ | |||
1021 | 1 | # HG changeset patch | ||
1022 | 2 | # Parent dcf661a5eef8f82503831bdb8e6c9d2f9beb285e | ||
1023 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
1024 | 4 | new file mode 100644 | ||
1025 | 5 | --- /dev/null | ||
1026 | 6 | +++ b/static/src/js/first_module.js | ||
1027 | 7 | @@ -0,0 +1,2 @@ | ||
1028 | 8 | +// static/src/js/first_module.js | ||
1029 | 9 | +console.log("Debug statement: file loaded"); | ||
1030 | 0 | 10 | ||
1031 | === added file 'addons/web/doc/module/4' | |||
1032 | --- addons/web/doc/module/4 1970-01-01 00:00:00 +0000 | |||
1033 | +++ addons/web/doc/module/4 2013-02-18 15:08:21 +0000 | |||
1034 | @@ -0,0 +1,11 @@ | |||
1035 | 1 | # HG changeset patch | ||
1036 | 2 | # Parent 139dae60de67efa0017f5032f71ab774685c5507 | ||
1037 | 3 | diff --git a/__openerp__.py b/__openerp__.py | ||
1038 | 4 | --- a/__openerp__.py | ||
1039 | 5 | +++ b/__openerp__.py | ||
1040 | 6 | @@ -4,4 +4,5 @@ | ||
1041 | 7 | 'description': "Basic example of a (future) web module", | ||
1042 | 8 | 'category': 'Hidden', | ||
1043 | 9 | 'depends': ['web'], | ||
1044 | 10 | + 'js': ['static/src/js/first_module.js'], | ||
1045 | 11 | } | ||
1046 | 0 | 12 | ||
1047 | === added file 'addons/web/doc/module/5' | |||
1048 | --- addons/web/doc/module/5 1970-01-01 00:00:00 +0000 | |||
1049 | +++ addons/web/doc/module/5 2013-02-18 15:08:21 +0000 | |||
1050 | @@ -0,0 +1,11 @@ | |||
1051 | 1 | # HG changeset patch | ||
1052 | 2 | # Parent c8ae7646cce3f271698c844eb2d67f9a8719650d | ||
1053 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
1054 | 4 | --- a/static/src/js/first_module.js | ||
1055 | 5 | +++ b/static/src/js/first_module.js | ||
1056 | 6 | @@ -1,2 +1,4 @@ | ||
1057 | 7 | // static/src/js/first_module.js | ||
1058 | 8 | -console.log("Debug statement: file loaded"); | ||
1059 | 9 | +openerp.web_example = function (instance) { | ||
1060 | 10 | + console.log("Module loaded"); | ||
1061 | 11 | +}; | ||
1062 | 0 | 12 | ||
1063 | === added file 'addons/web/doc/module/6' | |||
1064 | --- addons/web/doc/module/6 1970-01-01 00:00:00 +0000 | |||
1065 | +++ addons/web/doc/module/6 2013-02-18 15:08:21 +0000 | |||
1066 | @@ -0,0 +1,29 @@ | |||
1067 | 1 | # HG changeset patch | ||
1068 | 2 | # Parent 0026cb80097a724db8d36371bc00da993a51a06f | ||
1069 | 3 | |||
1070 | 4 | diff --git a/__openerp__.py b/__openerp__.py | ||
1071 | 5 | --- a/__openerp__.py | ||
1072 | 6 | +++ b/__openerp__.py | ||
1073 | 7 | @@ -4,5 +4,6 @@ | ||
1074 | 8 | 'description': "Basic example of a (future) web module", | ||
1075 | 9 | 'category': 'Hidden', | ||
1076 | 10 | 'depends': ['web'], | ||
1077 | 11 | + 'data': ['web_example.xml'], | ||
1078 | 12 | 'js': ['static/src/js/first_module.js'], | ||
1079 | 13 | } | ||
1080 | 14 | diff --git a/web_example.xml b/web_example.xml | ||
1081 | 15 | new file mode 100644 | ||
1082 | 16 | --- /dev/null | ||
1083 | 17 | +++ b/web_example.xml | ||
1084 | 18 | @@ -0,0 +1,11 @@ | ||
1085 | 19 | +<!-- web_example/web_example.xml --> | ||
1086 | 20 | +<openerp> | ||
1087 | 21 | + <data> | ||
1088 | 22 | + <record model="ir.actions.client" id="action_client_example"> | ||
1089 | 23 | + <field name="name">Example Client Action</field> | ||
1090 | 24 | + <field name="tag">example.action</field> | ||
1091 | 25 | + </record> | ||
1092 | 26 | + <menuitem action="action_client_example" | ||
1093 | 27 | + id="menu_client_example"/> | ||
1094 | 28 | + </data> | ||
1095 | 29 | +</openerp> | ||
1096 | 0 | 30 | ||
1097 | === added file 'addons/web/doc/module/8' | |||
1098 | --- addons/web/doc/module/8 1970-01-01 00:00:00 +0000 | |||
1099 | +++ addons/web/doc/module/8 2013-02-18 15:08:21 +0000 | |||
1100 | @@ -0,0 +1,14 @@ | |||
1101 | 1 | # HG changeset patch | ||
1102 | 2 | # Parent d987c9edd884de1de30f2ceb70d2e554474b8dd1 | ||
1103 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
1104 | 4 | --- a/static/src/js/first_module.js | ||
1105 | 5 | +++ b/static/src/js/first_module.js | ||
1106 | 6 | @@ -1,4 +1,7 @@ | ||
1107 | 7 | // static/src/js/first_module.js | ||
1108 | 8 | openerp.web_example = function (instance) { | ||
1109 | 9 | - console.log("Module loaded"); | ||
1110 | 10 | + instance.web.client_actions.add('example.action', 'instance.web_example.action'); | ||
1111 | 11 | + instance.web_example.action = function (parent, action) { | ||
1112 | 12 | + console.log("Executed the action", action); | ||
1113 | 13 | + }; | ||
1114 | 14 | }; | ||
1115 | 0 | 15 | ||
1116 | === added file 'addons/web/doc/module/9' | |||
1117 | --- addons/web/doc/module/9 1970-01-01 00:00:00 +0000 | |||
1118 | +++ addons/web/doc/module/9 2013-02-18 15:08:21 +0000 | |||
1119 | @@ -0,0 +1,21 @@ | |||
1120 | 1 | # HG changeset patch | ||
1121 | 2 | # Parent 6a1a7240ea0e63182f60abb1eb5c631089d56dbe | ||
1122 | 3 | diff --git a/static/src/js/first_module.js b/static/src/js/first_module.js | ||
1123 | 4 | --- a/static/src/js/first_module.js | ||
1124 | 5 | +++ b/static/src/js/first_module.js | ||
1125 | 6 | @@ -1,7 +1,11 @@ | ||
1126 | 7 | // static/src/js/first_module.js | ||
1127 | 8 | openerp.web_example = function (instance) { | ||
1128 | 9 | - instance.web.client_actions.add('example.action', 'instance.web_example.action'); | ||
1129 | 10 | - instance.web_example.action = function (parent, action) { | ||
1130 | 11 | - console.log("Executed the action", action); | ||
1131 | 12 | - }; | ||
1132 | 13 | + instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
1133 | 14 | + instance.web_example.Action = instance.web.Widget.extend({ | ||
1134 | 15 | + className: 'oe_web_example', | ||
1135 | 16 | + start: function () { | ||
1136 | 17 | + this.$el.text("Hello, world!"); | ||
1137 | 18 | + return this._super(); | ||
1138 | 19 | + } | ||
1139 | 20 | + }); | ||
1140 | 21 | }; | ||
1141 | 0 | 22 | ||
1142 | === removed file 'addons/web/doc/module/__init__.py' | |||
1143 | === removed file 'addons/web/doc/module/__openerp__.py' | |||
1144 | --- addons/web/doc/module/__openerp__.py 2012-12-05 13:28:54 +0000 | |||
1145 | +++ addons/web/doc/module/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
1146 | @@ -1,7 +0,0 @@ | |||
1147 | 1 | # __openerp__.py | ||
1148 | 2 | { | ||
1149 | 3 | 'name': "Web Example", | ||
1150 | 4 | 'description': "Basic example of a (future) web module", | ||
1151 | 5 | 'category': 'Hidden', | ||
1152 | 6 | 'depends': ['base'], | ||
1153 | 7 | } | ||
1154 | 8 | 0 | ||
1155 | === removed file 'addons/web/doc/module/__openerp__.py.1.diff' | |||
1156 | --- addons/web/doc/module/__openerp__.py.1.diff 2012-12-05 13:28:54 +0000 | |||
1157 | +++ addons/web/doc/module/__openerp__.py.1.diff 1970-01-01 00:00:00 +0000 | |||
1158 | @@ -1,11 +0,0 @@ | |||
1159 | 1 | --- web_example/__openerp__.py | ||
1160 | 2 | +++ web_example/__openerp__.py | ||
1161 | 3 | @@ -1,7 +1,7 @@ | ||
1162 | 4 | # __openerp__.py | ||
1163 | 5 | { | ||
1164 | 6 | 'name': "Web Example", | ||
1165 | 7 | 'description': "Basic example of a (future) web module", | ||
1166 | 8 | 'category': 'Hidden', | ||
1167 | 9 | - 'depends': ['base'], | ||
1168 | 10 | + 'depends': ['web'], | ||
1169 | 11 | } | ||
1170 | 12 | 0 | ||
1171 | === removed file 'addons/web/doc/module/__openerp__.py.2.diff' | |||
1172 | --- addons/web/doc/module/__openerp__.py.2.diff 2012-12-05 13:28:54 +0000 | |||
1173 | +++ addons/web/doc/module/__openerp__.py.2.diff 1970-01-01 00:00:00 +0000 | |||
1174 | @@ -1,11 +0,0 @@ | |||
1175 | 1 | --- web_example/__openerp__.py | ||
1176 | 2 | +++ web_example/__openerp__.py | ||
1177 | 3 | @@ -1,7 +1,8 @@ | ||
1178 | 4 | # __openerp__.py | ||
1179 | 5 | { | ||
1180 | 6 | 'name': "Web Example", | ||
1181 | 7 | 'description': "Basic example of a (future) web module", | ||
1182 | 8 | 'category': 'Hidden', | ||
1183 | 9 | 'depends': ['web'], | ||
1184 | 10 | + 'js': ['static/src/js/first_module.js'], | ||
1185 | 11 | } | ||
1186 | 12 | 0 | ||
1187 | === removed file 'addons/web/doc/module/__openerp__.py.3.diff' | |||
1188 | --- addons/web/doc/module/__openerp__.py.3.diff 2012-12-05 13:28:54 +0000 | |||
1189 | +++ addons/web/doc/module/__openerp__.py.3.diff 1970-01-01 00:00:00 +0000 | |||
1190 | @@ -1,12 +0,0 @@ | |||
1191 | 1 | --- web_example/__openerp__.py | ||
1192 | 2 | +++ web_example/__openerp__.py | ||
1193 | 3 | @@ -1,8 +1,9 @@ | ||
1194 | 4 | # __openerp__.py | ||
1195 | 5 | { | ||
1196 | 6 | 'name': "Web Example", | ||
1197 | 7 | 'description': "Basic example of a (future) web module", | ||
1198 | 8 | 'category': 'Hidden', | ||
1199 | 9 | 'depends': ['web'], | ||
1200 | 10 | + 'data': ['web_example.xml'], | ||
1201 | 11 | 'js': ['static/src/js/first_module.js'], | ||
1202 | 12 | } | ||
1203 | 13 | 0 | ||
1204 | === removed file 'addons/web/doc/module/__openerp__.py.4.diff' | |||
1205 | --- addons/web/doc/module/__openerp__.py.4.diff 2012-12-05 13:28:54 +0000 | |||
1206 | +++ addons/web/doc/module/__openerp__.py.4.diff 1970-01-01 00:00:00 +0000 | |||
1207 | @@ -1,13 +0,0 @@ | |||
1208 | 1 | --- web_example/__openerp__.py | ||
1209 | 2 | +++ web_example/__openerp__.py | ||
1210 | 3 | @@ -1,9 +1,10 @@ | ||
1211 | 4 | # __openerp__.py | ||
1212 | 5 | { | ||
1213 | 6 | 'name': "Web Example", | ||
1214 | 7 | 'description': "Basic example of a (future) web module", | ||
1215 | 8 | 'category': 'Hidden', | ||
1216 | 9 | 'depends': ['web'], | ||
1217 | 10 | 'data': ['web_example.xml'], | ||
1218 | 11 | 'js': ['static/src/js/first_module.js'], | ||
1219 | 12 | + 'css': ['static/src/css/web_example.css'], | ||
1220 | 13 | } | ||
1221 | 14 | 0 | ||
1222 | === removed file 'addons/web/doc/module/__openerp__.py.5.diff' | |||
1223 | --- addons/web/doc/module/__openerp__.py.5.diff 2012-12-05 13:28:54 +0000 | |||
1224 | +++ addons/web/doc/module/__openerp__.py.5.diff 1970-01-01 00:00:00 +0000 | |||
1225 | @@ -1,14 +0,0 @@ | |||
1226 | 1 | --- web_example/__openerp__.py | ||
1227 | 2 | +++ web_example/__openerp__.py | ||
1228 | 3 | @@ -1,10 +1,11 @@ | ||
1229 | 4 | # __openerp__.py | ||
1230 | 5 | { | ||
1231 | 6 | 'name': "Web Example", | ||
1232 | 7 | 'description': "Basic example of a (future) web module", | ||
1233 | 8 | 'category': 'Hidden', | ||
1234 | 9 | 'depends': ['web'], | ||
1235 | 10 | 'data': ['web_example.xml'], | ||
1236 | 11 | 'js': ['static/src/js/first_module.js'], | ||
1237 | 12 | 'css': ['static/src/css/web_example.css'], | ||
1238 | 13 | + 'qweb': ['static/src/xml/web_example.xml'], | ||
1239 | 14 | } | ||
1240 | 15 | 0 | ||
1241 | === added file 'addons/web/doc/module/series' | |||
1242 | --- addons/web/doc/module/series 1970-01-01 00:00:00 +0000 | |||
1243 | +++ addons/web/doc/module/series 2013-02-18 15:08:21 +0000 | |||
1244 | @@ -0,0 +1,27 @@ | |||
1245 | 1 | 0 | ||
1246 | 2 | 2 | ||
1247 | 3 | 3 | ||
1248 | 4 | 4 | ||
1249 | 5 | 5 | ||
1250 | 6 | 6 | ||
1251 | 7 | 8 | ||
1252 | 8 | 9 | ||
1253 | 9 | 10 | ||
1254 | 10 | 11 | ||
1255 | 11 | 12 | ||
1256 | 12 | 14 | ||
1257 | 13 | 15 | ||
1258 | 14 | 16 | ||
1259 | 15 | 17 | ||
1260 | 16 | 18 | ||
1261 | 17 | 19 | ||
1262 | 18 | 20 | ||
1263 | 19 | 21 | ||
1264 | 20 | 22 | ||
1265 | 21 | 23 | ||
1266 | 22 | 24 | ||
1267 | 23 | 25 | ||
1268 | 24 | 26 | ||
1269 | 25 | 27 | ||
1270 | 26 | 28 | ||
1271 | 27 | 29 | ||
1272 | 0 | 28 | ||
1273 | === removed directory 'addons/web/doc/module/static' | |||
1274 | === removed directory 'addons/web/doc/module/static/src' | |||
1275 | === removed directory 'addons/web/doc/module/static/src/css' | |||
1276 | === removed file 'addons/web/doc/module/static/src/css/web_example.css' | |||
1277 | --- addons/web/doc/module/static/src/css/web_example.css 2012-12-05 13:28:54 +0000 | |||
1278 | +++ addons/web/doc/module/static/src/css/web_example.css 1970-01-01 00:00:00 +0000 | |||
1279 | @@ -1,6 +0,0 @@ | |||
1280 | 1 | .openerp .oe_web_example { | ||
1281 | 2 | color: white; | ||
1282 | 3 | background-color: black; | ||
1283 | 4 | height: 100%; | ||
1284 | 5 | font-size: 400%; | ||
1285 | 6 | } | ||
1286 | 7 | 0 | ||
1287 | === removed file 'addons/web/doc/module/static/src/css/web_example.css.1.diff' | |||
1288 | --- addons/web/doc/module/static/src/css/web_example.css.1.diff 2012-12-05 13:28:54 +0000 | |||
1289 | +++ addons/web/doc/module/static/src/css/web_example.css.1.diff 1970-01-01 00:00:00 +0000 | |||
1290 | @@ -1,17 +0,0 @@ | |||
1291 | 1 | --- web_example/static/src/css/web_example.css | ||
1292 | 2 | +++ web_example/static/src/css/web_example.css | ||
1293 | 3 | @@ -1,6 +1,13 @@ | ||
1294 | 4 | .openerp .oe_web_example { | ||
1295 | 5 | color: white; | ||
1296 | 6 | background-color: black; | ||
1297 | 7 | height: 100%; | ||
1298 | 8 | - font-size: 400%; | ||
1299 | 9 | } | ||
1300 | 10 | +.openerp .oe_web_example h4 { | ||
1301 | 11 | + margin: 0; | ||
1302 | 12 | + font-size: 200%; | ||
1303 | 13 | +} | ||
1304 | 14 | +.openerp .oe_web_example.oe_web_example_started .oe_web_example_start button, | ||
1305 | 15 | +.openerp .oe_web_example.oe_web_example_stopped .oe_web_example_stop button { | ||
1306 | 16 | + display: none | ||
1307 | 17 | +} | ||
1308 | 18 | 0 | ||
1309 | === removed directory 'addons/web/doc/module/static/src/js' | |||
1310 | === removed file 'addons/web/doc/module/static/src/js/first_module.js' | |||
1311 | --- addons/web/doc/module/static/src/js/first_module.js 2012-12-05 13:28:54 +0000 | |||
1312 | +++ addons/web/doc/module/static/src/js/first_module.js 1970-01-01 00:00:00 +0000 | |||
1313 | @@ -1,2 +0,0 @@ | |||
1314 | 1 | // static/src/js/first_module.js | ||
1315 | 2 | console.log("Debug statement: file loaded"); | ||
1316 | 3 | 0 | ||
1317 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.1.diff' | |||
1318 | --- addons/web/doc/module/static/src/js/first_module.js.1.diff 2012-12-05 13:28:54 +0000 | |||
1319 | +++ addons/web/doc/module/static/src/js/first_module.js.1.diff 1970-01-01 00:00:00 +0000 | |||
1320 | @@ -1,8 +0,0 @@ | |||
1321 | 1 | --- web_example/static/src/js/first_module.js | ||
1322 | 2 | +++ web_example/static/src/js/first_module.js | ||
1323 | 3 | @@ -1,2 +1,4 @@ | ||
1324 | 4 | // static/src/js/first_module.js | ||
1325 | 5 | -console.log("Debug statement: file loaded"); | ||
1326 | 6 | +openerp.web_example = function (instance) { | ||
1327 | 7 | + console.log("Module loaded"); | ||
1328 | 8 | +}; | ||
1329 | 9 | 0 | ||
1330 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.2.diff' | |||
1331 | --- addons/web/doc/module/static/src/js/first_module.js.2.diff 2012-12-05 13:28:54 +0000 | |||
1332 | +++ addons/web/doc/module/static/src/js/first_module.js.2.diff 1970-01-01 00:00:00 +0000 | |||
1333 | @@ -1,11 +0,0 @@ | |||
1334 | 1 | --- web_example/static/src/js/first_module.js | ||
1335 | 2 | +++ web_example/static/src/js/first_module.js | ||
1336 | 3 | @@ -1,4 +1,7 @@ | ||
1337 | 4 | // static/src/js/first_module.js | ||
1338 | 5 | openerp.web_example = function (instance) { | ||
1339 | 6 | - console.log("Module loaded"); | ||
1340 | 7 | + instance.web.client_actions.add('example.action', 'instance.web_example.action'); | ||
1341 | 8 | + instance.web_example.action = function (parent, action) { | ||
1342 | 9 | + console.log("Executed the action", action); | ||
1343 | 10 | + }; | ||
1344 | 11 | }; | ||
1345 | 12 | 0 | ||
1346 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.3.diff' | |||
1347 | --- addons/web/doc/module/static/src/js/first_module.js.3.diff 2012-12-05 13:28:54 +0000 | |||
1348 | +++ addons/web/doc/module/static/src/js/first_module.js.3.diff 1970-01-01 00:00:00 +0000 | |||
1349 | @@ -1,18 +0,0 @@ | |||
1350 | 1 | --- web_example/static/src/js/first_module.js | ||
1351 | 2 | +++ web_example/static/src/js/first_module.js | ||
1352 | 3 | @@ -1,7 +1,11 @@ | ||
1353 | 4 | // static/src/js/first_module.js | ||
1354 | 5 | openerp.web_example = function (instance) { | ||
1355 | 6 | - instance.web.client_actions.add('example.action', 'instance.web_example.action'); | ||
1356 | 7 | - instance.web_example.action = function (parent, action) { | ||
1357 | 8 | - console.log("Executed the action", action); | ||
1358 | 9 | - }; | ||
1359 | 10 | + instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
1360 | 11 | + instance.web_example.Action = instance.web.Widget.extend({ | ||
1361 | 12 | + className: 'oe_web_example', | ||
1362 | 13 | + start: function () { | ||
1363 | 14 | + this.$el.text("Hello, world!"); | ||
1364 | 15 | + return this._super(); | ||
1365 | 16 | + } | ||
1366 | 17 | + }); | ||
1367 | 18 | }; | ||
1368 | 19 | 0 | ||
1369 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.4.diff' | |||
1370 | --- addons/web/doc/module/static/src/js/first_module.js.4.diff 2012-12-05 13:28:54 +0000 | |||
1371 | +++ addons/web/doc/module/static/src/js/first_module.js.4.diff 1970-01-01 00:00:00 +0000 | |||
1372 | @@ -1,15 +0,0 @@ | |||
1373 | 1 | --- web_example/static/src/js/first_module.js | ||
1374 | 2 | +++ web_example/static/src/js/first_module.js | ||
1375 | 3 | @@ -1,11 +1,7 @@ | ||
1376 | 4 | // static/src/js/first_module.js | ||
1377 | 5 | openerp.web_example = function (instance) { | ||
1378 | 6 | instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
1379 | 7 | instance.web_example.Action = instance.web.Widget.extend({ | ||
1380 | 8 | + template: 'web_example.action' | ||
1381 | 9 | - className: 'oe_web_example', | ||
1382 | 10 | - start: function () { | ||
1383 | 11 | - this.$el.text("Hello, world!"); | ||
1384 | 12 | - return this._super(); | ||
1385 | 13 | - } | ||
1386 | 14 | }); | ||
1387 | 15 | }; | ||
1388 | 16 | 0 | ||
1389 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.5.diff' | |||
1390 | --- addons/web/doc/module/static/src/js/first_module.js.5.diff 2012-12-05 13:28:54 +0000 | |||
1391 | +++ addons/web/doc/module/static/src/js/first_module.js.5.diff 1970-01-01 00:00:00 +0000 | |||
1392 | @@ -1,23 +0,0 @@ | |||
1393 | 1 | --- web_example/static/src/js/first_module.js | ||
1394 | 2 | +++ web_example/static/src/js/first_module.js | ||
1395 | 3 | @@ -1,7 +1,19 @@ | ||
1396 | 4 | // static/src/js/first_module.js | ||
1397 | 5 | openerp.web_example = function (instance) { | ||
1398 | 6 | instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
1399 | 7 | instance.web_example.Action = instance.web.Widget.extend({ | ||
1400 | 8 | - template: 'web_example.action' | ||
1401 | 9 | + template: 'web_example.action', | ||
1402 | 10 | + events: { | ||
1403 | 11 | + 'click .oe_web_example_start button': 'watch_start', | ||
1404 | 12 | + 'click .oe_web_example_stop button': 'watch_stop' | ||
1405 | 13 | + }, | ||
1406 | 14 | + watch_start: function () { | ||
1407 | 15 | + this.$el.addClass('oe_web_example_started') | ||
1408 | 16 | + .removeClass('oe_web_example_stopped'); | ||
1409 | 17 | + }, | ||
1410 | 18 | + watch_stop: function () { | ||
1411 | 19 | + this.$el.removeClass('oe_web_example_started') | ||
1412 | 20 | + .addClass('oe_web_example_stopped'); | ||
1413 | 21 | + }, | ||
1414 | 22 | }); | ||
1415 | 23 | }; | ||
1416 | 24 | 0 | ||
1417 | === removed file 'addons/web/doc/module/static/src/js/first_module.js.6.diff' | |||
1418 | --- addons/web/doc/module/static/src/js/first_module.js.6.diff 2012-12-05 13:28:54 +0000 | |||
1419 | +++ addons/web/doc/module/static/src/js/first_module.js.6.diff 1970-01-01 00:00:00 +0000 | |||
1420 | @@ -1,55 +0,0 @@ | |||
1421 | 1 | --- web_example/static/src/js/first_module.js | ||
1422 | 2 | +++ web_example/static/src/js/first_module.js | ||
1423 | 3 | @@ -1,19 +1,52 @@ | ||
1424 | 4 | // static/src/js/first_module.js | ||
1425 | 5 | openerp.web_example = function (instance) { | ||
1426 | 6 | instance.web.client_actions.add('example.action', 'instance.web_example.Action'); | ||
1427 | 7 | instance.web_example.Action = instance.web.Widget.extend({ | ||
1428 | 8 | template: 'web_example.action', | ||
1429 | 9 | events: { | ||
1430 | 10 | 'click .oe_web_example_start button': 'watch_start', | ||
1431 | 11 | 'click .oe_web_example_stop button': 'watch_stop' | ||
1432 | 12 | }, | ||
1433 | 13 | + init: function () { | ||
1434 | 14 | + this._super.apply(this, arguments); | ||
1435 | 15 | + this._start = null; | ||
1436 | 16 | + this._watch = null; | ||
1437 | 17 | + }, | ||
1438 | 18 | + update_counter: function () { | ||
1439 | 19 | + var h, m, s; | ||
1440 | 20 | + // Subtracting javascript dates returns the difference in milliseconds | ||
1441 | 21 | + var diff = new Date() - this._start; | ||
1442 | 22 | + s = diff / 1000; | ||
1443 | 23 | + m = Math.floor(s / 60); | ||
1444 | 24 | + s -= 60*m; | ||
1445 | 25 | + h = Math.floor(m / 60); | ||
1446 | 26 | + m -= 60*h; | ||
1447 | 27 | + this.$('.oe_web_example_timer').text( | ||
1448 | 28 | + _.str.sprintf("%02d:%02d:%02d", h, m, s)); | ||
1449 | 29 | + }, | ||
1450 | 30 | watch_start: function () { | ||
1451 | 31 | this.$el.addClass('oe_web_example_started') | ||
1452 | 32 | .removeClass('oe_web_example_stopped'); | ||
1453 | 33 | + this._start = new Date(); | ||
1454 | 34 | + // Update the UI to the current time | ||
1455 | 35 | + this.update_counter(); | ||
1456 | 36 | + // Update the counter at 30 FPS (33ms/frame) | ||
1457 | 37 | + this._watch = setInterval( | ||
1458 | 38 | + this.proxy('update_counter'), | ||
1459 | 39 | + 33); | ||
1460 | 40 | }, | ||
1461 | 41 | watch_stop: function () { | ||
1462 | 42 | + clearInterval(this._watch); | ||
1463 | 43 | + this.update_counter(); | ||
1464 | 44 | + this._start = this._watch = null; | ||
1465 | 45 | this.$el.removeClass('oe_web_example_started') | ||
1466 | 46 | .addClass('oe_web_example_stopped'); | ||
1467 | 47 | }, | ||
1468 | 48 | + destroy: function () { | ||
1469 | 49 | + if (this._watch) { | ||
1470 | 50 | + clearInterval(this._watch); | ||
1471 | 51 | + } | ||
1472 | 52 | + this._super(); | ||
1473 | 53 | + } | ||
1474 | 54 | }); | ||
1475 | 55 | }; | ||
1476 | 56 | 0 | ||
1477 | === removed directory 'addons/web/doc/module/static/src/xml' | |||
1478 | === removed file 'addons/web/doc/module/static/src/xml/web_example.xml' | |||
1479 | --- addons/web/doc/module/static/src/xml/web_example.xml 2012-12-05 13:28:54 +0000 | |||
1480 | +++ addons/web/doc/module/static/src/xml/web_example.xml 1970-01-01 00:00:00 +0000 | |||
1481 | @@ -1,11 +0,0 @@ | |||
1482 | 1 | <templates> | ||
1483 | 2 | <div t-name="web_example.action" class="oe_web_example oe_web_example_stopped"> | ||
1484 | 3 | <h4 class="oe_web_example_timer">00:00:00</h4> | ||
1485 | 4 | <p class="oe_web_example_start"> | ||
1486 | 5 | <button type="button">Start</button> | ||
1487 | 6 | </p> | ||
1488 | 7 | <p class="oe_web_example_stop"> | ||
1489 | 8 | <button type="button">Stop</button> | ||
1490 | 9 | </p> | ||
1491 | 10 | </div> | ||
1492 | 11 | </templates> | ||
1493 | 12 | 0 | ||
1494 | === added file 'addons/web/doc/module/testing_0.png' | |||
1495 | 13 | Binary files addons/web/doc/module/testing_0.png 1970-01-01 00:00:00 +0000 and addons/web/doc/module/testing_0.png 2013-02-18 15:08:21 +0000 differ | 1 | Binary files addons/web/doc/module/testing_0.png 1970-01-01 00:00:00 +0000 and addons/web/doc/module/testing_0.png 2013-02-18 15:08:21 +0000 differ |
1496 | === added file 'addons/web/doc/module/testing_1.png' | |||
1497 | 14 | Binary files addons/web/doc/module/testing_1.png 1970-01-01 00:00:00 +0000 and addons/web/doc/module/testing_1.png 2013-02-18 15:08:21 +0000 differ | 2 | Binary files addons/web/doc/module/testing_1.png 1970-01-01 00:00:00 +0000 and addons/web/doc/module/testing_1.png 2013-02-18 15:08:21 +0000 differ |
1498 | === removed file 'addons/web/doc/module/web_example.xml' | |||
1499 | --- addons/web/doc/module/web_example.xml 2012-12-05 13:28:54 +0000 | |||
1500 | +++ addons/web/doc/module/web_example.xml 1970-01-01 00:00:00 +0000 | |||
1501 | @@ -1,11 +0,0 @@ | |||
1502 | 1 | <!-- web_example/web_example.xml --> | ||
1503 | 2 | <openerp> | ||
1504 | 3 | <data> | ||
1505 | 4 | <record model="ir.actions.client" id="action_client_example"> | ||
1506 | 5 | <field name="name">Example Client Action</field> | ||
1507 | 6 | <field name="tag">example.action</field> | ||
1508 | 7 | </record> | ||
1509 | 8 | <menuitem action="action_client_example" | ||
1510 | 9 | id="menu_client_example"/> | ||
1511 | 10 | </data> | ||
1512 | 11 | </openerp> | ||
1513 | 12 | 0 | ||
1514 | === modified file 'addons/web/doc/testing.rst' | |||
1515 | --- addons/web/doc/testing.rst 2012-11-16 11:10:43 +0000 | |||
1516 | +++ addons/web/doc/testing.rst 2013-02-18 15:08:21 +0000 | |||
1517 | @@ -327,6 +327,8 @@ | |||
1518 | 327 | :js:attr:`~TestOptions.rpc`, and can be one of two modes: ``mock`` or | 327 | :js:attr:`~TestOptions.rpc`, and can be one of two modes: ``mock`` or |
1519 | 328 | ``rpc``. | 328 | ``rpc``. |
1520 | 329 | 329 | ||
1521 | 330 | .. _testing-rpc-mock: | ||
1522 | 331 | |||
1523 | 330 | Mock RPC | 332 | Mock RPC |
1524 | 331 | ++++++++ | 333 | ++++++++ |
1525 | 332 | 334 | ||
1526 | 333 | 335 | ||
1527 | === modified file 'addons/web/doc/widget.rst' | |||
1528 | --- addons/web/doc/widget.rst 2012-12-12 16:57:39 +0000 | |||
1529 | +++ addons/web/doc/widget.rst 2013-02-18 15:08:21 +0000 | |||
1530 | @@ -93,7 +93,7 @@ | |||
1531 | 93 | Any override to :js:func:`~openerp.web.Widget.renderElement` which | 93 | Any override to :js:func:`~openerp.web.Widget.renderElement` which |
1532 | 94 | does not call its ``_super`` **must** call | 94 | does not call its ``_super`` **must** call |
1533 | 95 | :js:func:`~openerp.web.Widget.setElement` with whatever it | 95 | :js:func:`~openerp.web.Widget.setElement` with whatever it |
1535 | 96 | generated or the widget's behavior is undefined.r | 96 | generated or the widget's behavior is undefined. |
1536 | 97 | 97 | ||
1537 | 98 | .. note:: | 98 | .. note:: |
1538 | 99 | 99 |
was merged into trunk, so cancelling this proposal