Most e-mail clients apply some padding around their e-mails, like
mass_mailing does in its editor. So for the plain text email template,
we mostly don't want to transfer that padding, but for Apple Mail we do
want some padding lest the e-mail be crammed in a corner. The editor's
padding was lost in conversion because the padding was applied to a
table with `border-collapse: collapse` so it was not applied (see
[mdn]).
Since we can't change that property (or layouts will be broken), our
remaining option is to wrap the layout table's contents in a `div` and
apply the padding to it instead. Since we only want this for Apple Mail,
we apply it in a nested media query, which Apple Mail is currently the
only client to support. This is the only known way to target Apple Mail
specifically but since e-mail clients tend to be remarkably slow at
adopting new technologies, this should be safe for a while.
[mdn]: https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse
task-3062027
closesodoo/odoo#162629
X-original-commit: bc84a40ff49cc82f1c6dd43ffddbffea6e211af0
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Co-authored-by: David Monjoie <dmo@odoo.com>
This commit fixes a traceback that occurs when calling `getValue` on
`wysiwyg` while the `odooEditor` instance variable is not defined for
whatever reason.
task-3600667
closesodoo/odoo#161110
X-original-commit: cb2c51aa28ade702a87bbdbb3b4eb9157a56b409
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
When applying a format in an unbreakable inline (without a class), the
format was immediately rolled back as we tried to remove split the
unbreakable in order to remove its style.
task-3768157
closesodoo/odoo#159110
X-original-commit: 78e809c18db7bd520ccf706b2504139248fbd0ff
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
A traceback was spotted when `unserializeNode` was called as a result of
a call to `resetContent`. That traceback could lead to other tracebacks
(including one when trying to read a history step's ID in
`_historyMakeSnapshot`). A traceback at that moment could remove all the
content of the editor before saving.
This commit ensures the argument passed to `unserializeNode` is defined,
that `unserializeNode` returns `undefined` if it couldn't return
anything valid, and that when such is the case the caller handles that
undefined return value properly.
task-3677431
closesodoo/odoo#158957
X-original-commit: bf062140877dabcb6db93d2a4bea2aa36f4b2601
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When typing in Japanese with Romaji input, a traceback occurred when
hitting backspace to remove the only character in the editable while the
Japanese character selection menu was open. This is because that case
triggers an `insertCompositionText` input event with an empty string,
and tries to delete the editable, which is unremovable. Since we called
`_applyRawCommand` without wrapping it in `_protect`, the unremovable
error caused a traceback instead of a rollback. When fixing that, an
other bug appeared, which was the insertion of a `#` character. This was
due to the fact that `insertText` was called with empty content, and
`insertText` defaulted to the character `#` for no particular reason
since the early proof of concept of the editor.
task-3134566
closesodoo/odoo#159005
X-original-commit: cb75212d4fe302b54097fbc90da6d6ef8b38205b
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
This adds a button to the AI Copywriter that allows the user to correct
the selected text without altering it otherwise.
task-3776377
closesodoo/odoo#156067
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When inlining styles for e-mails, some styles could be lost if they were
defined in css but also had an inline style that started with the same
characters. For example, a node with a style attribute defining
`margin-top: 10px` and a css style defining `margin: 5px` would end up
with `margin-top: 10px` and losing the rest of the information.
opw-3650141
closesodoo/odoo#156177
X-original-commit: f2d2531125af90bd2a20e0e1a5cb5e44e7b4a02b
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Steps to reproduce:
1. Type a backtick
2. Type "A"
3. Type a backtick
4. Hit Left Arrow key
5. Hit Right Arrow key 2x
This led to a traceback ("Cannot read properties of null (reading
'isContentEditable') at OdooEditor._onKeyDown") because using `nextLeaf`
without specifying the editable bounds returned a node that was not
within these bounds, and a subsequent call to `closestElement` on this
node returned `null` as a result.
task-3749506
closesodoo/odoo#154484
X-original-commit: ec1fe7b05e0d91605f78dd1844c7d2222671eab3
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
This commit fixes the problem of selection change on colorpicker fast
hover.
Before this commit, hovering too fast on the colors of the colorpicker
unselected text that would be on the edge of the selection and
uncolored. This is fixed by deep ranging the selection at the moment we
limit it to fonts. This improves the accuracy of the history as, in case
the font tag has been removed, it saves the text node as the current
selection. And since hovering updates rely on it, it prevents losing the
selection when unhovering fast (which is the cause of the bug).
We noticed two behavior when dealing with this bug. When hoving on a
color cell and exiting out of the colorpicker altogether, no bug
appears. But when switching between two cells, multiple selection issue
happen. After analysis of the performance graph, we believe that this is
due to the fact in the first case, onSelectionChange events are fired
and the handler is called, whereas in the other case it doesn't happen.
That handler particularly reacalulates the latest selection. And this
doesn't happen in our pathological case. After testing this theory, we
view that the problem is solved.
task-3295858
closesodoo/odoo#153212
X-original-commit: 9e3ee2563021b70ce64e7ec010b149820014bf8d
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
Co-authored-by: Hamza Maimoune <hmai@odoo.com>
Co-authored-by: Antoine Guenet <age@odoo.com>
Commit [1] introduced a responsive font size feature was. Following
this, in the context of mass mailing, an issue arises when users select
a font size from the toolbar dropdown. Specifically, the
`_computePxByRem` function converts the `px` value selected by the user
to the wrong `rem` value. This is because it relies on the font size of
the `html` element of the main window's document rather than that of the
iframe's document. Since the iframe's document has a font size of 14px
where the main document has a font size of 16px, the conversion was
faulty. Also, the value was cached on the window object, which is common
to both documents. So this commit moves that cache to the document so
two different values can be stored.
[1]: https://github.com/odoo-dev/odoo/commit/ddf25a16c46bfc3628512aba1390a1e345ec719a
task-3653543
closesodoo/odoo#147685
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Co-authored-by: Vishal Padhiyar <visp@odoo.com>
Co-authored-by: Dieleman Guillaume <gdi@odoo.com>
When converting a card for e-mail client compatibility, we apply the
attributes of the card's block children to their respective cells and
unwrap them. However, that's an issue if the child is an image or a link
since their respective `src` and `href` attributes are meaningless on
the cells.
task-3631900
opw-3580317
opw-3630693
closesodoo/odoo#148529
X-original-commit: d3bdb08c97ad7eab005ac185f393807df35f383e
Signed-off-by: Nicolas Bayet (nby) <nby@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
There was a condition in the `isBlock` util meant to bypass
`getComputedStyle` in the case that a node was not in the DOM. Rather
than doing that however, it was bypassing it in every case where the
node was in a document that was different from that of the window.
closesodoo/odoo#142803
X-original-commit: 04a9e97603806cb21cd90d991c0f94a225c326c5
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Link zws should not be applied on links that contain blocks so as to
avoid unfortunate side effects of zws on the dimensions of the link.
task-3596919
X-original-commit: 656fc7ca4d19311c679f6f3d3df6a4ea7e57c15c
Part-of: odoo/odoo#142803
An object was defined before a conditional return statement and as a
variable rather than a constant.
closesodoo/odoo#142049
X-original-commit: d6478d9af76422eccecffb79bfd6be90cc714342
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Signed-off-by: Nicolas Bayet (nby) <nby@odoo.com>
When reverting history removal steps, we check that the next node or the
previous node exists so we can add the removed node next to it. But we
failed to check that the node was still connected to the document.
closesodoo/odoo#141303
Related: odoo/enterprise#50304
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
The `closest` method is only available on the Element class.
`parentElement` guarantees the returned node will inherit from the
`Element` class, which `parentNode` does not. This replaces calls to
`closest` on nodes returned by `parentNode` so that they are called on
`Element` nodes instead.
Part-of: odoo/odoo#141303
To prevent history steps that include the link zws, we need to ensure
that the observer is always disabled when the link zws is inserted or
removed.
Due to these changes, we need to initialize `_currentStep` before
setting the original link zws, so that `observerApply` can access it in
the process of pausing the mutations observer.
Part-of: odoo/odoo#141303
The link isolation mechanism should not be applied in non-editable
links. It also should not be applied in Bootstrap navigation as we don't
want it to behave like a list of links and not to insert non-link
content between the navigation elements.
Part-of: odoo/odoo#141303
A Powerbox test was executed without first setting the selection in the
DOM, which caused the Powerbox to close immediately. It also omitted to
reopen the Powerbox after the first command selection, before using the
arrow keys to navigate through the commands.
Part-of: odoo/odoo#141303
We need to wait one tick after `triggerEvent` to be sure that the
event's listeners are resolved before checking the result. Some tests
did the waiting after calling `triggerEvent`, but some didn't. This
includes the waiting in `triggerEvent` itself.
Part-of: odoo/odoo#141303
When transforming an element into a checklist, we were first creating
the checklist and therefore adding the necessary class to the list
element, and then applying all the attributes of the original element to
the list. This was causing the class to be removed is the original
element contained a class attribute.
Part-of: odoo/odoo#141303
The selectionchange event is triggered one tick after the selection
changes so we need to wait for it to be triggered before moving forward
with testing.
Doing this implied correcting a test: as we were not waiting for the
selectionchange event, we were not taking advantage of some corrections
applied there.
Part-of: odoo/odoo#141303
When preserving the selection, we typically want our selection to remain
as close as possible to what it was before. But `preserveCursor` called
`setSelection` with its default `normalize` argument, which would change
the selection in sometimes unexpected ways.
Part-of: odoo/odoo#141303
`<span>` and `<font>` elements without attributes are useless and can be
removed. Removing them will make the editor output more readable and
will prevent endless nesting of attributeless `<span>` and `<font>`
elements when successively styling, unstyling and deleting text.
Part-of: odoo/odoo#141303
This adds a style on the link that currently hosts the selection, to
make it clear that the next character input will happen inside.
Part-of: odoo/odoo#141303
This replaces the link isolation mechanism with a more robust one that
doesn't require setting the `contenteditable` attribute on the editable
to `false` (which is rife with issues). In so doing, we also improve the
handling of selection at the edges of links, making a clear distinction
between the selection being inside the link or outside of it.
Note: we only do this for collapsed selections, as it's not clear what
should happen when the selection is not collapsed.
task-3103566
Part-of: odoo/odoo#141303
Some editor tests may be sensitive to the existence or not of a
selection in the DOM before initializing the editor. The first test to
be run won't have a selection before the editable is initialized, but
every subsequent test will (removing the test node add the end moves the
selection to its parent). One particularly problematic consequence
concerns tests that would fail with an initial selection but succeed
otherwise. Such a test would only fail when run after another test, but
not when run alone.
This commit prevents this confusing debugging situation (and potential
false negatives) by setting a selection at the beginning of the testNode
by default before running each test, ensuring that each test has the
same initial conditions.
Part-of: odoo/odoo#141303
The editor mobile tests are making wrong assumptions about the way the
editor behaves on mobile and are therefore wrong. This temporarily
disables them until the discrepancy is resolved.
Part-of: odoo/odoo#141303
The timeout for calls to the OLG API in the editor was set to 300
seconds, which is far too long for a chatbot. This reduces it to 30s.
closesodoo/odoo#141135
Signed-off-by: Nicolas Bayet (nby) <nby@odoo.com>
This rearranges the non-floating toolbar buttons so that the AI, animate
and highlight buttons are grouped together at the bottom and take up the
full width of the toolbar, and so that the options appear below them.
task-3572337
closesodoo/odoo#139857
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
When selecting an alternative in the AI Copywriter dialog, what we store
in the state is the index of the message. But that targets a different
message every time we add each new message at the start of the list.
This pushes new messages at the end of the list and only displays them
in reverse order, but also adds an ID to each message so they can be
targeted more robustly.
Part-of: odoo/odoo#139857
When inserting generated content in the editor, a frame is added around
the content to highlight it for a moment. This frame was not properly
positioned in the website builder. This also restyles it to match the
style of the "DRAG BUILDING BLOCKS HERE" frame.
task-3572397
Part-of: odoo/odoo#139857
With this commit, opening the ChatGPT alternatives dialog still
generates three alternatives, but whenever the user clicks on one of the
buttons:
1. one new version is generated (rather than three)
2. this new version is added at the top of the list (rather than
replacing everything)
3. older versions are showed in grey so as to differenciate them from
the new one
4. a badge next to each version shows which instruction was used to
generate it (shorten, lengthen, etc.)
Since we add new versions from bottom to top, the spinner is now shown
above the existing versions.
Since a badge is added, it's not necessary to keep the last used button
green anymore so once the AI is done generating the new version, the
button returns to its blue state.
task-3572397
Part-of: odoo/odoo#139857
This implements a way to abort the generation of a batch of alternatives
by the AI Copywriter. This is needed because if a batch was being
generated when the user clicked one of the buttons to select a mode, it
continued to be generated and to update the state while the new batch
was in the making, resulting in a potential total of more alternatives
than requested.
task-3572397
Part-of: odoo/odoo#139857
Sometimes, ChatGPT includes a little intro text (eg, "Sure, here are
some alternatives:") to its answer. This avoids this as much as possible
by improving the system prompt and asking to wrap the answer in tags
that we then remove.
task-3572397
Part-of: odoo/odoo#139857
This commit implements a dialog for content generation using ChatGPT,
which can be opened via the Powerbox or via a button in the toolbar.
If text is selected, the dialog opens in "alternatives" mode. In this
mode, five alternative versions of the selected text are generated. The
user can choose one and it will be inserted in lieu of the selection.
Five buttons can be used to guide the AI to make the content longer,
shorter, more professional, more friendly, or more persuasive. Clicking
any of these buttons will restart the generation process with the new
parameters.
If no text is selected, the dialog opens in "prompt" mode. In this mode,
the dialog contains a textarea in which the user can input a prompt
which is then used to generate content. The user can then exchange with
the AI back and forth until the content is satisfactory. Any of the AI's
responses can be inserted into the document by clicking its "Insert"
button.
When content is inserted into the document, a green frame is shown
around it for two seconds, to make it clear to the user that something
has been inserted and where.
If an error occurs, it is inserted in the dialog like other responses
but in red and it can't be inserted into the document.
Please find the PR of the IAP part (Odoo Language Generator) here :
https://github.com/odoo/iap-apps/pull/703
task-3383324
closesodoo/odoo#137064
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Co-authored-by: Antoine Guenet (age) <age@odoo.com>
Co-authored-by: Lou (loha) <loha@odoo.com>
The `insert` command was splitting the selection's starting text node
only if the selection was collapsed. But after deleting the range, the
selection is inevitably collapsed and therefore the same should be done.
closesodoo/odoo#138549
X-original-commit: 06a375db7e6250b388d410010a3d1c50e8af1326
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Test HTML being inserted for the utils tests was not cleaned at the end
of the tests.
X-original-commit: 092cee52b343665ea3ca90e4f4aa302318a763b5
Part-of: odoo/odoo#138549
This adds a few tests for `getState`, `restoreState` and
`enforceWhitespace`, regarding the handling of space visibility. Each
test handles equivalent cases for all three functions.
X-original-commit: 2f28f42640a7322eec35a4d48a1ec7ce287b77b3
Part-of: odoo/odoo#138549
This adds an option to log information in prepareUpdate flows for
convenient debugging.
X-original-commit: 3ec104d57e9b6bbe210f45354f160d982a9c6254
Part-of: odoo/odoo#138549
This adds a label to the prepareUpdate function to be able to easily
track which update is being restored when debugging.
X-original-commit: 5bb8a5a9b5d54ebe93c473087981e3464cd61368
Part-of: odoo/odoo#138549
When pressing delete on "[a] b c" the result is " b c" instead of
" b c". As result, text is rendered as "[]b c". The cause lies in
`deleteRange`: it ensures trailing spaces remains visible, but does not
take care of eventual invisible leading spaces. This adapts it to make
use of `prepareUpdate` which is made to handle this sort of issues. In
so doing we need to adapt `getState` and `prepareUpdate` to handle the
special cases brought by `deleteRange`. An option is introduced in
`prepareUpdate` to prevent its reentry until the update is complete (as
otherwise we may restore invalid intermediary states in the middle of
the deletion process).
task-3143042
X-original-commit: 8fd69afa591d11afe07da803ec550f052402713f
Part-of: odoo/odoo#138549
When sending a mailing we make sure to preserve comments (in particular
so that MSO comments can be read by Outlook). However this was not the
case when testing a mailing using the Test button in the form view.
task-3488162
opw-3290548
opw-3479234
closesodoo/odoo#133998
X-original-commit: 66b1dc38ced221d63f11827a217f9805827d5e65
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
The Mail Debug tab is confusing for users and should only be used by
people who know what can or cannot be expected from it. It is not
providing a good preview of the e-mail's rendering since the HTML it
displays is not meant to be rendered by a browser but by all sorts of
e-mail clients. This means that some things that render properly in it
won't necessarily render properly in some e-mail clients, but also
likewise that some things that don't render properly in it will in fact
render as expected in e-mail clients. This is why it's only available in
debug mode but since many users routinely enable debug mode to get
access to hidden features, this is not enough to prevent them from
reporting issues that are not issues.
closesodoo/odoo#133208
X-original-commit: 240ee9deb898f4346a9bc66548c881fc69e8b117
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When converting an email for compatibility with email clients, we move
the contents of the editor iframe inside a new iframe, keeping only
what's in the iframe target element. But we failed to remove the sidebar
and other UI utils elements, which are irrelevant to the conversion.
Additionally, failing to remove the sidebar from the conversion iframe
made the snippets' images load again when committing changes.
task-3323894
closesodoo/odoo#126845
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Images in mass_mailing are not lazy loaded, which is deliberate for the
mailing itself and its conversion, but when we load the sidebar we add
the HTML to all the snippets and hide it so if these images are not lazy
loaded, they all get loaded along with the sidebar, which is slow and
unnecessary.
This loads the images only once we add them to the mailing, which is
when we remove the lazy loading attribute.
task-3323894
Part-of: odoo/odoo#126845
Summary:
page with 2 popups (newsletter popup and regular popup), cookie
bar all justaposed. Chatbot window also open. For some reason
closestBlock(testedNode) is undefined (testedNode) is a #text
Node. Change already in place for 16.3
Cause:
no preventive measure for null value before creating
a node iterator on the value.Node in dom does not have
an ancestor of type block.
Solution:
backport solution from 16.3, return false when currentNodeParentBlock
is null, since preceding and following would also be undefined,
return false.
opw-3395673
closesodoo/odoo#132590
X-original-commit: 8a72f669813bc7d8aa9038d75e08ecef00b70e01
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Co-authored-by: Pedro Manuel Calheiros Lima de Sousa <peso@odoo.com>
Relative image urls have to be replaced with absolute urls in order to
be able to display them in the email. This failed to be done for urls in
styles attributes if they were enclosed in (unicode decimal) single
quotes.
opw-3452655
closesodoo/odoo#132339
X-original-commit: d952e0117a68dd19e86c45ae75250807231e82ad
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Base64 img src were converted to inline images but background images
were omitted. This commit fixes that.
opw-3374767
closesodoo/odoo#129645
X-original-commit: a10d1d305696f7ece38e7d3446c067338c411ea2
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
We currently convert rgb colors to hexadecimal, but not rgba colors.
Unfortunately since many Bootstrap border colors are defined as rgba,
this meant that these were not properly converted for Outlook (which
doesn't support rgba).
To convert rgba while losing the transparency information we need to
"flatten" it by taking in consideration the background color.
closesodoo/odoo#129153
X-original-commit: dc56506cffa5a13508ca24018d4f0a25c5353cca
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
The `font-family` style can sometimes include double quotes. This isn't
really a problem since these get escaped (`"`) but emailonacid
currently has a bug where the double quotes cause every subsequent style
to be ignored, and the rendering to be incorrect. For the sake of future
testing, this converts them to single quotes. It also removes the style
entirely from image elements since they don't make sense there.
X-original-commit: 03c7e69db63f326c7a3b3085debc5d3a5c95966d
Part-of: odoo/odoo#129153
A semi-colon unfortunately took the place of a double pipe in code that
retrieves an image's width in order to set its width attribute. This led
to some images being wrongly sized.
opw-3299392
X-original-commit: 0a21da39f05ef9ec9d202424e0e648849f44e164
Part-of: odoo/odoo#129153
On a products category page, there is an element ready to host a heading
but it's not explicitly marked as unremovable so when the user tries to
remove any snippet inside it, the heading host is removed as well. This
fixes it by using the `isUnremovable` utility function instead of simply
checking for the `oe_unremovable` class.
Steps to reproduce the issue this commit fixes:
1. Go into the website module
2. Click "Shop"
3. Click "Furnitures"
4. Click "Edit"
5. Drop a title block in "Drag building blocks here to customize the
header for "Furnitures" category."
6. Click the trash bin on your snippet to remove it.
It doesn't get removed. Well now it does.
task-3383348
closesodoo/odoo#128744
X-original-commit: d1836d2830d098e2c29cca2643b0b354859daeca
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When converting a row with items that are supposed to be stretch-aligned
we need to set each of its column's height. However this failed when
the row contained less than two columns.
opw-3371134
closesodoo/odoo#127813
X-original-commit: 7df4cc0d9aaccf0dabcc4a7863549b276efaa403
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When converting inline svg shapes to images, we checked if the source
ended with ".svg", which is not enough, as it can include query
parameters (eg, .svg?color=red). We now simply check if it includes
".svg" instead.
We also need to make sure we didn't make a clone of the image in an mso
before converting it, as the source wouldn't get converted in the mso.
closesodoo/odoo#125839
X-original-commit: 3e9fa219ce612875aa034d95080f9cca1f972d27
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When picking a mailing template, the size of the contents of the iframe
changes but we failed to signal it so the iframe could resize as well.
closesodoo/odoo#125820
X-original-commit: 387c4fb815a802e6138671a22864dac97a490365
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
When a scrollbar appears in the sidebar, the toolbar could end up being
to wide, making a horizontal scrollbar appear. This commit makes the
toolbar buttons smaller (smaller padding) to avoid this.
closesodoo/odoo#119972
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
With this commit, when a user clicks on the font size number in the
editor's toolbar, two things happen:
1. Same as before: the list of recommended sizes opens.
2. The current font size is selected, and the user can type any value
they want. They need to confirm with "Enter" or blur the input to use
a custom value.
task-3167041
Part-of: odoo/odoo#119972
When clicking on an input in the toolbar, the selection was lost and
the commands could not be executed. This restores the latest selection
in the editable in these cases.
Part-of: odoo/odoo#119972
When sanitizing the content of the editor, we sometimes move up too far
and sanitize nodes that are not in the editor. This adds the proper
boundaries required to contain the sanitization.
closesodoo/odoo#124803
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
In several places, `convert_inline` uses `classList.toggle('c', true)`
to set classes. This is not a good practice, as it's not clear what the
state of the class is. It's better to use `classList.add('c')` since
this anyway checks whether the class is already present or not.
closesodoo/odoo#124465
X-original-commit: 43afc5a5a30530bc3ede9f0a46249977a7896b5a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
Outlook needs explicit dimensions for images, which .img-fluid - by
design - doesn't provide. This puts them in mso conditionals with said
dimensions for Outlook.
X-original-commit: d0949de8ce895b7da5fd128fb5d72d23d5634866
Part-of: odoo/odoo#124465
Before this commit, the main image of the newsletter template had a set
width which doesn't do anything because it gets overridden by CSS, but
it confuses the conversion process.
X-original-commit: c23fe6dc5efe46990a5473f696966a2774ae16d4
Part-of: odoo/odoo#124465
The `_wrap` util function of `convert_inline` was not checking if
`className` and `style` were defined before adding them to the wrapper
element, leading to things like `<div class="undefined">element</div>`.
X-original-commit: 9fd6e069d07c3f7964511af7289d95c970d11b3e
Part-of: odoo/odoo#124465
This ensure the layouts of emails don't get distorted in Outlook when
the user is using DPI scaling (typically, some elements get scaled up
while others don't).
X-original-commit: 2348efb6e22544d82ce53d542975f334d5553f62
Part-of: odoo/odoo#124465
Firefox doesn't seem to do well with sibling tables, so we need to
wrap them each in separate rows.
X-original-commit: 625a6545ee9e64a90e36b676c5b7b9a3c8d42418
Part-of: odoo/odoo#124465
Bootstrap rows have negative left and right margins, which are not
supported by GMail and Outlook. Sometimes we use padding on columns to
undo the negative margins of their child rows. This corrects these.
X-original-commit: dc7c7330b4b7a1c17c3b736aa60c21882a455a31
Part-of: odoo/odoo#124465
Before this commit, the line-height of the body was not properly
inherited where it should. It is defined as a CSS variable and its value
was incorrectly retrieved (if the value is 1.5 and the font-size is
10px, `getComputedStyle` returns 15px instead of 1.5). Other properties
related to fonts were likewise improperly inherited.
X-original-commit: 12ae698bd9aff8466d69819e0b849752f967c126
Part-of: odoo/odoo#124465
This addresses a series of alignment issues in the conversion of html.
X-original-commit: 5b5a0030f8cd75f0a977d7804b54dc454a6a8751
Part-of: odoo/odoo#124465
This addresses a series of issues regarding images, their responsive
behavior and their alignment.
opw-3244705
opw-3185231
X-original-commit: e20bc14e8860ce8f84eb5b0006ec67b708530161
Part-of: odoo/odoo#124465
Base64 images get converted to attachments. However, if they are in a
mso comment, they were not converted.
X-original-commit: 2fa0694227a7beb6a000c2e8219fdd8c073cf348
Part-of: odoo/odoo#124465
Prior to this fix, elements with background images were converted to
images via the html2canvas library. This made them work in Outlook at
the cost of several tradeoffs:
- the process was slow and asynchronous
- there could be no interactivity (links, buttons, etc.) in the
converted element
- responsive behavior was wonky: if only a slice of the image was shown
when it was converted (due to background-size cover behavior), the
rest was lost so if more width was needed in mobile, we would be
zooming on that slice, making it sometimes irrelevant and pixelated
This replaces all that with a conversion to VML, which is a vector
format supported by Outlook. This conversion is done only for Outlook,
which means that all other clients are getting the original background
element again.
There is a way to keep the background-size cover behavior in VML, using
the "aspect" attribute with value "atleast" but this only works on
v-fill elements and sadly putting the image on a v-fill element bugs in
Windows Mail (which is the default mail client on Windows 10 and 11) and
this client can't be singled out of mso conditionals. To get around this
issue, since this is only for desktop clients, we assume the width of
the screen to be large and mimick the cover behavior by cropping the
image to the target size. This allows us to put the image on the v-image
element and have proper rendering in Outlook and Windows Mail on
desktop.
Note:
When retrieving the image by URL in Python in order to crop it, we need
to ensure we have an absolute path. This is done - perhaps seemingly
naively - by checking if the URL contains '//'. Here's the reasoning
behind that choice. To check if a URL is absolute, we could use
`urllib.parse.urlparse` and check if it has a scheme but that would lead
to `www.odoo.com/path` being considered relative (and thus we'd add a
host to the URL even though there's already one). Instead, we could
check it it has a netloc but that would lead to the same issue since the
documentation of `urlparse` says:
> Following the syntax specifications in
[RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808.html), urlparse
recognizes a netloc only if it is properly introduced by ‘//’.
Still, it would be more technically correct since `//some/path` would be
considered absolute (which it should be since it resolves to
`<current_scheme>//some/path`).
Base on that documentation, it seems that simply checking if the URL
contains '//' is pretty much equivalent to checking if it has a scheme,
with the double advantage that it's simpler and that it works for
`//some/path` as well. However, note that it doesn't solve the issue of
`www.odoo.com/path`.
In summary, here are the results with the current method:
```
http://www.odoo.com/path -> http://www.google.com/path // OK
some/path -> http://localhost:8069/some/path // OK
/some/path -> http://localhost:8069/some/path // OK
//some/path -> //some/path // OK
www.odoo.com/path -> http://localhost:8069/www.google.com/path // WRONG
```
X-original-commit: 9561ba31917024825705c876442139405e7a7957
Part-of: odoo/odoo#124465
Several issues were found regarding the responsiveness of columns,
especially in the Masonry snippet. This implements a new, more robust
approach to responsiveness of columns, based on article [1], where each
column is wrapped inside a new table, itself wrapped in an inline-block
div element, and all adjacent wrapped columns are in turn wrapped in a
common table cell:
```html
<.container>
<.row>
<.col id="A">
<.col id="B">
</.row>
</.container>
```
becomes something like:
```html
<table>
<tbody>
<tr>
<td>
<div style="display: inline-block;">
<table>
<tbody>
<tr>
<td id="A">
</tr>
</tbody>
</table>
</div>
<div style="display: inline-block;">
<table>
<tbody>
<tr>
<td id="B">
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
```
with some additional attributes and styles to make it work.
[1]: https://www.litmus.com/blog/mobile-responsive-email-stacking/
task-3184107
X-original-commit: 3ddba4dbd57891c2d9fc80fb7aa0dd08338fe3f6
Part-of: odoo/odoo#124465
Conversion of some masonry grids caused unexpected responsive behavior,
leading to a result that didn't match the edited design. This was caused
by a few separate issues:
1. Sometimes Masonry declares rows with a height of 100% but with
columns that overfit the grid. In these cases, we split the rows into
multiple rows but we failed to adapt their heights for them to be
divided equally.
2. A call to `setProperty` failed silently, making it so the height was
never set on certain rows.
3. When converting background images, we failed to remove their padding.
4. Bootstrap grid media queries were only inlined from the xl breakpoint
and up, but the snippets typically use the lg breakpoint.
5. The "o_desktop_h100" class was not applied to the parents of
`.o_desktop_h100` cells, making the rows too big for their cells in
mobile.
6. A combination of the above made the conversion fail when the masonry
snippet had a non-automatic height.
task-3184107
X-original-commit: 04d1c0caeb78ee3bedff579e229e5da47c2689ce
Part-of: odoo/odoo#124465
This adds two util functions, to create mso and !mso comments (which can
be error-prone).
X-original-commit: e258a28aa147db97eab1d3dc5db3595adf91541c
Part-of: odoo/odoo#124465
This addresses a series of issues with mso conditionals that were not
closing in the right places.
X-original-commit: 247e05a9cca403fca3de01feb49d0f0374ea38de
Part-of: odoo/odoo#124465
One of the list tests had two "end of selection" characters in its
content before and after the step function. This made it unclear which
was relevant and which wasn't.
closesodoo/odoo#111119
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Superfluous zero-width spaces were removed by the sanitizer and then
upon saving (`cleanForSave`). This commit removes the code dedicated to
that from the sanitizer in favor of the code in `cleanForSave` (adapted
to cover all cases).
Note: this means that with this commit, superfluous zero-width spaces
are not removed from the editor during edition anymore, but only when
saving.
task-3081457
Part-of: odoo/odoo#111119
When cleaning zero-width spaces (ZWS) in the editor, we were replacing
the node values of all text nodes descending from the node we were
cleaning, regardless of whether they contained a ZWS or not. This could
lead to wrong selections in the tests when arbitrarily changing the
value of a text node in the selection.
Part-of: odoo/odoo#111119
Since commit [1], the state of the editor in the html field is only set
to dirty when the user triggers an input event. This means that if the
user uses the mouse to change the content of the field (eg, drag and
dropping snippets), the editor is not marked as dirty so the save button
will not appear and autosave will not work.
This commit fixes this by checking the editor's dirty state whenever a
history step event is triggered. Since this reverts commit [1], we need
to ensure the bug it fixed does not reappear. This is done by ensuring
we don't check the saved value against the modified editing value when
it's empty (namely, the editor doesn't allow an empty string as a value
and replaces it with `<p><br></p>`, which we need to undo in
`_isDirty`).
task-3263653
task-3288416
opw-3274329
[1]: https://github.com/odoo/odoo/pull/113088/commits/095bbb93d6c3b9b0b099b7ed1a6a15e8ad914e9fclosesodoo/odoo#122628
X-original-commit: db0c092973f480f3336a44e5f6868dc5a79f0e3a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
When double-clicking on an image in an html field, display it "full
screen" (similar to clicking on an image in the attachments list). This
replaces the current behavior (which is to open the media selector to
replace the current image - the Replace action remains available in the
toolbar).
In the toolbar for images, display an icon that users can click on to
open the full screen preview as well.
task-3109331
closesodoo/odoo#119625
Related: odoo/enterprise#40450
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Since the attachement viewer was moved to core, this renames it to file
viewer to decouple it from the Attachment model/concept from the mail
module.
Part-of: odoo/odoo#119625
The `mail` module's `attachment_viewer` is useful for more than `mail`
alone. In order to be able to use it in the `web_editor` module (which
doesn't depend on `mail`), we move it to the `web` module.
task-3109331
Part-of: odoo/odoo#119625
Commit [1] defined a value for the `onWysiwygBlur` option of `Wysiwyg`
in the `mass_mailing` `html field`. This had the side effect of
overriding the value set by its parent `html field`, which was to call
`commitChanges`. As a result, the `mass_mailing` `html field` was not
saving its content on blur. This restores that behavior by explicitly
adding the call to `commitChanges` where it was missing.
[1]: https://github.com/odoo/odoo/commit/e212e873eb35eb9b9a931fb1521109475c008074
task-3288881
closesodoo/odoo#121231
X-original-commit: 817d494e4eaa29983f75d4f3d6754ef3c3cc6e51
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
When clicking on a button from the link popover, the popover gets
hidden, which pauses the editor's mutation observer until the popover is
fully faded out. This is problematic when the button in question calls
an editor command which we need to be able to undo, since the mutation
observer will still be paused during the command execution. This lets
the buttons' listeners handle the hiding of the popover themselves to
prevent this race condition.
closesodoo/odoo#118248
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Before this commit when a button containing a text then an icon was
unlinked in Chrome, all further buttons were also unlinked (see steps
below).
It turns out this bug is due to the browser's `execCommand`
implementation so this commit reimplements the feature without relying
on it.
Steps to reproduce (in website module):
* drop Text+Image snippet twice
* inside first button type /image and insert a pictogram after the text
* click on the text of the first button => the link popover appears
* click on the unlink button of the popover
=> both buttons become flat texts in Chrome
=> nothing happens visually in Firefox, but the <a> actually gets
turned into a <span>
task-2778912
Part-of: odoo/odoo#118248
Co-authored-by: Antoine Guenet <age@odoo.com>
Co-authored-by: Benoît Socias <bso@odoo.com>
This removes the `clearEmpty` util which was only used in the `enter`
command.
closesodoo/odoo#114178
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This removes a parameter in `isVisible` that made it consider (wrongly)
all blocks as visible. This made it confusing to use because it was
effectively returning fake news by default.
Part-of: odoo/odoo#114178
When pressing enter at the end of a heading, we want to insert an empty
paragraph instead of a new heading. This failed when the paragraph had
a zero-width space in it because we didn't recognize it as empty.
closesodoo/odoo#116558
X-original-commit: 228e7937f818f5606601e575b1d9a2bb87cda99d
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>