Before this commit: a notification asking to reload the current window
appeared as soon as the server detected a change in one of the assets
bundles, even on first load.
To fix this problem and make the feature more meaningful, it has been
decided to only notify the client when the server version (not the
bundle version) is outdated (i.e. on database upgrades, when the changes
in the code are actually relevant).
closesodoo/odoo#82032
X-original-commit: a3b5a9d715be6a93c7f2859074b916f3249f97c3
Signed-off-by: Antony Lesuisse <al@odoo.com>
Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
* = auth_signup, calendar, im_livechat, snailmail_account, survey, test_mail,
web_editor, website_crm_iap_reveal, website_livechat
The aim of this PR is to improve/fix various flaws and limitation of the current
API, to make it easier to use and more efficient.
Notification are now defined with 3 distinct parts:
- the channel determines which client(s) should receive it
- the type determines how it should be handled
- the payload determines any extra information helpful for handling it
Channel
=======
Business code
-------------
- Record channel is introduced for ease of subscribing to and sending
notifications to specific partners, channels, documents, ...
- String channel is still supported (but it is converted internally to the tuple
channel).
- Tuple channel is still supported without any change (but should be avoided
whenever possible due to its complex syntax).
The channel is no longer sent to the client. When the channel was used for
business purpose, the information it contained has been moved into either the
new type, or the payload itself.
Technical note
--------------
All channels are now internally converted to the tuple (db, ...) channel, which
is necessary for the platform code (saas/sh).
Internally, the bus.bus table is not changed, type and payload are grouped
together into what was (and still is) called message.
Type
====
Type is introduced to uniformize the way notifications are sent and handled.
All existing notifications already had some kind of manually-built type in them.
This is now officially supported at the bus API.
In client code this will allow (to be done in future commits) to register one
handler per specific type, instead of having to iterate and to filter all
received notifications on every handler.
Payload
=======
Payload (ex message) did not change, it can still be anything depending on
business needs.
Few adaptations:
- When the type was included on the payload, the type has been moved to the new
type parameter.
- When the channel was used in business code, its data has been copied into the
payload.
task-1891151
closesodoo/odoo#79201
X-original-commit: 543af27c7d6836ffac9e80ff8490b6ddbd849221
Related: odoo/enterprise#21998
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit prepares the ground for the collaborative feature.
Before this commit, it was impossible to have different channels for
each tabs. In collaboration, multiples tabs could listen to differents set
of channels.
Example:
One tab X could be subscribed to channel [a, b] and tab Y on channel
[a, b] and a tab Z on [a, c].
Before this commit, only the channels of the master tab were
listened. So in this case it was either [a, b] or [a, c] depending on
which tab is the master.
So either channel b or channel c were not listened depending on which tab
is the master.
Now, each time a tab listens or stops listens to a channel, the
master tab listen all channels for all tabs.
task-2497931
odoo pr: 75768
Part-of: odoo/odoo#75768
Previously, when killing the server, the longpolling bus stopped but
didn't start polling again after a few seconds, this was caused by the
fact that ConnectionLostError wasn't treated like a legacy error and
remapped to an object with a message, meaning it didn't trigger
guardedCatch callbacks.
Since ConnectionLostErrors should be handled much the same way as
RPCError when interacting with legacy code this commit simply adds
ConnectionLostError in the same places we already have RPCError during
error handling of legacy errors, but delegates behaviour to the new
lostConnectionHandler when appropriate.
closesodoo/odoo#74530
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
A number of functions from `web.test_utils` have been deprecated at
the module root and should be called through submodules.
Fix a bunch of remaining cases. Also add a few missing `await`s on
`triggerMouseEvent` calls. Don't bother rewriting the imports in
unpacking style as for most updating the imports is unnecessary. Do so
for `field_one2many_tests.js` where we have to rewrite the imports
anyway:
* recursively import controlPanel, createView, mock.patch and
mock.unpatch
* remove the aliasing of controlPanel to cpHelpers
Some services are coupled with a Component. Usually the service
handles the state of the system, and the Component displays or uses it.
To enable the communication between the service and the component
while making it private, the services should add themselves their
Component in the relevant registry, with the proper means of communication
passed in props.
This mechanism relies on c1d49d494e0ae3a94b3943186eb6d1ebd7b98a6e
* bus, calendar
This commit changes the notification API and adapts codes that use it
Notification API before:
- create(...): number
- close(id: number, wait?: number)
Notification API now:
- add(...): RemoveCallback
closesodoo-dev/odoo#908
Related: odoo-dev/enterprise#158
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
This commit splits the 'getActionManagerTestConfig' helper into 2:
'setupWebClientServiceRegistry' and 'getActionManagerServerData'.
The first one is now automatically called by the 'createWebClient'
helper, as it properly setups the service registry with all services
required by the WebClient component.
The second one generates a few data (menus, actions, views...) that
can be used in tests. That helper is mainly useful for action tests
(formerly ActionManager tests) in web. With this refactoring, they
are no longer generated for each test in the whole codebase that
spawns a webclient, as before this commit.
closesodoo-dev/odoo#906
Related: odoo-dev/enterprise#161
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
This commit adapts the community codebase to the rewriting of the
/web application in owl.
Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Samuel Degueldre <sad@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Simon Genin (ges) <ges@odoo.com>
Co-authored-by: Francois (fge) <fge@odoo.com>
Co-authored-by: Michael Mattiello (mcm) <mcm@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais (lpe) <lpe@odoo.com>
Co-authored-by: Jorge Pinna Puissant <jpp@odoo.com>
Before this commit, it might happen that, in some situations,
with several tabs opened, the CrossTabBus called the longpolling
route repeatedly, thus slowing down the server, and freezing the
webclient.
The issue was tricky to reproduce. It was a race-condition that
could occur when several tabs performed simultanous calls to
addChannel, while being unloaded or becoming mastertab in the
meantime (e.g. when opening/closing/refreshing several tabs
simultaneously).
This issue has been introduced by [1] which by mistake (probably)
made each tab calling itself the localStorage to update the list
of channels when it was notified that the list of channels in
the localStorage just changed. So if several tabs had a slightly
different list of channels at a given moment (e.g. at startup),
it might happen that they in turn, undo what another tab just
put in the localStorage, and thus produced an infinite loop of
localStorage writes and longpolling request aborts/calls.
The issue could be reproduced with the OCA module [2], which
performs several addChannel at webclient startup.
This commit restores this part of the code as it was initially
written in [3].
Closes#69067
opw~2502799
maybe opw~2451865 as well
[1] https://github.com/odoo/odoo/commit/6448420
[2] https://odoo-community.org/shop/product/web-notify-2670#attr=10773
[3] https://github.com/odoo/odoo/commit/38581f67236377daa767ca2216529a26b8708b00#diff-f6eccad21ae3543606ab8f97b8b097d015412caeaee2bf8cc928eb3ccabac9f5R149closesodoo/odoo#69777
X-original-commit: a52aa41d04330efb81090409ec7fbcbbedaca317
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit changes the way assets are declared in Odoo modules.
Before: assets were declared in template files. Template bundles were
generated from primary templates, so technically any qweb template could
have been called as an asset bundle, with the 't-call-assets' directive.
Being standard qweb templates, they had access to standard HTML tags
(script, link, with or without raw scripts or style definition), qweb
directives (t-call, t-raw, etc.) and could be inherited by other
templates.
Now: assets are defined in the module's manifest and generated by the
't-call-assets' directive.
More information on the new system can be found on the updated user
documentation (see the "JavaScript Reference" section).
Task: 2352566
Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Simon Genin <ges@odoo.com>
PURPOSE
Discuss notification needs to be changed for better UI.
SPECIFICATION
Improving design of discuss notification by using bg-info instead of bg-warning.
LINKS
PR https://github.com/odoo/odoo/pull/55542
Task-2308799
closesodoo/odoo#55542
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Use case:
When the server is restarted, the python is updated,
but some users may have an ongoing session in a browser tab
This may lead to code being unsynchronized and ultimately to some
odd bugs.
Purpose:
When we are in such a case, that is, the assets were recomputed
after a update of the code and a restart of the server by the request of another user,
notify connected users that assets have changed.
Then propose them to reload the page.
Known caveats:
- This is not a developer's feature.
Since assets computing is ORM cached, they have limited
opportunities to rebuild. Namely, the feature won't trigger
each time the JS has changed, rather, it will
when JS has changed AND the cache has been reset somehow (e.g. when the server is restarted).
- This not a portal/website feature either, but only in backend.
Business clients won't be notified that the JS has changed.
- While requests debug=assets do trigger a recomputing
of the *components* of bundles, they do not save a bundle
This means that the requests that sends the notification
cannot be debug=assets.
Task 2034462
closesodoo/odoo#39875
Signed-off-by: Mathieu Duckerts-Antoine <Polymorphe57@users.noreply.github.com>
This commit adapts tests following recent changes on the helpers.
The main change is that addMockEnvironment (and all functions using
it) are now async, as they need to wait for services to be started.
*bus,mail
This commit extracts the common basis of the env to use both in
the frontend and the backend. The public env now contains most of
the features that were previously (only) in the webclient env.
Moreover, the PublicRoot no longer uses the ServiceProviderMixin,
such that services are only deployed once, in the (public) env.
Owl components can now be defined in the website, and rely on a
properly built env. Legacy widgets still works as they access
services through the PublicRoot (via trigger_up) which redirects
those requests to the env.
Before this commit, the Notification is used but in Chrome Mobile
we can't use it outside a ServiceWorker.
After this commit, if the Notification Object produce
an error it will fallback to the old method do_notify()
Steps to reproduce:
* Open a Odoo instance with Chrome Mobile (e.g. with Demo user)
* In Chrome Mobile, accept to receive the "Native Browser Notification"
* Put Chrome Mobile in the background of Android (don't close it)
* Open another instance of the same Odoo somewhere else with another user (e.g. Admin)
* From Admin, send a direct message to Demo
* Resume Chrome Mobile to the foreground the you will see the traceback (BUG)
GitHub issue: odoo/odoo#34714
Ref:
https://bugs.chromium.org/p/chromium/issues/detail?id=481856closesodoo/odoo#51474
X-original-commit: ebe6731c583f9f4125272af3d8bdc4625e06de7c
Signed-off-by: Adrien Dieudonné (adr) <adr@odoo.com>
Signed-off-by: rfr-odoo <rfr-odoo@users.noreply.github.com>
Fix regression introduced with e0ed7b12ca
Issue without current commit:
When doing `abort` next updates from the bus are only received after the normal
timeout, which makes the interface unresponsive to updates during that amount of
time.
`abort` is for example called during `addChannel`, where it is specifically
documented that new updates are to be received immediately.
closesodoo/odoo#49355
X-original-commit: 888610e5e07794e000ef27edcb075cb45c1e2ccc
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
The title of notification is the author name escaped (for security
reasons).
if (message.hasAuthor()) {
title = _.escape(message.getAuthorName());
}
When forwarded to the system notification, it does not need to be
escaped though, as the system notification is not HTML based.
Without this patch, a user named "Bob's friend" sending a message was
creating a notification with the title "Bob's friend"
Unescaping the notification body just in case but the HTML of the body
in a mail.messages should be stripped by _notifyIncomingMessage.
Unescaping will just ignored unescaped characters and should do
nothing on messages not escaped.
Fixesodoo/odoo#24846closesodoo/odoo#44550
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Sink handling of JS logging, exceptions and websocket timeouts so
calls other than _wait_code_ok handle them somewhat properly: the
issue fixed by odoo/odoo#41231 passed because it occurred during
module loading, which happens during initial page loading (browser_js
> navigate_to > _websocket_wait_event), which ignored logs (and
exceptions though here it's a console.error log), and as a result
reported no failure (and would simply miss that specific test as well
as every test following it).
Also since ChromeBrowser treats console.error as an exception,
important messages should be logged atomically. Merge two consecutive
console.error into a single one at the loading of modules so we don't
just get an exception "error while loading foo.bar" without any of the
useful details.
That ChromeBrowser treats console.error as exception is also why the
new method gets a flag (to suppress this behaviour): in the case of
two console.error, upon encountering the first it's treated as an
error so we try to take a screenshot, which goes through the messages
in order to get the screenshot response, which encounters the second
console.error, which gets treated as an exception, which hides the
first error.
Instead, screenshotting (and more generally _websocket_wait_id) should
treat console.error as a regular logging call, probably.
Also run JS tests in debug=assets for easier debugging (ha!) and
improve formatting of exception object when receiving an exception:
* if we can get a description on an `exception` remote object just
print that, it's formatted to show the exception type, message &
traceback
* otherwise format the garbage that is an "ExceptionDetails" object
Before this commit, when navigating from test environment (e.g.
page reload), it crashed with following error:
`TypeError: Cannot convert undefined or null to object`
This error comes from mocked bus services in tests: even when they
have been destroyed, they handle the window event 'unload'. They
no longer have a parented parent, so `this.call()` returns
`undefined`, hence the crash.
This commit prevents mocked bus services to listen on window 'unload'
event. Tests must always simulate this window event by explicitly
calling the handler.
closesodoo/odoo#41378
X-original-commit: fd08d04f0a24fea52e7b668b90aec48b33d349a3
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
The im_support module was broken in 12.0 after bus refactorings between
11.0 and 12.0.
closesodoo/odoo#38838
X-original-commit: db37e0cedcd0da46bd57686a076a8165e60d6c3b
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Co-authored-by: @alexkuhn
Before this commit, there could be an infinite loop when changing
the chat window state of a document chat window.
This is caused when mutiple tabs overwrite the chat window state
with a different value everytime, resulting to an infinite loop.
Accross multiple tabs, `setItem` and `onStorage` are not synchronous.
That's why tabs should communicate through local storage events
instead of actual value in the local storage.
To illustrate the issue, suppose there are 2 tabs (T1 and T2) with
one document chat windows (C) and the following user interactions:
- T1 and T2 both have C open
- on T1, user folds C
- on T2, user folds C
Now let's add an example of local storage (LS) logics that could
apply from above example:
- T1 and T2 both have C open
- on T1, user folds C
[1] T1 writes 'C folded' in LS
- on T2, user folds C
[2] T2 writes 'C folded' in LS
[3] T2 detects 'C folded' in LS (from [1])
=> T2 writes 'C folded' in LS
[4] T1 detects 'C folded' in LS (from [2])
=> T1 writes 'C folded' in LS
[5] T1 detects 'C folded' in LS (from [3])
=> T1 writes 'C folded' in LS
[6] T2 detects 'C folded' in LS (from [4])
=> T2 writes 'C folded' in LS
etc...
This scenario could have been easily prevented by not writing on
local storage when the chat window state has not changed. However,
this wouldn't fix this scenario that also introduces an infinite
loop:
- T1 and T2 both have C open
- on T1, user folds C
[1] T1 writes 'C folded' in LS
- on T2, user folds C
[2] T2 writes 'C folded' in LS
- on T2, user unfolds C
[3] T2 writes 'C unfolded' in LS
[4] T2 detects 'C folded' in LS (from [1])
=> T2 writes 'C folded' in LS
[5] T1 detects 'C unfolded' in LS (from [3])
=> T1 writes 'C unfolded' in LS
[6] T2 detects 'C unfolded' in LS (from [5])
=> T2 writes 'C unfolded' in LS
[7] T1 detects 'C folded' in LS (from [4])
=> T1 writes 'C folded' in LS
[8] T2 detects 'C folded' in LS (from [7])
=> T2 writes 'C folded' in LS
[9] T1 detects 'C unfolded' in LS (from [6])
=> T1 writes 'C folded' in LS
etc...
This commit fixes the infinite loop issue:
- by turning local storage read during cross-tab communication into
local storage event read instead. This should prevent race
conditions based on read/write operations in local, since their
order is not guaranteed accros tabs.
- by isolating document chat window state to their own local
storage entry. This should prevent a tab from notifying a chat
window state that it didn't change, which may also result in
an infinite loop.
Some tests were adapted from the changes above. Also, some tests did
pass thanks to local storage being mocked by a ram storage: the
handler `_onStorage` should have been called, but it didn't because
it was registered on the actual local storage instead of the ram
storage. In order to make tests pass again, the following additional
changes were required:
- Cross-tab bus service now exports the unique tab ID with
`getTabId`.
- document thread entries in local storage now track the tab ID, so
that self-tab ignore their own local storage writes.
Task-Id 2034997
Closes#36177
According to MDN, HTMLMediaElement returns
> A Promise which is resolved when playback has been started, or is
> rejected if for any reason playback cannot be started.
>
> Note: Older browsers may not return a value from play().
Since un-resolved un-handled promises re-raise and trigger the crash
manager, this is extremely noticeable if the browser doesn't support
the media type or is not currently allowed to play
medias (e.g. configured to prevent auto-play).
This just avoids the error, but eventually it might be useful to
display a toast noting the user could allow sounds iff the rejection
reason is NotAllowedError. This fix would probably be implementable /
implemented on older revisions (which might have the issue, just not
as prominent as unhandledrejection is not hooked into the crash
manager).
closesodoo/odoo#33260
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
`this._id` is overriden by the crosstab_bus, so the event handlers
weren't unbound at destroy.
Manual forwardport of odoo/odoo#31578, as we need this for another
branch, in which it makes tests fail.
closesodoo/odoo#31579
Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
This commit is a refactoring of im_status management.
This commit also add im_status in two places, near the author in a mail thread and on each suggestion when using mentions.
A service to manage im_status will have multiple benefits here:
-centralise information, avoid to call the server multiple time for the same im_status
-update all im_status at once and keep consistency in display.
With this commit, the im_status updates are now done by rpc call.
Updates where previously made with the bus but this has some drawback,
since the bus will only give the information 50 seconds after the beginning of
the request, in the worst case, we van wait 2*50 seconds to get an update.
More than that, the im_status where only updates for pinned dm_chat. Dm chat
are synchronized cross tabs, making the use of the bus possible for this purpose.
Since we will need to display im_status not linked to dm_chat, the list to update
will be different from tab to tab making the use of bus difficult for this purpose.
Technical notes:
-im_search has been moved from bus to mail addons since it concerns mail.channel
-Update of an im_status should be reflected everywhere in the page.
Since im_status is a rendered template used in multiple widget, we should add
the correct logic to all concerened widget. The current solution is simple:
use a jquery selector to find every place where im_status is rendered.
-we add a new im_status: im_partner. This will indicate that that
the partner has no user linked to him, making it possible to avoid to ask
for status updates for this partner.
-The update will only be done when the tab is focused. (and will be done
asap once the tab get focus back)
With this commit, no push notification is sent to user when
to acknowledge that he just has accepted them. Also, on native
push notifications, the Odoo Bot icon now has a transparent
background.
Task-ID 1881001
This rev. introduces robust helpers to use in the JS tests suite to
interact with DOM and components, and starts using them (almost)
everywhere.
All the helpers are exposed though testUtils.js.
There are 2 kinds of helpers:
1. Assertions
-------------
* assert.containsNone, containsN, containsOnce check that the DOM
(or a specific part of the DOM) contains a `selector`. It
generates a correct error message automatically.
ex: assert.strictEqual(form.$('.o_form_editable'), 1, "msg");
-> assert.containsOnce(form, '.o_form_editable');
* assert.isVisible, isNotVisible check that the DOM has an element
visible or not. They also check that the element is actually in
the DOM (before most tests didn't verify this).
* assert.hasClass, doesNotHaveClass, hasAttrVAlue, check specific
properties of a DOM element, and also validate that it is
applied on a single existing DOM element (before most tests
didn't verify this).
ex: assert.notOk(form.$('button').hasClass('btn-primary'));
-> assert.doesNotHaveClass(form.$('button'), 'btn-primary');
2. Utilities
------------
The goal of the utilities is to centralize the definition of many
standard components and interactions, ensuring that when we
refactor the JS framework, we do not need to change all the tests.
Existing mock utilities (addMockEnvironment, intercept, path,
patchDate, unpatch and fieldsViewGet) are moved to
'testUtils.mock.*'.
Existing DOM utilities are moved to 'testUtils.dom.*'.
New dom utilities are created for opendDatePicker, click,
clickFirst and clickLast. Helper `click` verifies that there is
exactly 1 element visible in the DOM you click on, `clickFirst`
and `clickLast` verify that there are more than one element on the
DOM.
ex: form.$('button').click();
-> testUtils.dom.click(form.$('button'));
New Form utilities: (testUtils.form.*)
clickEdit, clickSave, clickCreate, clickDiscard, all clicks on
the control panel buttons of the form.
`reload` reloads the form data.
New modal, graph, kanban and pivot utils (testUtils.pivot.*,
testUtils.kanban.*, etc.).
New fields utils: (testUtils.fields.*)
* editInput, editSelect: allow to change the value of a field,
using a selector to identify it. They validate that the input
exists and trigger the change event automatically.
* editAndTrigger: allow to modify a field and trigger specific
events after the value change
* many2one (testUtils.fields.many2one.*)
clickOpenDropdown, clickHighlightedItem, clickItem,
searchAndClickItem: use a field name instead of a selector and
do all the complex mechanism to open, filter and highlight
many2one fields.
Joint work with aab, dam, ged, mge, svs and vsc.
`this._id` is overriden by the crosstab_bus, so the event handlers
weren't unbound at destroy.
closesodoo/odoo#31578
Signed-off-by: "Aaron Bohy (aab)" <aab@odoo.com>
Before this commit, there was no livechat menu when accessing it from
the customer URL, e.g. `http://mycompany.odoo.com/im_livechat/support/1`)
This is due to missing JS modules, such as the root widget.
Also, the crosstab polling directly requires the session module,
because the public root widget does not return the session module
from the OdooEvent `get_session`.
Task-ID 1885445
Co-authored-by: Mohammed Shekha <msh@openerp.com>
Before this commit, chat windows could not be sync'ed
between browser tabs for about 10 to 20 seconds.
This issue is caused by the implementation of the
crosstab longpolling, which uses a master-slave
architecture with a single tab being the master tab.
The master tab is responsible for performing the
longpolling RPC, so that it keeps a single HTTP request
for all Odoo tabs. Other tabs are synchronized through
the local storage.
When the master tab was closed, a new master tab election
must occur. However, this process was taking up to 20 seconds,
due to the tab waiting for their next tick on the local
storage to initiate a new election. The tick for a slave
tab is 10 seconds, and it may jumps a tick in case the master
tab is closed exactly before the tick, hence extending the
duration to 20 seconds.
This commit fixes the problem by ensuring that the tab
election for the longpolling is done right after the master
tab is closed. As a result, a new master tab should follow
right away.
Steps to reproduce:
1. open two tabs.
2. open a chat window in one tab: it opens in both tabs.
3. fold/unfold chat window in one tab: both tab should sync.
4. refresh both tabs.
5. fold/unfold chat window in one tab: both tab should not sync.
6. after 10 or 20 seconds, both tabs should again sync.
Task-ID 1911437
closesodoo/odoo#28925
Revision on bus refactoring: https://github.com/odoo/odoo/commit/6448420c5dd160470e465dee7729d19d8d5e7bab
Before this commit, when a user was disconnected for a very long
time, he would receive lots of chat notifications on his next login.
Here is an example of weird behaviour with this issue:
- User folds and unfolds a chat window 50 times
- User disconnects for more than 50 seconds
- User reconnects
==> the chat window rapidly folds and unfolds itself 50 times!
This issue comes from the fact that after 50 seconds without any
longpolling, the web client ignores the last tracked notification
and sents the ID `-1` to the server.
The web client always provides a notification ID to the server
on a `longpolling/poll`. Usually, the server returns all
notifications of the user with an ID greater than the provided ID.
There is an exception with ID `0`, in which all notifications since
the last connection of the user are returned.
The cause of the issue is a mismatch of the special notification
ID between the server and the web client. For the web client, the
ID `-1` is used for not tracking any notification, whereas the
server uses the ID `0` for this case. As a result, when the server
receives the value `-1`, it returns all notifications having an ID
greater than `-1`. In other words, it returns all notifications
related to this user, even the ones received long time ago!
This commit fixes the issue by enforcing the special notification ID
`0` on both the webclient and server.
Note that this logic is similar to 11.0:
- The webclient uses the ID `-1` most of the time to define 'untracked':
https://github.com/odoo/odoo/blob/11.0/addons/bus/static/src/js/bus.js#L154
- However, it passes the ID `0` to the server:
https://github.com/odoo/odoo/blob/11.0/addons/bus/static/src/js/bus.js#L193
If we use the cross tab, and the session has more than 50 seconds (or
does not exist), a remove is done in the init. The change trigger in
local storage causes the value of _lastNotificationID to become null.
This causes a loading error in the long poll.
This commit makes a lot of small improvements of the JS of mail and
related modules.
A. Mail Manager
---------------
im_support:
- [REF] Slightly more robust way to determine a support
message, so that it more reliably falls back on
default kind of message (i.e. support channel UUID
should be clearly set).
mail:
- [REF] Improved method names for readability purposes.
Some examples:
- `fetchFromServer` becomes `fetchMailStateFromServer`
- `_initialize{*}` becomes `_update{*}FromServer`
- `_isModerator` becomes `_isMyselfModerator`
- [REF] Use 'template' pattern design to make Include on
Mail Manager much more robust. In particular,
the flow is always as follow:
1. Initialize internal state.
2. Listen on buses.
3. Fetch mail data from server.
- [REF] Improved workflow for thread window workflow
(Shorter & more readable).
B. Mail Tests
-------------
- [REF] Thread Window Tests crashes with clean message when
there are some thread windows open before running the
tests.
C. (Model) Message
------------------
- [REF] Improved method names for readability purposes
(e.g. `isAuthor` becomes `isMyselfAuthor`).
D. (Model) Thread
-----------------
- [REF] Improved `init` parameters on each kind of thread.
- [REF] 'Thread With Cache' has been renamed to 'Searchable
Thread': it embraces all kinds of threads that can
be used with the search view.
- [REF] 'DM' has been renamed to 'DM Chat' (for clarity).
- [IMP] New Livechat model in the backend.
- [REF] No more direct instances of the Channel class: public
and private channels are now 'Multi-User' channels,
while DM Chat and Livechat are 'Two-User' channels:
This change has been made so that instances of classes
always have direct classes as "leaf" in the Class
modeling. It eases making changes to a certain model
without being too constrained by another model.
- [REF] As a consequence of above changed, the method `isChat`
has been renamed to `isTwoUserThread`.
This is to avoid confusion with the terminology
'chat', which is more like a shortcut for 'quick real-
time conversation'. In other words, the property of
'chat' depends of the way to interact on a thread, not
of the intrinsic type of the thread.
Still, some parts have kept the terminology 'chat',
such as in the systray messagin menu.
- [IMP] Added `message_added` and `message_posted` hooks,
which may be useful to easily hook on those events.
E. Thread Widget
----------------
- [REF] Now uses a `mail.model.AbstractThread` for the
rendering of a thread, instead of a list of
`{mail.model.AbstractMessage}`.
- [FIX] Stick thread scroll height to bottom on new rendering,
if it was previously at the bottom of the thread.
- [REF] Option ORDER has its meaning changed: it now refers
to the chronological order of messages in the thread,
in which DESC means 'from top to bottom', while ASC
means 'from bottom to top'.
- [REF] Improved doc on templates, in particular with the
option `ORDER`.
F. Thread Window
----------------
- [REF] Moved more logic to thread windows, which were
previously in Mail Window Manager.
- [REF] Now hides the thread widget attribute. So instead of
`threadWindow.threadWidget.isAtBottom()`, it uses
`threadWindow.isAtBottom()`.
- [FIX] New received messages when not having focus on Odoo
tab should always make the corresponding thread
windows "passive" (i.e. windows that keep threads
unread until click on them).
- [FIX] Blank thread window (i.e. 'New message' TW) correctly
opens Discuss with 'Inbox' when clicking on 'Expand'
Button in the title
- [FIX] Do not display the composer for channels with property
'mass-mailing' set in thread windows.
G. (Website) Livechat
---------------------
- [REF] Some `trigger` have been turned into `trigger_up`.
- [REF] Some logic has been moved to models (e.g.
`{im_livechat.model.WebsiteLivechat}`), from
`{im_livechat.im_livechat.LivechatButton}`.
- [FIX] New messages should be received in real-time. The
longpolling was broken with a recent refactoring on
bus service (6448420c5d).
Purpose of this commit is to improve onboarding with a wow effect and a bot
to test the Discuss app. Otherwise new users have nobody to talk to. Retention
will be improved by both increasing interactions and onboarding of Discuss
features.
This commit adds a simple bot in discuss. It answers some questions, helps
users getting their hand on discuss and eases the onboarding.
In this version, the flow is quite simple, and only im_livechat adds some
logic in order to show canned response. The logic is contained in new
modules: mail_bot and im_livechat_mail_bot in order to keep everything
well separated. It also allows users to remove the mailbot if they do not
want to keep this functionality.
Odoobot will only answer if he is in the onboarding conversation (alone
with a user in a channel of type chat) or if a user pings odoobot.
Odoobot logic applies to both standard chatter / channel messages and
also transient messages (like help commands).
Specifications
* 2 minutes after first sign in, users will receive a direct chat from
Odoobot;
* make Odoobot an archived partner;
* scenario
* Odoobot: "Hello, I'm here to help you discover chat features. Try
answering me with an emoji :)";
* User: Send emoji
* Odoobot: "Great! :) Did you notice that you can also send attachments,
like a picture of your cute dog? Try it!"
* Odoobot: "Not a cute dog, but you get it :) To access special features,
start your sentence with "/" (I.E. /help)""
* User: /help
* Auto message then Odoobot: "Wow you're a natural! As a channel usually
contain a lot of users, you can grab the attention with a ping. Try to
ping me with @Odoobot!"
* User: @Odoobot lorem ipsum
* if Livechat installed
* add 2 demo canned response so it does not look weird (like "Hello, how
may I help you?" and "Have a nice day!")
* Odoobot: "Perfect! <br> Try to type ":" to use canned responses."
* User tries canned
* Odoobot: "Good, you can customize your canned responses in the live chat
application. <br><br> + réponse suivante"
* Odoobot: "There's 3 different ways in Odoo to interact with your
colleagues: via this chat window, [img of chat window] via the Discuss
application [img of Discuss app + icon on it] or via the chatter [img of
the chatter]. Aaaaand that's it! Enjoy discovering Odoo! :)"
* random answers to ping/bad answer
* "Mmmmh I'm not sure what you mean.. Can you try again?"
* "I'm afraid I don't understand. Sorry!"
* when someone pings @OdooBot with no reason: Odoobot: Yaaaay that's me!
[party emoji]
* fun stuff to add for some answer
* User: i love you / love
* Odoobot: Aaaaaw that's really cute but, you know, bots don't work
that way. You're too human for me! Let's keep it professional <3
* User: Fuck
* Odoobot: That's not a really nice thing to say, you know? I'm a bot but I
have feelings, ok?! </3
This commit is linked to task ID 1838588 and PR #25075.
Purpose of this commit is to improve the onboarding and the first steps of
Odoo notably when using Discuss and inviting first people to join Odoo.
When a new user connects the user who invited him will be notified with
a desktop notification inviting him to have a chat in Discuss and talk
together.
This commit is linked to task ID 1838588 and PR #25075.
The purpose of this change is to make the code clearer and testable.
In this change, the 'tab_manager' static object was merged with the bus
cross tab.
Cleaning was done to clearly define private and public functions as well
as handlers. The methods are documented and the constants are now defined
on the class. The bus use the service behavior with 'trigger_up'.
'bus.CrossTab' who extend 'bus.Longpolling' are instantiated by the
bus service.
The class is always instantiated with a parent, or root in the case of the website
(im_livechat), to use the ajax and localstorage services. So the behavior, perhaps
logger or redefined by the parents.
If the service bus are called and destroyed the rpc can be returned after, to
avoid a useless call to the database and unexpected behavior, we abort the
connection.
----------------------
Summary
----------------------
The purpose of this commit is to improve the JS code of the `mail` module.
It applies the new coding guidelines and makes some changes on the design
of some modules, such as the old ChatManager module.
Here is a short summary of the changes that have been made:
1. New coding guidelines
- snake_case to camelCase
- prefix private attributes and methods with '_'
- jsdoc on most methods
- one class per module
2. Rename/Merge some classes
- 'chat manager' becomes 'mail manager' (internal) and 'mail service' (external)
- 'chat window manager' is now included in mail manager
- 'thread' widget now named 'thread widget'
3. New model abstraction for mail objects:
- modules 'mail.model.*'
- modeling:
0..1 0..1 * *
ThreadWindow <------> Thread <-------> Message
/ \
/ \
Thread With Cache Document Thread
/ | \
/ | \
Mailbox Channel Support Channel
|
|
DM
- Thread: the superclass of threads.
- ThreadWindow: the window component of a thread.
- Message: mail objects representing messages.
- Thread With Cache: threads that can be used with search view (Discuss app compatible).
- Document Thread: represents the thread part of a chatter.
- Mailbox: represents what was previously called 'static' channel, e.g. 'Inbox'.
- Channel: mail objects representing channels, including livechat.
- DM: special kind of Channel for 1:1 communication in the backend.
- Support Channel: special channel for im_support module.
This new modeling approach let us easily add features on all threads, such as the
possibility to put any thread in a small window.
----------------------
Known issues
----------------------
[Already Present in Master]
1. When the Discuss app is in the background with 'Inbox' as the selected
Thread, when clicking on a document thread preview in the messaging menu
of the systray, the rainbow man appears.
2. When a document with the chatter is in the background, when receiving an
inbox notification from this document thread, the document thread is
automatically marked as read, which removes the notification right away.
3. Sometimes, opening a DM window from the "blank" thread window does not work.
4. Reply-to feature on Inbox is not working: no message is sent in the document
thread.
5. On the first login of admin user with demo data, the inbox counter is wrong
(it displays 6, instead of 3).
Explanation after investigation:
> On page load, it fetches the correct number of Inbox messages (3),
but the server notifies of 3 needaction messages right away,
so it wrongly assumes these are new needaction messages.
> Not possible for web client to detect that these messages should not
increment the Inbox counter while keeping same API.
6. Notifications for new document thread messages only work when the user sets
'handle with Odoo' for the Notification Management in the preferences.
> due to notifications on the longpoll bus for document thread
messages that come from needaction notifications.
> requires server-side changes to send notification on the longpoll
bus to mentionned user.
[New]
7. When receiving a message on a unjoined channel, thread window flickers
('open' > 'close' > 'open')
Explanation after investigation:
> JS logic:
a) On auto-join, ask server to join the channel and get channel infos.
b) The info tells the channel is not detached, but JS code makes decision
to detach it, and tells server the channel is now detached.
c) From (a), server notifies on longpoll bus the state of channel, which is
not detached. The web client thinks that the window state of the channel
has been changed somewhere else, and the channel is now closed.
d) From (b), server notifies on longpoll bus the state of channel, which is
detached. The web client opens the thread window of this channel.
> The flicker didn't occur before refactoring because the web client was only
updating the model of channel when it receives the longpoll notification.
> Server behaviour on 1st longpoll notification is necessary for cross-tab
synchronization for channel window state.
> New design implies that model and view should be synchronized, hence the
issue now.
> Solution: remove server-side thread window synchronization and replace with
client-side synchronization.
----------------------
Hacks
----------------------
The module `im_livechat` now uses mail objects that are compatible with Message
and Window objects:
Modeling for messages:
AbstractMessage
/ \
/ \
LivechatMessage Message
- AbstractMessage: message compatible with the thread widget.
- LivechatMessage: message used by im_livechat.
- Message: message used with the mail manager.
Modeling for thread windows:
AbstractThreadWindow
/ \
/ \
LivechatWindow ThreadWindow
- AbstractThreadWindow: behaviour share between all types of thread windows.
- LivechatWindow: window used by im_livechat.
- ThreadWindow: window used with mail_manager.
The reason for these hacks are twofold:
1. Use the thread widget in the frontend and livechat external lib bundles.
2. Do not have a dependency with the mail manager in the frontend and external
lib bundles.