Commit Graph
3323 Commits
Author SHA1 Message Date
David Monjoie 7a14ea6986 [FIX] web_editor: prevent media selection during search
When updating the results following a change in the search filter or the
source sources filter (All, Illustrations, ...), the list of media is
regenerated to match the new results. If the user clicks on one media at
the right time after the search is triggered (not too fast but not too
slow either) it is possible to select a media which id is out of sync
with the new state of the widget, thus prompting `_onAttachmentClick` to
provide `undefined` to `_selectAttachment`, which ultimately leads to a
traceback in `_highlightSelected` when accessing either `media.id` or
`attachment.id` depending on the case.

This commit fixes the issue by disabling pointer interactions with
the attachments during the search and rendering update process.

closes odoo/odoo#91985

X-original-commit: bc9db4e5a5559692f461acc7402df969b6236481
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-20 21:09:08 +02:00
Nicolas Bayet 36e80e02a8 [FIX] web_editor: fetch undraw images in website and note
task-2794153

closes odoo/odoo#91970

X-original-commit: 536b2ff35f28836ef14cbb353b4749adee21aaad
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-20 20:14:23 +02:00
Sébastien Geelen (sge) ce067c3b56 [FIX] web_editor,website,website_sale : fix products header edition
Prevent edition on e-commerce products header bar.
Since we cannot save any change done in the header object anyway,
And some edition would trigger error.
We put the all bar in a read-only mode.

task-2745151

X-original-commit: e2f7b8fad76dc816b2f6864340d3740446117cdb
Part-of: odoo/odoo#91840
2022-05-20 13:15:39 +02:00
Sébastien Geelen (sge) 6a9fd6b827 [FIX] web_editor: fix some linting errors
closes odoo/odoo#91786

X-original-commit: 46094420d70bfef0e9834a1ed7ef60beab1ccb22
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-20 13:15:30 +02:00
Sébastien Geelen (sge) a3ee176405 [FIX] web_editor: Fix style formating traceback
In some case, when removing format on element with multiple textNode,
the code generate a traceback.

The loops in `toggleFormat` provide a limit element `closestDecorated` to
the `splitAroundUntil` util. However this limit element can be split and
dumped by the format removal. In this case the reference was never encountered
in the DOM by the `splitAroundUntil` code and will bubble all the way to the
`<html>` TAG an try to split it, which generate an error.

We fix it by getting the `closestDecorated` in every loop.

task-2850686

X-original-commit: 2d93345c38f55c276370d0059d562d28320db2fb
Part-of: odoo/odoo#91786
2022-05-20 13:15:30 +02:00
Sébastien Geelen (sge) cc80572ee6 [FIX] web_editor: fix missing strikeThrough tests
Add some unit test for strikeThrough format.
Those tests reveal some bug in the current formating code.

task-2850686

X-original-commit: 4d8e1dc381d01bb254d2e806a335a40733608f2e
Part-of: odoo/odoo#91786
2022-05-20 13:15:30 +02:00
Sébastien Geelen (sge) 491a9d6399 [FIX] web_editor: fix unit test
Wrong contentAfter labeling.

X-original-commit: 22bb8ae8e131a576987e95911d229aad42d00193
Part-of: odoo/odoo#91786
2022-05-20 13:15:30 +02:00
Younn Olivier 79867ca96f [FIX] web_tour, web_editor: observe iframe DOM mutations in tours
Before this commit, iframes DOM mutations were not taken into account to
update the tour manager. So in the context of mass_mailing, displaying
the web editor in an iframe, the tours were updated at the right moment
by chance (no mutations for 750ms in the global document and in the
iframe document).

This commit adds an o_iframe class, used to define an iframe that will
render a part of Odoo. An observer is added in the tour service to
monitor the addition of such iframe, and sets an observer on that iframe
to correctly update the tour manager, counting the iframe DOM mutations
for the 750ms delay.

In addition to this observer, the iframe's HTML content is added to the
final document HTML log when a tour crashes (directly between the
<iframe></iframe> for convenience, copy/pasting it in a browser just
ignores what's in between).

Also, when the tour_service is initialized in an o_iframe, it will not
run the tours.

This fix targets the saas-15.3 as it is needed to avoid a race condition
introduced with [1] (introducing a tour which relies on DOM updates
inside the mass mailing iframe). This could be backported if the need
ever rise (it should really have been the case since [2]).

[1]: https://github.com/odoo/odoo/commit/52d32e26c34bef10823582ef5c1f840492b73d7a
[2]: https://github.com/odoo/odoo/commit/971629b9fe40911c3a9765c9fb746ea1c55d3560

closes odoo/odoo#91718

X-original-commit: ea35bd06c84b7101224c3b3dd24d1780e13232a9
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
2022-05-19 12:28:24 +02:00
Antoine Guenet b389313682 [FIX] web_editor: prevent traceback on reduce empty array
The mailing html converter uses the `reduce` method of `Array` to
compute column size when converting Bootstrap grids to tables. However,
if that array is empty, given that no initial value was passed, the call
caused a traceback. This is fixed by providing an initial value of zero
as should be expected.

task-2853723

closes odoo/odoo#91683

X-original-commit: 4504d1a880032829fb46dbdeab996bd4e0f9ee97
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-18 17:09:51 +02:00
Nicolas Bayet 814659b73d [FIX] web_editor: disable element hint for website
Task-2674569

closes odoo/odoo#91148

X-original-commit: 117d465eff2c79a9d17164306c17f3f87aa11848
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-18 09:42:48 +02:00
Sébastien Geelen (sge) 9de29c709d [FIX] web_editor: fix toolbar visibility check
When the selection span across two element linked
to odoo field that cannot be styled.
The toolbar should not be visible.

The visibility check was performing a verification
based on the `range.commonAncestorContainer`,
therefore when the selection spanned across multiple element
the common ancestor was higher in the DOM than we wanted, and
the check was not working.

We changed the check to use `selection.anchorNode`
and `selection.focusNode` to ensure the verification works any time.

task-2845346

closes odoo/odoo#91324

X-original-commit: aaa65a49489bad3d25cc3229f0b85e66b8ae855d
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-13 14:39:53 +02:00
3cd87ca0dc [IMP] knowledge: add the template and file commands
This commit adds some commands that can be used in the html editor.

Editor Commands
---------------

Some new editor commands have been added:

- */article:*
This command is available on every html field using the Odoo Editor.
This command allows to add a direct link to the selected knowledge article.

- */file:*
This command is only available in the Knowledge App.
This command allows to add a file (or an image) download button inside the
body. The user can choose a file to add from its own file directory or an
existing attachment already present in the database.

- */template:*
This command is only available in the Knowledge App.
This command allows the user to create a block where them can write and lay out
content destined to be reused by the readers of the article. The lasts will be
able to copy and paste it to send it as message or use it as a description on
other records.
No /command can be added inside a template.

Technical notes:
/file and /template commands can be activated in other modules by adding
knowledge_commands = True on the html field in the view where they should
be activated.

Task-2674460

Part-of: odoo/odoo#82315
Co-authored-by: Damien Abeloos <abd@odoo.com>
Co-authored-by: Julien Banken <jbn@odoo.com>
Co-authored-by: David Beguin <dbe@odoo.com>
Co-authored-by: Fabio Barbero <faba@odoo.com>
Co-authored-by: Thibault Delavallee <tde@odoo.com>
Co-authored-by: Aurelien Warnong <awa@odoo.com>
2022-05-13 02:58:51 +02:00
661f98be3c [ADD] knowledge: manage knowledge
Purpose
=======

Allow companies to centralize all their knowledge in a specific place they own.
Create wiki-like pages to structure the information and make it easily
available. Leverage those later on while working in the back-end.

Specifications
==============

An article is mainly composed of a title and a body. The later is an html field
that can contain text, images, link to other articles or records from other
models, templates, etc..

Articles will be classified in 4 categories:

- *Workspace:*
The articles are available for each internal users in read or write access.
Only internal users can create, read, modify and delete knowledge articles.

- *Private:*
The articles are only available for the owner. Only internal users
can set an article as private. A private article can be shared to external users
in read access only. If the article is shared with internal users, see Shared
section.

- *Shared:*
The articles are not available for any user except the ones that have been
added as members on it. For the current user, this section contains all the
private article the user shared with someone and all the other's private
articles shared with me.

- *Favorite:* (Additional category for UX)
Articles can be set as favorite and are user specific. Any identified user can
set an article in favorite, as long as the user has access to it. Public users
cannot add articles to favorites. Favorites can be reordered and this ordering
is user specific.

An article can have a parent and multiple children. Each parent and each
children is also an article. Root articles are the highest parent in the
hierarchy and are considered as the *Subject* (aka Topic) of their whole
hierarchy. There is no limit on how many levels there are in the hierarchy.

In the 3 first categories, the articles are listed starting for the root
article. The child articles are listed below their parents only if the user has
access to them. It can be that a user has access to an article that is not
listed in knowledge main view because that user has no access to the parent
article. More information about access below.

Categories are based on the root article. If a children is private, because only
accessible by 1 user, and its parent is accessible by everyone, the children
will be listed in Workspace section.

Technical notes

The following domains apply to assign root articles in the different categories:
- Private: permission 'none', only member = uid
- Shared: permission 'none', more than one member with read/write access
- Workspace: other
In addition, the UX category
- Favorite: is_user_favorite = True (can contain articles from any category)

Home View (backend)
===================

The main knowledge view is a tweaked form view that displays all the accessible
root articles and their accessible children in a side panel hierarchic tree.
This side panel allow quick access to each articles without having to navigate
back to a list or kanban view. This form view mainly displays the title and the
body but also integrate custom buttons to manage and search the articles.
All those buttons + the side panel are detailed below.

This "Home" view is loading displaying the first favorite article of the
user. If the user has no favorite, it falls back to the first root article of
Workspace section.

The default view mode depends on the user access:
- If user can read: readonly mode
- If user can write: edit mode

Search View
-----------

The standard list view will be used as an advanced search to find an article
that cannot be found easily via the command palette (ctrl+K). All the searching
options remains standard (search / filter / group by). Selecting an article in
that view will redirect to the home view (displaying the selected article).

Side Panel
----------

- *Reorder and hierarchy:*
From the side panel, drag and dropping an article can resequence the articles
between them and/or change the parent of the moved article.

Note on reordering:
Each parent have its own sequence for its children. So the sequence is not
common for each articles in the database, but specific for the children of a
same parent. The resequencing is done among the children of the same parent.
If some articles has no parent, there are considered as the root articles and
all root articles have their own sequence too.

- *Create:*
From the hierarchy tree, the user can directly create an article using the '+'
signs:
    - as root of Workspace or Private section
    - as a child of a target article.

- *Fold/Unfold:*
To speed up Home page loading: only first level is loaded + the articles that
user already unfolded in the past. The app keeps track of unfolded articles per
user (using Local Storage).

- *Icon:*
Each article has an icon associated with it. The user can click on the icon to
change it.

- *Search an article:*
This button opens the command palette to perform a search on articles.
More detail on this in the Advanced Feature section (below).

Article header and Button Menu
------------------------------

- *Breadcrumb:*
Located on the top left of the main view, the breadcrumb can be used to edit the
article title.

- *Favorite:*
Next to the title, a star button can be used to add/remove the article to/from
the favorite.

- *Create:*
Creates a new private root article.

- *Share:*
Opens the permission panel. This is where the user can configure the access on
the article or, if user has no write access, see what are the access rules on the
article. More detail on this panel in the Access Rules section (below).

- *Chatter:*
Toggle the chatter On/Off at the right of the article view.
There users can:
    - Send messages and log notes
    - Schedule activities
    - Follow an article

The following buttons can found in the kebab menu, in which we can also find
who created or edited the article last and when.

- *Move To:*
Opens a modal to select the parent under which the current article should be
moved. The article will be placed as the last children of the selected parent.

- *Lock:*
When activated, prevents all edition of the article content (body and title)
until it is unlocked. (Purpose: avoid accidental edits)

- *Duplicate:*
Creates a copy of the current article, under the same parent, but does not copy
the children articles. The new created article will have the same access rules
as the original article.

- *Archive:*
Will archive the current article and all its children. Archived articles can be
retrieved using the Advanced Search (see below for detail) with "Archived"
filter.

- *Full Width:*
By default, the article is centered in the view, to make it easier to read.
If needed, the can activate the full width. This will make the article body take
full width available on the article view. This option impacts the rendering of
article, also in the frontend view. More detail on the Frontend View below.

Body
----

The body is composed of an html field that can be edited using the Odoo Editor
and all its capabilities. Some new commands have been added to enrich the
editor: /template - /file - /article (More details in Advanced Features section)

At the top of the article body, the article icon and cover can be added using
their respective "Add" buttons.

- *Icon:*
Can be modified by simply clicking on it.

- *Cover:*
Can be modified using the "Pen" icon at the top left of the cover,
and deleted using the "Bin" icon at the top right.

Frontend View
=============

The frontend view is basically a simpler version of the backend view where users
can only read the article and add them to their favorites (if user is
identified).

The frontend view is composed of the side panel in the left, the article title
and favorite button on the top and the main body view.

From the side panel, the user can navigate to each available article, reorganize
them favorites and filter the articles using the search bar.

From the main body view, the user can consult the content of the article and
download eventual attached files from the '/file' sections.

Access Rules
============

Basics
------

The access is defined depending on two criteria:
- The Internal Permission
- The article members and their permission

Both have 3 level of permission:
- none (No Access)
- read
- write

The internal Permission is the base permission for internal users. By default,
all internal users can write on the article, unless the permission have been
downgraded to 'Read' or 'No access'.

An internal user however can be added as a member of the article with a
specific permission that applies only for them. This member permission takes the
priority on the internal permission.
The internal users will always be redirected to the backend view when they want
to consult an article.

By default, external users (portal or public users) cannot have access to the
articles, unless they have been added as member. They can only be invited with
read acces on the articles.
External users will always be redirected to the frontend view when they want to
consult an article they have access to.

An administrator (group_system) will always have write access, even if
permissions tell the contrary. However, only the articles they have the
permission to see or write on will be listed in the side panel. They can find
the other articles in the Advanced Search view.

Only the users with write access can edit the article body and title, reorder or
change the parents and children, invite members and edit the access rules of the
article.

- *Constraint:*
An article should always have at least one user having write access on it.

- *Lock mechanism:*
Only users with write access can lock or unlock the article.
when an article is locked, the title and body of the article cannot be edited,
even by a user with write access on it.

Access Inheritance
------------------

By default, a child article inherit the access rules from its parent.
That means that access rules can be defined on the root article and those rules
will apply for each descendant article (children and their own children, etc.).

However, a child article can have specific rules that will apply only on itself
(+ its descendant):

- *Synchronized:*
That can be done by adding a member on that article, or by upgrading any of the
permission based on its parent(s). In that case, the article access rules still
depend on its parent(s). If an additional member is added on the parent,
the child article will still inherit that member. The rules that applies
specifically on the child article have the priority on the inherited rules.

- *Detached:*
When an access rule is downgraded in a child article that initially depends on
parent's access rules, the article access rules are detached from the parent's
access rules. All the access rules that applied on the parent are copied on the
child article and that article is flagged as detached. The children of that
article will, for now on, only depend on it, and not on higher parents anymore.

An detached article can be resyncronized with its parent. In that case, all the
specific access rules that do not apply on its parent will be removed. The child
article will still keep its specific upgraded access rules but will, once again,
depends on its parent.

Share Modal (and access rules application)
------------------------------------------

The share modal (or permission panel) is where the access rules of an article
can be configured.

From there, a user with write access can:

- *Invite new members:*
A modal opens and the user can:
- add existing partners or type email addresses and create new partners
- select the permission that should apply on all selected partners.

If there are external users among the selected partners, only the read access
can be used. That means that if the user select:
- Write permission: the read permission will be given to that partner.
- No Access: The partner will not be added the members.

An invitation email is sent to the invited partner.
If the partner is already registered (has an active user), them can directly
access the article with the link provided in the email. They may need to log in
first.

If a partner is not yet registered (have no user), when using the link provided
in the email, them will be asked to register first, and will be afterwards
redirected to the article.

- *Modify the Internal Permission:*
The user can select the new permission to set for all internal users.

    - Special use cases:
        - If the user sets internal permission != write, the user will be added as
member with write access. The purpose is to let the user continue to edit the
article.
        - When downgrading internal permission on a child article (that depends on its
parent), detach it from parent in terms of access rules.
        - when upgrading internal permission on a child article, just set the
permission. The article is not detached from parent, but the article will use
its own internal permission to compute the user accesses.

- *Modify a member's permission:*
The user can select the new permission to set on the target member. The user can
also remove a member.

    - Special use cases:
        - When downgrading or removing a member based on parent: Detach the article
from it's parent
        - When upgrading a member based on parent: add a new member with the selected
permission.

Website Published (Access for public users)
-------------------------------------------

When the Website App is installed, users have the possibility to publish the
articles. When an article is published, everyone can read the article.

- *Internal users* can read a published article even if their permissions does not
allow them to read it. They can access those published articles like every other
articles, still in backend view.

- *Portal users* can read a published article even if their permissions does not
allow them to read it. They can access those published articles like every other
articles, still in frontend view.

- *Public users* can read a published article. They can access it by using the
article link from the frontend view.

Advanced Features
=================

Search and Advanced Search
--------------------------

- *Command Palette:*
Searching is done through the command palette. Just as we have '#' for channels,
'/' for menus and '@' for users, '?' has been added for articles.

The command palet is accessible by either
- Hitting CTRL+K (and then adding ? to search among articles)
- Clicking on the fa-book icon of the chatter, which already
adds the '?' so that one can start searching straight away.
- Clicking on the "Search An Article" button (in the side panel)
while reading another article, where the '?' is automatically added too)

The search result are ordered as followed:
My Favorites > Most Favorites > the rest.

The results display the article name + the subject (highest parent name).

If no results are found and user have write access, them can create a new
(private) article with the search query as title.

- *Advanced Search:*
If the user is not happy with the search results, them can do an
"Advanced Search", which sends me towards a normal Odoo list view where I can
search, filter, groupby, ...

Editor Commands
---------------

Some new editor commands have been added:

- */article:*
This command is available on every html field using the Odoo Editor.
This command allows to add a direct link to the selected knowledge article.

- */file:*
This command is only available in the Knowledge App.
This command allows to add a file (or an image) download button inside the
body. The user can choose a file to add from its own file directory or an
existing attachment already present in the database.

- */template:*
This command is only available in the Knowledge App.
This command allows the user to create a block where them can write and lay out
content destined to be reused by the readers of the article. The lasts will be
able to copy and paste it to send it as message or use it as a description on
other records.
No /command can be added inside a template.

Technical notes:
/file and /template commands can be activated in other modules by adding
knowledge_commands = True on the html field in the view where they should
be activated.

Technical considerations
========================

Access Rules Computation
------------------------

Articles access rules are based on inheritance from parent articles. Purpose is
to avoid making copies of all member rules on each article in the hierarchy.
This allows to lower database storage. The counter part is that the computation
of user accesses is made more complex. Instead of simply reading the article
internal permission and members permissions on the article, access is computed
based on each parent above the article.

To speed up batch compute, user permissions are computed directly with recursive
SQL queries. They collect all the needed information for multiple users (based
on their partner) and multiple articles.

Ordering on is_user_favourite
-----------------------------

To allow ordering on is_user_favourite computed field, the search method have
been overridden to add the favorite articles of the current user to the search
result. This is used in the advanced search view but will also be used in
the ctrl+K command.

Sequences and resequencing
--------------------------

Sequences in knowledge article does not respect the conventional sequencing
(one sequence for all the records of the model). Instead, the sequence is
specific for all children of same parents. Resequence had to be overridden to
take that into account and only resequence the children of same parent, and not
the entire table. Moving an article in the middle of a 'folder' should not
impact the other folders but only the children of that target folder.

Breadcrumb
----------

On the form view, the breadcrumb will be located in the control panel.
For the knowledge module, we needed a headless layout. In the mockup,
the breadcrumb has to be placed within the form sheet.

Unfortunately, the breadcumb is a owl component and its logic is
encapsulated in a function which makes it not editable.

To avoid having to update the core, we will render a custom breadcumb
that will be generated based on the `breadcrumb` parameter passed to the
`init` function of the form view.

Task-2674460

Part-of: odoo/odoo#82315
Co-authored-by: Damien Abeloos <abd@odoo.com>
Co-authored-by: Julien Banken <jbn@odoo.com>
Co-authored-by: David Beguin <dbe@odoo.com>
Co-authored-by: Fabio Barbero <faba@odoo.com>
Co-authored-by: Thibault Delavallee <tde@odoo.com>
Co-authored-by: Aurelien Warnong <awa@odoo.com>
2022-05-13 02:58:50 +02:00
Nicolas Bayet 53b4afe747 [FIX] web_editor: keep content on enter on mobile
Before this commit, when hitting enter while not in composition mode,
the editor sometimes removed all the content that was added the previous
composition.

task-4720

closes odoo/odoo#91235

X-original-commit: eddc820417d97b4100a9fb2f9f8934a84bb2417c
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-12 17:35:04 +02:00
Nicolas Bayet 6f9110bfb0 [FIX] web_editor: prevent deleteBackspace to move nodes
Before this commit, whenever the element that must be deleted by
`deleteBackspace` matches `isMediaElement` or `isNotEditableNode` and
the cursor was in the beginning of a `<p>` with inline content, the
inline content moved to the parent and the `<p>` was deleted.
Which is wrong.

Now, whenever the element that must be deleted by `deleteBackspace`
matches `isMediaElement` or `isNotEditableNode`, no inline content
moves.

Task-2781328

closes odoo/odoo#91233

X-original-commit: 34d06958d053b070b1e07541214899649602873a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-12 17:35:00 +02:00
Nicolas Bayet 4338881cd4 [FIX] web_editor: restrict url regex
Inserting `w.r.t` in the editor transformed it into an url.
This kind of content should not be considered as an url.

task-2795012

closes odoo/odoo#91221

X-original-commit: 75c146fac019b952543403736948b803689bd15b
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-12 16:05:16 +02:00
Hiral Bhavsar cfa916379b [FIX] web_editor: traceback on strikethrough with a checklist
Before this commit:

When having a checked checklist and clicking on the `strikethrough` gives
traceback.

After this commit:

No traceback is being generated.

Task-2833325

closes odoo/odoo#91114

X-original-commit: 491a79f6f8f734990a2ece3fd1b3f90d09a55c85
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-11 18:50:14 +02:00
Nicolas Bayet 7dfd2e071e [FIX] web_editor: prevent class to create history steps
There is some classes that are technical and should not create steps.
Otherwise it compromise the ability to undo/redo or compromise the
ability to detect the dirty elements properly.

This commit prevent thoses classes additions and removals to create
history steps.

task-2836351

closes odoo/odoo#91074

Forward-port-of: #90064
X-original-commit: 41d8a0f246a134e2b5292da4db11e67aa9cfb4ed
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-11 14:54:28 +02:00
Nicolas Bayet 57d3211c99 [FIX] web_editor: disable observer only when necessary
Before this commit, the linktool was disabling the editor observer
until it was destroyed. This messed up with the undo/redo and the
isDirty.

This commit only disable the observer when necessary.

task-2836351

Forward-port-of: #90064
X-original-commit: 57c98f314332bbb4c3225942e1d3748eb131d8b0
Part-of: odoo/odoo#91074
2022-05-11 14:54:28 +02:00
Guillaume (gdi) 8d6c4e421e [FIX] web_editor: fix form not saved
Before this commit, the modifications of the form were not saved if the
user had only clicked on the submit button of the form. Only elements
with the class o_dirty are saved, but since this commit [1], the
observer that adds this class was disabled. The resolution of the bug is
just to remove the fact that the link tool disables the observer that
adds the o_dirty class. This commit also adds a test to make sure that
this bug does not happen again.

Here are the steps to see the bug:
- Go to /contactus page
- Click on edit
- Click on the Submit button
- Change a Form option (eg: Recipient Email, Labels Width, URL, ...)
- Save

Edit again the see that the changes are not saved

[1]: https://github.com/odoo/odoo/commit/c29fe9fa8fc8ff4a5e6f042607ef9b3070d1d339

task-2812722

Forward-port-of: #90064
X-original-commit: 3b45ef633adbeebee4819c30808680644b85c5fc
Part-of: odoo/odoo#91074
2022-05-11 14:54:28 +02:00
xO-Tx f0fe283c76 [FIX] web_editor, *: fix image options visibility
*: website

Issue: from 15.0 onwards all image options are available on "/shop".

Details:

On 14.0, images options were removed for unsupported images (we had
a message "Quality Options Unavailable" - see [1]) and images related
options on old editor toolbar were hidden too.

On 14.4 and after [2], images options from the toolbar (crop, width,...)
were moved to a separate 'ImageTools' option and as a consequence, they
don't respect the same visibility rules as 'ImageOptimize'. Other
options were added in XML and they have the same issue, they are visible
as long as the target is an 'img'.

This is a list of options that should be available for unsupported or
partly supported images:

[A] For "t-field" images (shape & quality options are available only if
the image is supported for processing):

- Shape
- Filter
- Width (image width)
- Quality
- Transform (crop)

[B] For external images or images unsupported for processing:

- Description
- Tooltip
- Transform (crop, transform)
- width (CSS width)
- Alignment
- Style
- Padding
- Animate

[C] For illustrations:

- Same as [B]
- Dynamic colors

The goal of this commit is to fix this visibility issue on the JS code
of image options.

[1]: https://github.com/odoo/odoo/commit/84417a174bc2bb76730cc89783d3426a3a3b07d9
[2]: https://github.com/odoo/odoo/commit/d934b81aaae8d68b5579d1489b1fbe8ea347b4ed

task-2724946

closes odoo/odoo#90224

closes odoo/odoo#90832

X-original-commit: 8e6ca51ed3ebf121acfc7cb1ab992984d0764c90
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
2022-05-10 15:16:44 +02:00
Nicolas Bayet fc26cc1789 [FIX] mass_mailing: clean oe_edited_link
Task-2729195

closes odoo/odoo#90722

X-original-commit: 99210fc58f7ed35c2c066b6aaba8efc94bcd2931
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-06 13:30:25 +02:00
abd-msyukyu-odoo f75462eeaf [IMP] web_editor: expand deleterange for uneditables
In Chrome, it is possible to partially select the contents of a
contenteditable=false element if it has a contenteditable=true child.

This commit prevents breaking such uneditables by expanding the range in a
deleterange to fully contain such elements.

It will be useful with the new blocks introduced with the Knowledge module.

Task-id: 2794990
Part-of: odoo/odoo#86489
2022-05-05 11:41:57 +02:00
abd-msyukyu-odoo f4d72dd1ed [IMP] web_editor: prevent command refocus when unnecessary
Currently, the focus is forced on this.editable when using a powerbox command.

Knowledge /template will introduce blocks which are contentEditable=False, but
contains sub-elements with contentEditable=True, which are allowed to use
powerbox commands. Those sub-elements have another editable context as
this.editable. As such, forcing a refocus on this.editable will remove the
caret from the sub-element.

Avoid doing the refocus if the currently focused element is a child of
this.editable and is contentEditable=true.

Task-id: 2794990
Part-of: odoo/odoo#86489
2022-05-05 11:41:56 +02:00
abd-msyukyu-odoo c007dafae8 [IMP] web_editor: add failsafe upon CTRL+BACKSPACE
Prevents the user to remove the last child (if it is an empty block) of an
editable, in order to avoid the case where the user can add text nodes directly
in a block where it should not be possible (i.e. directly under this.editable).

Replaces any empty block other than `<P>` by an empty `<P>` which is the default
block for the editor.

Task-id: 2794990
Part-of: odoo/odoo#86489
2022-05-05 11:41:55 +02:00
abd-msyukyu-odoo e82e96f173 [IMP] web_editor: set contenteditable as a safe attribute
Add the attribute 'contenteditable' to the frozen list for html elements of
DOMPurify, so that this attribute is not sanitized in collaborative mode when
using _safeSetAttribute.

Task-id: 2794990
Part-of: odoo/odoo#86489
2022-05-05 11:41:54 +02:00
David Monjoie f3372799ae [FIX] web_editor: fix traceback on paste
When fakeEl is empty, firstChild and lastChild both equal null.

task-2842638

closes odoo/odoo#90523

X-original-commit: 626caa89cf290f226b19dfa73bc4ab41c7f95fc0
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-04 17:46:41 +02:00
Sébastien Geelen (sge) d8fd724cb3 [FIX] web_editor: transform orphan LI into P
Avoid living `<li>` tags without a `<ul>` or `<ol>` parent
in the editable html.

task-2842638

closes odoo/odoo#90518

X-original-commit: c6660d9ae1c931da3ad442b30f610db463ede894
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-04 17:46:35 +02:00
Benoit Socias af5bf85d34 [FIX] web_editor, website: increase stability of ace test tour
This is an attempt at fixing a runbot race condition.
It was executed succesfully without any error on Multi build around
200 times on runbot.

Since [1] the reset button could be clicked before the HTML editor was
reloaded.
The `MutationObserver` in `tour_service.js` is debounced. Because of
this the states used to detect tour steps triggers might differ between
executions.
With the Reset button of the HTML editor not being hidden in the
rendered template, it might be detected before it gets hidden during
the `start` of `ace.js`.

This commit makes sure the the editor is both closed then reopened with
the Reset button visible before clicking on it, and also makes sure the
Reset button is not visible by default upon rendering.

[1]: https://github.com/odoo/odoo/commit/d20468c3463927a54c34688769a22b3949c5c465

runbot-3674

closes odoo/odoo#90453

X-original-commit: b35f127c86c1d271a76dae7186a96190e8558c73
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-04 10:55:59 +02:00
Nicolas Bayet a05874f808 [FIX] web_editor: prevent loading toolbar twice in translate mode
task-2802733

closes odoo/odoo#90416

X-original-commit: ee62ad02875fa79e4f91186d73b969e138419eab
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-03 16:55:05 +02:00
Hiral Bhavsar 5f9ba2435b [FIX] web_editor: reverted useful code which had been put as a comment by mistake at https://github.com/odoo/odoo/commit/344d82ca251bbba8f54e85d6b881cc92f8823f13
closes odoo/odoo#90401

X-original-commit: 6e990b6d13699e347275383b703dec34ddac3197
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-03 15:44:23 +02:00
Deepak Shah 223491036a [FIX] web_editor: traceback after clicking crop button.
Before this commit:

After selecting an image and clicking on crop button, crop widget displays and
vanish immediately and crop does not work. After clicking on screen, it raises
an error (Cannot read properties of null (reading 'removeChild').

After this commit:

The crop button works fine without raising any traceback.

Task-2804892

X-original-commit: 1ab1c15386f778b04eb78f26b1e0934f3329c6af
Part-of: odoo/odoo#90401
2022-05-03 15:44:22 +02:00
Xavier Morel 7bce4c19f3 [IMP] web_editor: cleanup channels regex
Model pattern was too permissive, separator is the literal `.`
character, not any random thing.

Also remove unnecessary bracket expression, it's unnecessary when
matching a single item.

OPW-2836106

closes odoo/odoo#90107

X-original-commit: 320cdb4e85cb86915fa25cfda8f17e0a372e765e
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-05-03 13:31:03 +02:00
Antoine Guenet 53aba047ce [FIX] web_editor: apply original element attributes on toggle list
When converting an element to a list element, we didn't preserve that
original element's attributes. As a consequence the text direction was
lost.

closes odoo/odoo#90247

X-original-commit: 0731ff677491d80540fa2ffc645fd2b471a9f61c
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-05-02 07:43:55 +02:00
Antoine Guenet 618d5bc3ca [FIX] web_editor: provide proper support for mixed language directions
This introduces a "direction" option on the editor to set the text
direction of the editor (passed by Odoo based on the localization), and
a Powerbox command to switch said direction on a given block. This
allows users to mix several text directions within the same text, eg.
when quoting Hebrew in an English text.

task-2814004

X-original-commit: 693df325588ccaf6385c9f610709f687ccdf61a8
Part-of: odoo/odoo#90247
2022-05-02 07:43:55 +02:00
Sébastien Geelen (sge) e42dc39e37 [FIX] web_editor: fix isDirty() in wysiwyg.js
The isDirty method of the wysiwyg was not very accurate
and was most of the time returning true
even if no changes were done in the editor.

task-2692125

closes odoo/odoo#90200

X-original-commit: bab673488e185ddd7792aedecc3870663290fed3
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-29 18:22:20 +02:00
Arthur Detroux (ard) b66409cad4 [FIX] website, *: properly stop widgets before removing snippets
* web_editor

Prior to this commit, removing a snippet while its widget was still
active could lead to slow removal as editors would be created for its
inner content.

Stopping a widget before removing it is good practice as it will clear
the DOM from any content it may leave behind and will prevent snippet
editor to be created for its dynamic inner content.

As an example, the `Products` snippet had SnippetEditors being created
for its product cards, which could lead to slow removal especially
in later versions of Odoo. E.g. in 14.0, because ImageTools were
introduced.

Closes #85464

task-2781418

closes odoo/odoo#90100

X-original-commit: ca1359e0f40b94b93eb8cfd6834a05796f64c675
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
2022-04-29 12:06:26 +02:00
Denis Ledoux b03c227e88 [REF] models: refactor fields_view_get, load_views
Refactor the `load_views` API so it no longer sends multiple times the same
fields description.

e.g.
When `load_views` is called to get the kanban, tree and form views,
the list of fields of the model was sent 4 times:
- Once for each view, with only the fields used in the view,
  in `['fields_views']['kanban']['fields']` for instance
- Once globally, with all the fields of the model, in `['fields']`

The goal of this revision is to change that so it sends the list of all fields
only once.

In addition, if a view contains x2many fields,
the fields description of the comodel is also sent.
It was sent in the `views` key of the view fields dict.
e.g.
When calling `load_views` of `res.partner` to get the kanban,
tree and form views,
the `res.partner` fields description was actually sent 6 times:
- Once for each view
- Once globally
- Once for each view of the many2many field `child_ids` of the form view, in
  - `['fields_views']['form']['fields']['child_ids']['views']['kanban']['fields']`
  - `['fields_views']['form']['fields']['child_ids']['views']['form']['fields']`

The change suggested in this revision is to:
- Remove the fields description for each view in `['fields_views']`.
  As it no longer contains the fields,
  the key becomes `['views']` instead of `['fields_views']`.
- Replace the dict key `['fields']` by `['models']`,
  which is a dict with as key the model name and as values
  the model fields description. It contains the fields description
  for all models implied in the view:
  the model of the main view and the model of all one2many and many2many fields.

With this change, the fields description will only be sent once by model
implied in the view.

In addition, the web client was getting the information about the fields
sometimes in the global fields description list (e.g. `['fields']`),
sometimes in the fields description list of the view type
(e.g. `['fields_views']['form']['fields']`),
making it a pain to try to make changes / performance gain
in these field description dictionaries, because you never knew in which dict
the web client was getting its info.
Now, as there is only one place to get the fields description from,
it's clearer and cleaner.

- one2many and many2many fields views are passed directly in the main view
  architecture rather than being put in the `views` key
  of the field description.
  This is actually easier to treat by the web client,
  and this will allow in a future work to cache an entire view in one block
  of text rather than having to combine multiple cached blocks of text
  to return one view.
- one2many and many2many fields which do not have directly embedded views
  have their views directly injected in the architecture,
  so the web client doesn't have to do RPC calls to `load_views`
  for each one2many and many2many fields not having embedded views.
  For instance, this allow to reduce the number of RPC calls to `load_views`
  from 8 to 1 when loading the form of `product.product`.
  Currently, this behavior is limited to 1 level deep but we consider making it
  go all the way down in future works. We did not do it for the moment because
  in certain cases it rises the processing time and the size (bytes) too much.
  e.g. the sale.order view can be 5 levels deep,
  meaning you can reach 4 dialogs on top the main view.
  ```
  sale.order form > order_line > sale.order.line form > invoice_lines >
  account.move.line form > asset_ids > account.asset form >
  depreciation_move_ids > account.move form.
  ```
  This will also benefit in future works to cache an entire view in one block
  of text rather to having to combine multiple cached block of text
  to get one view.
- `fields_view_get` becomes `get_view`.
  As it no longer returns the fields description,
  keeping the `fields` in the name `fields_view_get` no longer makes sense.
  Hence removing `fields` from the method name, it becomes `view_get`.
  As it gets renamed anyway, we take the opportunity to rename it `get_view`,
  which is more in line with the general getter/setter guidelines
  in the model object world.
- `_fields_view_get` becomes `_get_view`. For the same reasons than above.
- `load_views` becomes `get_views`.
  This is not mandatory, there is no technical reason to rename `load_views` as
  it practically sends the same info as before,
  the view architectures and their fields description. Just in another way.
  We just take the opportunity of this pull request to suggest a cleaner API:
  `_get_view`, `get_view` and `get_views`.
- Arguments `toolbar=False, submenu=False` fo the methods
  `_fields_view_get` and `fields_view_get` are converted to a kwargs `**options`
  in `_get_view` and `get_view`.
  The rationale is that submenu was already no longer used (deprecated)
  and the mobile options is introduced.
  The mobile options is necessary to tell the server to send the mobile views
  for x2many fields (kanban instead of tree).
  Instead of adding a new argument each time we add a new option to
  `fields_view_get`, it seems wiser to have a kwargs `**options` to avoid
  to re-write all overrides each time a new option is introduced.
- `_fields_view_get` returned a dict containing the arch in text and some of the
  view information. Now, `get_view` returns a tuple with the view architecture
  as an `etree` node, and the view as a browse record. The rationale is that all
  overrides of `_fields_view_get` were about modifying the arch only
  (e.g. changing the address format/re-organizing the address related field
  nodes of the partner according to the company country).
  To do so, all these overrides were doing `etree.fromstring` to parse the arch
  which was sent in text to convert it to an `etree`,
  then operations were done on the `etree`,
  and then `etree.tostring` was called to convert back the arch to string.
  With this change of signature to send the arch as an `etree`,
  all these back and forth `etree.fromstring` -> `etree.tostring` are avoided,
  allowing some performance gain and less code in the end.
- A cleanup of the keys returned in the dict of `fields_view_get`
  has been performed in `get_view`:
  - `fields` is removed, as explained above,
  - `view_id` is renamed `id`,
  - `name` is removed, it was unused by the web client,
  - `type` is removed, it was unused by the web client,
  - `field_parent` is removed, it was unused by the web client,
  - `base_model` is removed, it was unused by the web client.
- `filters` is moved from the global dict returned by `load_views`
  (now `get_views`) to the dict returned by `fields_view_get` (now `get_view`)
  as it applies only to the `search` view type.
- Retro-compatible methods for the 3 methods
  `fields_view_get`, `_fields_view_get` and `load_views` are provided,
  with deprecation warnings in them.

- The web client could cache the model fields description
  (as it already caches the views),
  so it doesn't need to fetch them again if it asks for another view of a model
  for which he already has the fields description.
  If we do so, `get_views` could return only the list of models used by
  the views, without the fields description as of now,
  and the web client would then call `fields_get` independently only for
  the models for which it doesn't have yet the fields description.
  This would avoid the server to return the fields description
  and to call `fields_get`, which is costly, for each `get_views`,
  therefore gaining performances.
- Inject the views of the one2many and many2many fields all the way down,
  unlimited depth level, as explained above.
- Cache with `ormcache` the architecture of back-end views.
  This is already done for qweb views, it's not done for back-end views.
  Therefore the postprocessing of the views is performed for each `get_views`,
  which is costly, while the view architecture doesn't change for users
  belonging to the same groups, according to the groups implied by the view.

This pull request is co-authored by
Aaron Bohy (aab) for the web client part and
Denis Ledoux (dle) for the server part.

Part-of: odoo/odoo#87522
2022-04-29 09:57:44 +02:00
Nicolas Bayet fa796c76ad [FIX] web_editor: past mulitple lines and undo
Before this commit, when pasting multiples lines a new step per line.
So when performing an undo, only one line was removed instead of the
whole pasted text.

task-2833740

closes odoo/odoo#89932

X-original-commit: 06fb4e3e8377dedb02644779f0077e0d883df918
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-28 09:00:50 +02:00
Nicolas Bayet 444fb09d1e [FIX] web_editor: prevent crash when inserting empty string
Before this commit, when unsing the function `insert()` with data being
an empty string, the function crashed but shouldn't.

task-2833740

X-original-commit: d44302550ddc027d4891ad04bf16c364e171e5ad
Part-of: odoo/odoo#89932
2022-04-28 09:00:50 +02:00
Nicolas Bayet c40d9e513c [FIX] web_editor: make checklist work in firefox
task-2833778

closes odoo/odoo#89918

X-original-commit: e3304148035ec04f435475bbf9ba803dc630ae37
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-28 09:00:45 +02:00
Sébastien Geelen (sge) 1bec40e88e [FIX] web_editor: save editor value during urgentSave
Ensure the current editor value is set in the Odoo FieldHtml during
`commitChanges` so it can be used by the `urgentSave` when needed.

closes odoo/odoo#89916

X-original-commit: 43dfc8140760497d9f0352897d71ad49b12fd6e5
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-27 21:28:28 +02:00
Merlin (megu) 1683c0d62e [FIX] web_editor: remove command /image for portal users
The command `/image` used by portal users (in a forum post for example)
throws an access error. This fix removes this command for portal users
until master. In master, the command is reintroduced [here].

Indeed, before the new editor in v15, those restricted users could
insert an image as we were using an "in place" image upload dialog
from summernote resulting in simple base64 image added in the image tag.
This allowed to add image without creating an attachment.
But with the new editor, there is no such base64 image upload, and it
would be too tedious / risky to introduce one in stable.

[here]: https://github.com/odoo/odoo/pull/82612

opw-2648770
task-2811325

X-original-commit: e453d4c119a69f285d9a014babe485492bbe9c40
Part-of: odoo/odoo#89890
2022-04-27 21:28:06 +02:00
Nicolas Bayet ca5ddbbcd7 [IMP] web_editor: disable checklist and stars for readonly
Disable checklist and stars when the html field attribute readonly is
true.

task-2832281

closes odoo/odoo#89845

X-original-commit: 7c87495d34713cf4ea82cfeb376097d67862eb2a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-27 15:31:40 +02:00
David Monjoie 5951960bcf [REV] web_editor: revert fix onChange event
task-2832078

closes odoo/odoo#89834

X-original-commit: 50dc710363a5222098e1fea2919b6fc4ae0aee65
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-27 14:29:10 +02:00
Arthur Detroux (ard) cefaeab852 [FIX] web_editor: remove temporary color gradient element
Commit [1] introduced a way to use pre-configured gradient that included
a change to the util method _areCSSValuesEqual.
Commit [2] added lines of code to compare shadows but unfortunately
broke commit [1].

The changes of commit 2 left a lots of elements in the body of the
document.

Steps to reproduce:
- Install base database
- Find HTML field (e.g. Login as admin => preference => Email signature)
- Select text and click on Text Color
- Click on gradient then custom gradients
- Move the slider around
- Inspect the body element
- Lots of divs are there

[1]: https://github.com/odoo/odoo/commit/a48a30f954afcb6ff3a59c4f32b05fd0c2cfcd2b
[2]: https://github.com/odoo/odoo/commit/212d8ec10bb48e8fd7de3d3ff7660447b968c62a

closes odoo/odoo#89785

X-original-commit: 043dea4d8a46465f2faf3d6b93847dc2eabfde8c
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
2022-04-27 11:06:33 +02:00
Nicolas Bayet 71e98b11c3 [FIX] web_editor: disable linktool when selection not in editable
Before this commit, when the selection was not in the editable at the time
of calling the LinkTool, a link was created outside the editable, which
is wrong.

Task-2696969

closes odoo/odoo#89772

X-original-commit: 78decd6a75d6abf06177747f350871fefc84fd5a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-27 11:06:29 +02:00
Nicolas Bayet b23437e5aa [FIX] web_editor: do not correct link on empty link
closes odoo/odoo#89641

X-original-commit: db8bf3b4cc1bce3f7f160bf4d09a9842e6e0d340
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-26 11:02:06 +02:00
Nicolas Bayet f694ecc71b [FIX] web_editor: keep the selection when opening linktool
task-2750970

closes odoo/odoo#89637

X-original-commit: 56f26a0277d72f6604dac153216385d0f5a8a34e
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-26 11:02:03 +02:00
Nicolas Bayet a8109a384d [FIX] web_editor: debug collaboration _resetEditor
There are cases that seems to reset the editor content but shouldn't.
This commit:
- provide a dialog to allow the user to save his content before being
  lost forever
- reset only if the record content has changed

task-2810115

closes odoo/odoo#89625

X-original-commit: e812e923ffe040e734e4d913eceaae396adf6c3d
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
2022-04-26 11:01:59 +02:00