Availability |
Odoo Online
Odoo.sh
On Premise
|
Lines of code | 1350 |
Technical Name |
web_progress |
License | LGPL-3 |
Website | https://github.com/gmarczynski/odoo-web-progress |
Versions | 16.0 15.0 11.0 12.0 13.0 14.0 |
Dynamic Progress Bar
Progress bar for Odoo waiting screen, possibility to cancel an ongoing operation and a system tray menu for all operations in progress.
web_progress exists for Odoo 11.0, 12.0, 13.0, 14.0, 15.0 (CE and EE).
Author: Grzegorz Marczyński
License: LGPL-3.
Copyright © 2023 Grzegorz Marczyński
Features
- progress reporting for all standard Odoo import and export operations
- system tray menu that lists ongoing operations initiated by the logged user (all operations visible to Administrator)
- support for all operations initiated through UI and executed by planned activities (cron)
- generator-like method to simply add progress reporting to any iteration (support for sub-iterations)
For developers
Typically when your code executes any long-term operation there is a loop over a collection
in
your
code.
In order to report progress of the operation, wrap the collection
with self.web_progress_iter(collection, msg="Message")
or,
if the collection
is self
(or other recordset),
use a simpler version self.with_progress("Message")
Say, your operation's main method looks as follows:
@api.multi def action_operation(self): for rec in self: rec.do_somethig()
then a progress-reporting-ready version would be:
@api.multi def action_operation(self): for rec in self.web_progress_iter(self, msg="Message"): rec.do_something()
or a simpler version for recordsets:
@api.multi def action_operation(self): for rec in self.with_progress(msg="Message"): rec.do_something()
Progress tracking may be added to sub-operations as well:
@api.multi def action_operation(self): for rec in self.with_progress(msg="Message"): lines = rec.get_lines() for line in lines.with_progress("Sub-operation") line.do_something()
Release Notes
2.0 - 2023-01-03- new functionality and fixes:- add styles (standard, simple, nyan cat)
- make the progress bar appear directly when the screen becomes blocked
- keep basic progress functionality even if long polling is disabled or cease to work
- fix import of o2m fields for Odoo v13.0 and v14.0
- support Odoo v15.0
- fix deadlock on bus.bus garbage collection
- fix deadlock on access to res.users
- do not animate but set the progress bar going backwards
- estimated time left / total
- refactor global progress data
- change progress template name to avoid clash with progressbar widget
- remove unecessary dependency on multiprocessing
- fix memory leak in time-tracking internal data
Adding progress tracking to your code
Prerequisites
Progress reporting uses longpolling to send progress data from backend to web client, so make sure that the longpolling is operational before testing this module.
Simple case
Typically when your code executes any long-term operation there is a loop over a collection in your code.
In order to report progress of the operation, wrap the collection with self.web_progress_iter(collection, msg="Message")
Say, your operation's main method looks as follows:
@api.multi def action_operation(self): for rec in self: rec.do_somethig()
Then a progress-reporting-ready version would be:
@api.multi def action_operation(self): for rec in self.web_progress_iter(self, msg="Message"): rec.do_something()
or a simpler version for recordsets:
@api.multi def action_operation(self): for rec in self.with_progress(msg="Message"): rec.do_something()
Progress tracking may be added to sub-operations as well:
@api.multi def action_operation(self): for rec in self.with_progress(msg="Message"): lines = rec.get_lines() for line in lines.with_progress("Sub-operation") line.do_something()
Advanced case
This module adds methods web_progress_iter and with_progress to every Odoo model. The only difference between these methods is that web_progress_iter requires as its first parameter a collection to iterate upon and with_progress iterates always on self.
Both methods accept the following optional parameters:
- msg (str): an operation description, the message to be shown in the progress report,
- total (int): if provided, will be used as a length of the given collection, so len(collection) will never be called, which is essential when tracking progress of generators (default is None, i.e. len will be called),
- cancellable (bool): whether cancelling the operation should be possible, i.e visible button "Cancel" (default is True),
- log_level (str): which log level shall be used when logging progress (default is "info").
@api.multi def action_operation(self, data, length): for row in self.web_progress_iter(data, total=length, msg="Message", cancellable=True, log_level="debug"): self.do_something(row)
Another approach
You can also add iteration progress reporting to any recordset by adding progress_iter=True to its context.
FAQ
In this section you will find answers to the common questions concerning progress reporting implemented in web_progress module.
How to report a problem or ask a question?
Please use the issue tracker of our GitHub repository to report problems or ask questions. You will find it here.
How the progress reporting works?
...
How each operation is identified?
- Web client injects a unique progress_code (UUID) into the context of every RPC call towards backend.
- Both web_progress_iter and with_progress convert the given collection (or generator) into an instance of a generator-like class that uses a progress_code from context to perform progress tracking while your code iterates upon the collection.
- Sheduled (cron) actions have their progress_code injected into the context by scheduler prior to their execution.
How often the progress is reported?
For each progress_code (i.e. a unique operation) the first interation (the first element) of the collection wrapped with web_progress_iter or with_progress is reported to the web client (via longpolling).
After that, the progress is reported in intervals of minimum 5 seconds (i.e. any access to any wrapped collection more than 5 seconds after the last reported progress is reported).
Also the final iteration (the last element) of the main wrapped collection (on the top-level) is reported.
What is the overhead of progress reporting?
...
How the operation cancelling works?
...
How multi-level progress reporting works?
...
Is the current transaction commited to make progress visible?
No. Progress reporting uses a fresh transaction for each progress report and cancelled operation verification; therefore, the main transation stays untouched and in total isolation.
However, it should be noted that since progress report records and longpolling messages are commited into the database, even if the main transaction is still not commited, the main transaction shall never inspect or change those records in order to avoid inter-transactional conflicts (update-in-parallel exceptions).
Is it possible to put an ongoing operation into background?
Yes, by pressing F5. Actually this is a standard Odoo behaviour that any long-term operation may be put into background by pressing F5. The difference here is that, thanks to system tray menu, user has possibility to follow the progress of ongoing background operations and to cancel them.
Beware that putting an operation to the background makes it impossible to interact further with the user after the operation is finished. So this is OK for data imports (unless there are import errors) and this is definitely not OK for data exports (or reports) that let the user download a generated file after the export operation is finished.
Does progress reporting work with reports?
Yes, you can iterate over the wrapped collections in QWeb reports and the progress will be visible to the user.
Please log in to comment on this module
Report comment
Any abuse of this reporting system will be penalizedWorks great
Hello, I have just installed your app on a demo setup (Odoo 12 enterprise) and works very nice. But I noticed there is no option to "push" the process to background. Only "cancel" the process. I can suggest you add another button "move to background" next to cancel. Now somebody can decide to "wait" until it's ready or put it to background so you get the screen back and do other things. In the top bar, we now have the icon where we can follow progress. But in your current version, this is useless. Because when you start e.g. an import, the black overlay screen just stay in front so I can not click and see that icon in top bar. Being able to move it to background gives the user back freedom to do other tasks while your progress is available in a single click in top bar. Thanks for your great app! I hope you can put my idea in a next update!
Re: Works great
Hi, Thank you for comment and your suggestion. I thought about the "Put to background" button, but technically this is not that obvious how should it be handled. For the moment you can just press F5 to refresh the page and you can continue to work and even run another import, if you like. The progress of all operations will be visible in the tray menu next to the unread messages icon. Just beware of the number of workers in your configuration, because each long-term operation occupies one worker, so make sure that you leave at least one for the UI operations. Good luck with your Odoo adventure!
Doesn't work. Great idea, very disappointed :(
I have installed numerous aftermarket apps successfully, but failed twice with this one. It installs, but doesn't work.
Re: Doesn't work. Great idea, very disappointed :(
Please give some more details of how it does not work (Odoo ver.? Odoo config? How do you test it?). Do you have longpolling working correctly?
Odoo crashes when loading the home screen after I installed this: Uncaught Error: QWeb2: Template 'web_progress.ProgressMenu' not found
Template 'web_progress.ProgressMenu' not found
it worked well in production server, but in test inviroment i tack a backup from the db i get this errpr Uncaught Error: QWeb2: Template 'web_progress.ProgressMenu' not found