* web_editor
This commit's goal is to optimize the delay to make a scss customization
thanks to the website customize dialog. Before this commit, the JS code
took advantage of existing web_editor routes but this was far from
efficient as this was done:
1) PY: Load all scss files used in the page
2) JS: Find the one we want to customize and adapt the scss content
3) PY: Create the scss customization with the new content
(So two RPC (including one very slow) and content building in
javascript)
After this commit, this is done:
1) PY: Load the scss file being customized, adapt its content according
to the new values and save the customization
(So the whole logic is in python, requiring only one small RPC)
This commit also take the opportunity to review the web_editor ace
editor loading code (the logic is shared with website customizations).
PR https://github.com/odoo/odoo/pull/29624
task-1904244
* web_editor
Currently, when an user wants to edit the css of its website, he has
access to lots of files and, in debug mode, to even more files. While
the feature is nice for people who know what they are doing, a lambda
person can easily break its website by changing the wrong files. Also,
nothing warns the user that the files that are edited will never receive
updates anymore (unless if they are reset). The goal is to prevent
those behavior while still allowing the add custom css. Another goal
is to be able to *add* custom javascript.
Custom files created for the user:
SCSS: user_custom_rules.scss, user_custom_bootstrap_overridden.scss
JS: user_custom_javascript.js
See https://github.com/odoo/odoo/pull/29999
task-1919350
Before this commit:
1. If we were editing a template with no xml_id, typically the case when
editing a specific view (COW'd), the 'Template ID' label would be left empty
as the view does not have an xml_id but only a key.
2. If we were editing a generic view, the template would be COW'd and replaced
by the specific one created during the save.
After the save, the page would be reload and will try to reopen the edited
template (stored in url `res=123`). But as this template would be replaced
by the COW'd view, the JS would crash trying to access an inexisting view.
The HTML editor would then open in a very thin modal, barely editable.
Now:
1. Display the template's key instead of its xml_id. The key is basically a
duplicate of the xml_id, mainly used in website.
2. If we are saving a generic view, we search for its newly created specific
view to upload the URL hash before reloading.
task-1934279
Fix#30447
Modifying less files and saving them using the web editor can raise
and error. The error is due to the way odoo save the modified file.
It extends the view containing the URL of the file by filtering views
related to the xml bundle id and keeping those that have the said URL
in their content.
This lookup fails to give just one result in case there are multiple
file containing the said URL. This fix change the filter from a
bare `if url in view.arch` to a correct xpath lookup.
The "/web/static/src/variables.less" less file was one of the
problematic files.
opw-1889794
closesodoo/odoo#30186
While creating a new record, the default value of a field used with the
'html_frame' field widget was not used.
Discovered with task-1903256
closesodoo/odoo#28838
Odoo no longer supports python 2, thus some of these helpers can and
have been replaced by python 3 built-ins, therefore there is no need for
them to stay defined.
The removed helpers are:
* izip, imap and ifilter
* unichr, text_type
* implements_to_string, implements_iterator
* string_types, integer_types
* to_native
The python 2 shims have also been removed, and only the python 3 helpers
have been kept, because they can still be usable (i.e. accepting
both bytes and str for functions that can only accept one of the two)
[REM] pyjsparser: remove PY3 shims
They're no longer necessary as Odoo doesn't officially support python 2
anymore.
closesodoo/odoo#28519
This commit replaces calls to pycompat helpers that were intended for
python 2 <-> python 3 interoperability for python 3 builtins, as python
2 is no longer officially supported by Odoo.
This includes:
* calls to imap/izip/ifilter replaced by map/zip/filter
* uses of text_type replaced by str
* uses of unichr replaced by chr
* calls to implements_to_string, implements_iterator removed
* string_types and integer_types replaced by str, int respectively
* calls to to_native replaced by calls to to_text
This is done in preparation to the removal of these deprecated helpers
in the following commit.
* Creating a new structure by transforming all the plugins in the
library using the odoo inheritance system. Plugins are easier to
implement with the AbstractPlugin to add Odoo behaviors.
* From now on, the methods of the library (in this case Summernote) can
no longer be called by other modules or files. Only the wysiwyg
widgets can access it, to simplify the updating process. The wysiwyg
object serves as an interface.
* Depending on the options the snippets will be loaded or not, the
editor will be in an iframe or not... all of this is transparent from
the outside.
* Regarding iframes, all controllers related to editing have been
removed: the new API no longer needs them. This speeds up loading,
eases testing and removes complexity for the same
features.
PUBLIC FEATURES
There are several public methods on the Wysiwyg class:
* Wysiwyg.prepare (WidgetParent): returns a deferred resolved when the
library (xml, lazy, assets...) is loaded.
* Wysiwyg.getRange (DOM): returns the range (selection in the dom)
* Wysiwyg.setRange (startNode, startOffset, endNode, endOffset): creates
a range (selection in the dom)
* Wysiwyg.setRangeFromNode (DOM, options) that creates a range from an
element (option available to select all, start or end)
A jQuery selector was added: :o_editable, which indicates whether the
current element is editable. That is, if it is contained in a tag with
the attribute 'contentEditable = "true"' or in a tag with the class
o_editable.
Several methods are also present:
* focusIn: makes a focus and places the cursor at the beginning of the
element
* focusInEnd: makes a focus and places the cursor at the end of the
element
* selectContent: makes a focus and selects the content
HTML FIELD
The HTML field can receive different options:
* style-inline: {boolean} transforms a class into an inline style when
saving and vice versa when reading.
* no-attachment: {boolean} prevents the use of attachments (in media
dialog)
* cssEdit: {xml_id} to use a template containing the css to loaded in
an iframe when editing
* cssReadonly: {xml_id} to use a template containing the css to load
into an iframe when viewing in readonly
* snippets: {xml_id} snippets template (can be used with or without
cssEdit)
* wrapper: {template} qweb static template (containing a tag:
id = "wrapper") that will include the content during editing (removed
on save)
MASS MAILING
A widget was created for mass mailing. There are now two fields:
body_html and body_arch.
body_arch contains the code with the class without conversion into
inline style, useful when editing and one with the inline style that is
visible in readonly mode and sent by email.
Advantage: no spreading errors, able to update css/theme, able to do
more changes when converting to inline style so that a maximum of mail
clients have an impeccable rendering.
Co-authored-by: Antoine Guenet <age@odoo.com>
* base, website
An image URL may be like "/web/image/<xml_id>" where <xml_id> is the
xml id of an ir.attachment. In fact, the route does not use the xml_id
but the 'key' field, which is normally equal to the xml_id for standard
attachment. In the context of themes + multi-website, the value used as
an xml_id may refer to a theme.ir.attachment instead of an ir.attachment
and this led to a bug as those must not be used the same way.
The crop route which gets image information is adapted by this commit to
always look for the *current website* *ir.attachment* related to the
given xml_id/key.
Thanks to @kig-odoo for spotting the issue.
Closes https://github.com/odoo/odoo/pull/27588closesodoo/odoo#27611
* web_editor, website_blog, website_crm_partner_assign, website_links,
website_livechat, website_mail_channel, website_mass_mailing,
website_slides
Calling a model's method thanks to an RPC will now always send the
web_editor context automatically, making sure the method gets the
website_id all the time, removing the need to guess the current website
(now the get_current_website method uses the context website_id if any).
Note: other routes already have the website_id via request.env.context
if they correctly set website=True (this commit also adds website=True
for scss files customization routes).
Before this commit, the view create by editor (to change the scss file in asset for example) was not website specific.
Now we override (use the new hook method) to add the website_id.
With multi-websites, we expect qweb views to have a key set as it is the key
that is used to find duplicates (two views with same keys are duplicate, the
one with a website_id set is more specific than the one without a website_id)
Thus, 5ff87e8039 sort on key in order to find the most suitable one.
It would crash if a qweb view is created without a key (False) as it can't sort
`bool` and `str`.
This commit:
- Adds a generated key to scss views
- Adds an SQL constraint to avoid QWeb views without a `key`
- Generates a random key when creating a QWeb view without a `key`
- Handle False key in `filter_duplicate()` by extracting views with False key
before sorting, and then adding these views to the recordset
Note: We also want the key to be editable as it is now an important field with
multiwebsite. Thus, we removed the readonly on this field.
+ fix python tests as we now force key on qweb views with sql constraint
+ pep8
From now, when you install a theme, it load the data from xml to template
table theme [ir.ui.view|ir.attachment|website.page|website.menu].
Data are only copied from this template table into the real table when you
choose a theme on a website; Making them website_specific and with a link
to the original to allow futur update.
A special case is done to create theme.ir.ui.view when you are installing
a theme, even if you continue to use template tag to create quick view.
Co-authored-by: Derie Romain <rde@odoo.com>
Co-authored-by: Kersten Jérémy <jke@odoo.com>
* survey, website_slides
Before this commit, the web_editor app created bg and text classes its
own way for theming (alpha, beta, grays, ...). Now the system is far
more automatic by extending BS4 color maps.
Previous implementation was wrong as it did not care about the ability
to discard a crop edition. Indeed, whenever a crop dialog was saved,
a crop attachment was created or updated at once. Discarding the editor
would then either:
- Seem to discard a first-time cropped image but would have created an
attachment for nothing (just the image src was reset)
OR
- Fail to discard a second-time cropped image as the cropped attachment
would have been directly updated and the image src would not have
changed
This commit changes the way it works:
- On crop dialog save, the image is marked with required data for a
potential future save of the cropped image (as a DB attachment) and
the src is set to the base64 cropped image directly.
Note that the code ends up being clearer and efficient that way too.
Before this commit, if the user opened the LESS editor and emptied a
file, he may get a compilation error (as intended if the file contained
necessary variables and stuff) but this error also prevented to open
the editor again because some code tried to decode an empty content.
Now, when a file is emptied it is set to an unique line feed.
Before this fix, when a user don't have write access on a document, he
can't send an email with attachment because, the attachments is added on
the document.
The change improving security was introduced by the commit:
https://github.com/odoo/odoo/commit/6494f511718893eec3573c60c0a62e04d386359d
With this fix, for mail, the attachments is added on the
'mail.compose.message' and re-render the fields attachments displayed in
the current view. This change respect the access rules like all others
attachment of 'mail.compose.message' (can send an email when the user have
read access on the document).
The media dialog of the html widget display all documents attachments and
the added attachments Allowing users to use these in the body of their
message.
- Set the demo user to have access to all quotations
- Connect as demo, create a quote and send the message
- In the message try to upload an image
An access error is raised, although the user can write on the record.
This is because the `res_id` received is a `string`, not an `int`.
Therefore, the access check fails.
Introduced with 6494f51171
opw-1824673
The access_token is automatically added by the media editor. It's added
on the website and by the html editor to send by email. The widget display
the attachments from 'ir.ui.view' (public attachment) and the attachment
from the current record.
Issue: can't load image in gmail or mobile because the client mail use a
proxy who avoid ours odoo access.
- Remove useless snippet background suggestions (only one button to
open the media dialog directly)
- Show meaningful-only tabs in the media dialog (no document as
background, ...)
- When editing a background shows the background suggestions first and
show the background suggestions last for standard images. Technically,
this is done by filtering on the name/fname of the attachments and
adding magic name parts to the fname on image upload (e.g. when
uploading an image from the media dialog when customizing a bg, the
uploaded image will automatically be marked as a background). Note:
there were discussions to implement this feature with a tag system for
ir.attachment/s but the implementation's cost was too great in regards
to the feature.
- When editing an existing link or creating one from selected text, do
not show the "Link Label" field in the dialog; it was confusing. Only
show that field when adding a link at the cursor location with no
selected text.
* remove references to basestring & unicode (use relevant pycompat
helpers)
* remove some str calls (either entirely or replaced by relevant
helper, either text or native)
* use better API to avoid unnecessary conversions
* remove some XML declarations in views
* StringIO removed from stdlib, replace with io
* try to correctly handle BytesIO/StringIO (one is for bytes the other
is for text)
* fix base64: Python 3 removed bytes-encoding and bytes-bytes
codecs (via #encode) so replace all calls to str.encode('base64'),
also b64encode is a bytes->bytes conversion so attempt to properly
handle that
issue #8530