Steps to reproduce:
- install website, website_mass_mailing
- go to website, edit and add a popup window (you should see warning banner stating
that a newsletter popup is present on this window). Save.
- go to settings > languages > load a new language (fr_FR for example) and translate
the website
- go back to the website > select the new language > click the TRANSLATE button
Previous behavior:
the warning banner is not editable, also click the "Edit popup" button does nothing
Current behavior:
clicking the "Edit popup" button triggers an alert with
a quick explanatory text
opw-2280188
closesodoo/odoo#53988
X-original-commit: af57e4924dbd432f9362881dae71d2a4e4595a1f
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: mightyjol <jhk-odoo@users.noreply.github.com>
Previously, duplicating a block inside of the newsletter popup would
cause the subscribe input and button to disappear. Actually, it
disappears when you use most options of the left panel, because
selecting an option refreshes the public widgets, which destroys them
and starts them again, but for some reason, the subscribe widget's
destroy method makes it d-none, but only removes that class if the
subscribe input is not inside of a modal.
This commit fixes that by not using d-none on the subscribe input group
at all. We keep the d-none removals for databases which may have the
button saved in a disabled state.
task-2244780
closesodoo/odoo#53927
X-original-commit: 5562e7dbf5205c9b3ea0ef2d5283f3ccc5fbc30e
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
* = base_setup, website_form, website_sale, website_crm,
crm_iap_lead_website, website_hr_recruitment, website_mass_mailing
Integrate reCaptchaV3 on website_form submit and website_mass_mailing
subscription.
You can now use ReCaptchaV3 to add reCaptcha verification in any module
using google_recaptcha.
Also added a better error management on the form with custom messages.
task-2217980
closesodoo/odoo#48466
Related: odoo/enterprise#9649
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Clearly display to the user which newsletter is currently being used by the
Newsletter Block. Currently when editing the block it displays the first
available newsletter by default. This is confusing for the user that may
think its block was badly configured.
It now clearly display the current chosen newsletter.
Task ID #2192807Closes#47959
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
When the newsletter popup was introduced, the modal was for some reason
marked with the o_editable class, which is normally used to let the
editor know which elements in the page can be edited and saved in the
database. Because of this, upon saving with the modal in the page (ie,
if the modal is open when saving) it would try to destroy the editor
associated with the modal, which doesn't exist, resulting in a
traceback.
This commit fixes that by removing the o_editable class from the modal,
this doesn't actually prevent edition, because the modal is already
inside of an editable segment of the page.
task-2092593
closesodoo/odoo#50080
X-original-commit: 856d21cef530a9393bcebbf314a9316934ffb7c7
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
* website_blog, website_event, website_form, website_mail_channel,
website_mass_mailing, website_sale, website_twitter
+ Reorganize the order.
+ Do not promote apps via snippets when they already are promoted via
the "New" menu. Also do not promote apps in the same snippet section
more than once.
Part of https://github.com/odoo/odoo/pull/42937
task-2088157
* website, website_mass_mailing
Instead of triggering an event on the invisible element when its related
button in the left panel is clicked, the invisible element's options are
now toggled (shown if were hidden and hidden if were shown). To do that
the new 'onTargetShow' and 'onTargetHide' methods are called, and the
appropriate action can be done there.
Those two new methods are also automatically called in other cases:
- When dropped in the page, after onBuild, 'onTargetShow' is called
for any snippet.
- Before cleanForSave: 'onTargetHide' is called for snippets with the
'o_snippet_invisible' and 'onTargetShow' is called for the others.
In case the element visibility should be toggled another way (like the
close button of a modal), the option can trigger_up an event named
'snippet_option_visibility_update' with a 'show' parameter so that the
the UI is updated accordingly (and so that the options are hidden if
necessary).
Part of https://github.com/odoo/odoo/pull/41789
* website, website_mass_mailing
Now, when any option method is called (editor left panel), the widgets
related to the targeted DOM is automatically updated. This is possible
to disable for a specific widget with `data-no-widget-refresh="true"`.
This commit also makes the `_refreshPublicWidget` method better handle
its async component: it is now "fully async" so the caller should wait
for its resolution before executing some other related code.
* website, website_mass_mailing
We only have one invisible snippet (newsletter popup) which is handled
by adding a yellow alert in the DOM in edit mode to be able to click
somewhere to open the snippet options.
As we will add some new invisible snippet (generic popup, cookies bar,
and probably more) this needed to be improved.
Now, any snippet having the `o_snippet_invisible` class will have an
entry in the left panel in a dedicated zone to edit itself. This also
allows to get rid of the yellow alert, making sure that "what you see
is what you get" in the editor zone.
task-2150966
closesodoo/odoo#41420
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
The issue here is, the modal for the newsletter is part of the editable area,
and when we click on the 'close' button of that modal, it is destroyed but the
'summer note' tries to bind the events related to the button(because close is a button).
fixed the traceback, to disable invoking 'summer note' events on click of
the 'close' button on modal
task-2075232
X-original-commit: 110ea837903f3e6c67c1d0e0081073edea8852d1
In the backend, when a mailing popup was being edited, it was not
centered in the edition area (and went under the editor UI) and was not
using the correct style.
task-2083465
closesodoo/odoo#38449
X-original-commit: 6ccf3b618b4b0774deccb4f75bf33f3ea4dc8b75
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
* mass_mailing, note, website, website_blog, website_form,
website_mass_mailing, website_sale
This commit, unfortunately, mixes three things:
- Restoring as much as possible the scss organisation to allow styling
the web_editor UI properly.
- Fixing some bugs like a border around the page once the editor is
loaded, no ability to scroll the snippets, etc
- Introducing a whole new UI for snippet options: a left panel instead
of the old dropdown & button overlay.
Note: this commit also do some linting and ES6 convertion even though
some of it has been done in the parent commit.
Note 2: some elements that were removed are still styled in the POS apps
but this is because part of a feature was removed while leaving dead
code behind, this is handled in another PR which is to be merged
(https://github.com/odoo/odoo/pull/36136).
Part of https://github.com/odoo/odoo/pull/36068
task-1942370
closesodoo/odoo#36068
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
PURPOSE
Mass mailing is currently a bit messy. As SMS will be added as a way to notify
people in mass through SMS let us take this opportunity to somehow clean this
application: organization, light code cleaning, model renaming.
SPECIFICATIONS
Rename mail.mass_mailing.list and mail.mass_mailing.list to mailing.list
and mailing.list.merge. Rename mail.mass_mailing.contact to mailing.contact.
Rename mail.mailing_list.list_contact_rel to mailing.contact.subscription.
Rationale :
* those new names are easier to understand: mailing.list and mailing.contact
are less mail-related, especially taking into account that SMS will allow
to be less mail-oriented;
* those names are easier to read / find / understand;
* align wizard and sub-models naming with the main naming;
* have a mailing as first part of namespacing;
MIGRATION
mail.mass_mailing.list model -> mailing.list
mail.mass_mailing.list.merge model -> mailing.list.merge
mail.mass_mailing.contact model -> mailing.contact
mail.mass_mailing.list_contact_rel model -> mailing.contact.subscription
mail_mass_mailing_contact_list_rel table -> mailing_contact_list_rel (specific
case of a decorated m2m)
fields updated (no column change)
* mailing.list: subscription_contact_ids -> subscription_ids
LINKS
Task ID 2037906
Preparing task ID 1997464 (SMS addition in mass mailing)
PR #34938
* website, mass_mailing, web_editor
This commit adds various improvements in newsletter snippets as follow:
- Improves UI for newsletter popup.
- We only had one popup for all websites. Now, we can have a different
popup for each website.
- The popup was not appearing on mobile/tablet devices. Now, in
mobile/tablet devices, the popup appears automatically after 5secs.
- Added the ability to customize the whole editor popup like any
editable area (background colors, etc).
- User needed to enable popup snippet from the settings. We removed that
setting so now popup snippet will always be available.
- Added new snippet "Newsletter block".
- Display notification after successful subscription the same way for
all newsletter snippets.
Closes https://github.com/odoo/odoo/pull/29353
task-1903256
closesodoo/odoo#29353
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
* website_blog, website_crm_partner_assign, website_event,
website_event_track, website_form, website_forum, website_links,
website_mail, website_mail_channel, website_mass_mailing,
website_sale, website_sale_comparison, website_sale_delivery,
website_sale_stock, website_sale_wishlist, website_slides,
website_twitter
While using the 'Animation' class of website instead of the frontend
'Widget' class leads to the same behaviors, this refactoring is done for
two reasons:
- Stop using the confusing 'Animation' name for non-animated behaviors
- Instantiation of 'Widget' is slightly faster than 'Animation'
Part of https://github.com/odoo/odoo/pull/29442
task-1932066
* portal, sale, web, website_blog, website_crm_partner_assign,
website_forum, website_event_track, website_links, website_mail,
website_slides, website_mail_channel, website_mass_mailing,
website_sale, website_sale_comparison, website_sale_delivery,
website_sale_wishlist
The `editableMode` option and its related options in public widget
should only be part of website, this commit moves them there. This is
also the occasion to implement something that is long overdue: stop
creating 'animations' / public widgets in edit mode by default. Indeed,
lots of 'animations' were defined by beginning with 'if not edit mode'.
Now, if a public widget should be considered in edit mode, it must be
defined explicitely through a property at *definition* of the widget.
Part of https://github.com/odoo/odoo/pull/29442
task-1932066
* 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>
The refactoring of the wysiwyg editor and 'html' field allows us to
move some of the code that was in web_editor but only used in website or
in mass_mailing. Some parts are still in web_editor but will be
moved at a later time.
Compatibility: rebuilding a correct modal from user database content.
Since the first version, the modal is saved in databases directly but
has never used a correct structure. While it was working with BS3, it is
not with BS4. This was breaking the design and prevented the modal to
be able to close.
task-1889341
closesodoo/odoo#28589
* 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).
Purpose
=======
- Apply the blacklist implementation to Improve mailing subscription to be more
compliant with the European GDPR law. Keep a list of people who does not want
to receive promotional emails (or mass mailing in general) anymore.
- Allows the recipient to update himself his mailing preferences
Specifications
===========
This commit is regrouping some main changes on mass mailing.
Apply Blacklist for following models through blacklist.mixin :
- crm.lead
- res.partner
- mail.mass_mailing.contact
- mail.channel.partner
- Opt_out per mailing list instead of per mailing contact.
- Replace opt_out by blacklist in crm.lead + res.partner models
- Added 'ignored' state for mass_mailing. Ignored = blacklisted, opted-out
Ignored email are not included into final statistics to avoid confusion.
- Unsubscribe(d) pages migrated from website_mass_mailing to mass_mailing module
as thoses pages should work without having the website module installed
Detailed implementation
===================
Mass-mailing :
- A blacklisted email is notified by the ban icon next to the email field.
(at the left of the email field for display purpose)
- Renaming the '_get_blacklist' method that was actually
searching opt_out list into 'get_opt_out_list'
- Opt out per mailing list : Add opt_out + related fields (for display and
ergonomy reasons) on the relational model
- Display relational model tree view instead of mass_mailing.contact tree
view when clicking on mass_mailing_list in kanban view
-> In order to be align between contact_nbr displayed in kanban tile and
the content of the tree view
-> mass_mailing contact is accesible via the user icon in this tree view
- Remove custom filters 'filter_contact_subscription' and
'filter_contact_unsubscription' as opt_out is not on mass_mailing.contact
model anymore
- Add 'is_public' to mailing list
The name of this mailing list can be seen (or not) by recipient in
the unsubscription page
If the mailing lists used in the mass mailing are not public,
the user in only informed that he has been unsubscribed.
If the mailing lists are public, the user is informed that he has been
unsubscribed from the mailing lists
and he has the choice to modify his subscription to all the public
mailing list he is or was subscribed to.
- Unsubscription Page :
- mass_mailing_contact :
Opt_out per mailing list, done by email and not by id, as multiple
contact can have the same email
The recipient can add/remove himself to/from the blacklist
The recipient can send a feedback about why he unsubscribed
- crm.lead + res.partner :
Once the recipient unsubscribe, he is automatically blacklisted
The recipient can 'Come back' and remove himself from the blacklist
if he changes his mind
- Show blacklist button parameter added in config :
The idea is to enable/disable the fact that the recipient can add
himself to the blacklist by showing or not the 'blacklist me' button
Only applies for mass_mailing.contact. The recipient, once
blacklisted, can always, no matter the value of this parameter,
'come back' and unblacklist himself
crm.lead + res.partner :
- Replace opt_out by blacklist in crm.lead + res.partner models.
As when a res.partner or crm.lead unsubcribe, we assume that the recipient
does not want to receive mass mailing anymore, at all, even if we adds him
to a mailing list afterwards. He is then blacklisted to avoid this.
With this behaviour, if a new lead is created with the same email address,
he won't be able to receive mail in mass_mode.
But he will still be able to receive '1 to 1' direct email.
Task ID 33224
Closes#25966
The 'form-horizontal' class have been removed; the '.form-group'
elements must now use the 'row' class for an horizontal layout.
The 'control-label' class was renamed to 'col-form-label'.
The 'help-block' class was renamed to 'form-text'.
The 'has-error' and 'has-success' classes have been removed and
replaced by a new system using the :valid and :invalid pseudo-classes,
when a parent has the 'was-validated' class. While this system is great,
it is not straightforward to use it in Odoo. Fortunately, BS4 provides
the 'is-valid' and 'is-invalid' classes as fallback. This commit
replaces the 'has-error' and 'has-success' classes by 'o_has_error' and
'o_has_success' classes (for JS compatibility) and use the 'is-*'
fallback classes. (The 'has-warning' class has no equivalent but was
unused in Odoo anyway).
The input-group-addon class has been replaced by a combination of the
input-group-text and the input-group-append/prepend classes. The
input-group-btn class is replaced by the input-group-append/prepend
classes.
The system completely changed. I also had to adapt classes to new
screen breakpoints.
hidden/hide -> d-none
show -> d-block
hidden-xs -> d-none d-md-(block/inline/...)
hidden-sm -> d-md-none d-lg-(block/inline/...)
hidden-md -> d-lg-none d-xl-(block/inline/...)
hidden-lg -> d-xl-none
visible-xs-* -> d-* d-md-none
visible-sm-* -> d-none d-md-* d-lg-none
visible-md-* -> d-none d-lg-* d-xl-none
visible-lg-* -> d-none d-xl-*
hidden-print -> d-print-none
visible-print-* -> d-none d-print-*
...
and all possible combination of those had to be handled too.
* mass_mailing, payment, point_of_sale, portal, survey, web, web_tour,
website_blog, website_crm_partner_assign, website_event,
website_event_questions, website_form, website_forum, website_gengo,
website_hr_recruitment, website_links, website_mail,
website_mail_channel, website_mass_mailing, website_quote,
website_sale, website_sale_options, website_slides, website_twitter
This commit reviews the whole "JS side" of the web_editor and website
apps. This is a first step to be able to improve them with new and
better functionnalities; this commit is not supposed to change any
visual behavior.
The main goal was to achieve a structure similar to the backend one.
Now, the frontend side also has a root widget (like the WebClient)
and all other widgets are attached to it one way or another. This allows
the benefits of using the 'trigger_up' functionnality for example.
As RPC are now mainly done with the `this._rpc` functionnality (being
possible thanks to the parent hierarchy), the frontend will also be
possible to test thanks to QUnit in a future update (besides the "text"
editor side which still requires a refactoring to be able to do that).
---
Here are some of the changes:
(-) conventions and documentation
The code has been updated to follow JS conventions and a lot of code has
been commented (around +2000 lines of comment). This also means that
lots of functions have been renamed to use camelCase or simply to make
their name understandable.
See https://github.com/odoo/odoo/wiki/Javascript-coding-guidelines.
(-) deprecated: web_editor.base
The "web_editor.base" module has been split and does not force the
modules which require it to wait for DOM ready anymore. This was indeed
slowing loading times, but also prevented to use some modules in some
contexts (see the LESS editor use in web_studio which is the subject of
another task).
Now the "editor context" can be got thanks to the "web_editor.context"
JS module with its "get" function.
The "web_editor.base" module should probably not be used anymore (see
its code and recent updates).
(-) new: web.dom_ready
If a JS module should wait for the DOM to be ready to be executed, a
new JS module has been created: "web.dom_ready". This should always
be used in a module which only want to instantiate stuff. Do not
extend (or worst, include) classes after DOM ready.
(-) website.website
The "website.website" module has been split. "website.website" does not
return anything useful anymore, it just initialize some miscellaneous
stuff, without waiting for the DOM to be ready. You might want to check
"website.utils", "website.content.compatibility" or `WebsiteRoot`. Also
`website.form` has been deleted (use `this._rpc`), so has been
`website.error`. `website.prompt` will be removed in a future update to
be replaced by `Dialog.prompt`.
(-) widgets are great
Many classes which were not widgets are now widgets. This allows them to
use the 'events', the 'xmlDependencies' and the 'this._rpc' features for
example. Here are some of the main ones:
- Snippet options: these were classes with a `$el` for the menu element
and `$target` for the customized element. This is still the case
but following standard `Widget` structure (one exception: using
`this.$(...)` searches in the `$target` as before this update).
- Snippet animations: instead of class instances with a `$target`
element which can be `start` and `stop`, these are now standard
widgets which can be `start` and `destroy`. `this.$target` is
an alias to `this.$el` for ease of compatibility.
- Snippet editors: instead of class instances in charge of an editor
overlay, these are now widgets. Each "child" snippet editor is
properly attached as a "child", which allows editors to communicate
and to be properly destroyed.
(-) root widgets and website navbar
The frontend is different of the backend. In the backend, the page has
an empty <body/> element and all the components are instantiated from
parent to children (i.e. the `WebClient` is instantiated and is in
charge of instantiating the `ControlPanel`, etc). The frontend cannot
work like that on page loadings as they are way more frequent than in
the backend and we do not want them to flicker. A frontend page is
loaded as a <body/> element which already contains the website navbar
and its menus and the whole content page. JS code has to be "attached"
to these existing elements. This is possible thanks to the `RootWidget`
instances and the specialized `WebsiteRoot`, `IframeRoot` and
`WebsiteNavbar` (see code for details).
(-) lazy loading
No more (or at least a lot less) XML/JS has to be loaded on page
loading, thanks to the use of the `Widget.xmlDependencies` feature.
XML which have to be lazy loaded is loaded only on related Widget
instantiation if necessary, which allows to execute a lot of JS code
before the DOM is ready and to start many widgets on DOM ready (not
later). A visual benefit of this is clicking on the 'edit' button as
soon as it is possible: before this commit, this was sometimes not
doing anything as event handlers were not binded yet.
Still a possible exception: loading the session and locales. This may
be asynchronous stuff which is still required before widget
instantiations but this will be the subject of another task.
(-) deprecated code and code location
More than reviewing code and organizing it, many apparent dead code was
removed. More importantly, mislocated code was put in the right app.
This is the case for snippet animations which is a concept for website
apps but was defined in the web_editor app, or some translation concepts
which were part of website but should have been part of web_editor.
---
There are probably more things to say about this commit but I will let
the comments speak for those.
* mail_channel, mass_mailing, twitter, event
- t-install attribute holds the technical name of the module that
needs to be install to use a particular snippet.
- Disable the drag & drop feature for these dummy snippets.
- Move some images to website module.
- Installed snippets display at the top of the list.
- Hide not-installed module snippets if user don't have rights to install module.
The RPC system was not completely satisfactory, we decided to prepare
the future and do it properly. This commit introduces the new rpc
system, which replace the previous new one. We now simply have a
method, this._rpc, which takes a dictionary of parameters. The idea is
that depending on the parameters, it is able to add correct default
value when necessary.
For situations where we don't have the this._rpc method, we can use the
rpc.query method, which takes the same arguments, but directly calls
ajax.rpc instead of triggering up some events.
Commit 9676ceec02 removed/replaced image files in mass_mailing
module but two of them were still used by website_mass_mailing.
This commits adds these two images in website_mass_mailing module and
use a more standard convention to define associated snippets and
link them in the snippet panel. Also lint JS files.
The "edit" action is on the "website.TopBar", which will create a new
instance of the "editor" (web_editor.editor) widget.
So if we want to do something when the "editing" start, we have to
either override "edit" of the TopBar, or override "start" or "init" of
the editor.
opw-657662
`mass_mailing.unsubscribe` depends on
1. `web.ajax`, as it uses `ajax.jsonRpc`
2. `web_editor.base`, to explicitely wait
for all dependencies to be loaded,
so the DOM can contain `o_unsubscribe_form`
opw-654396
Each module can return a deferred. In that case, the module is marked as loaded
only when the deferred is resolved, and its value is equal to the resolved value.
The module can be rejected (unloaded). This will be logged in the console as info.
Remove if_dom_contains from the website, the modules return a rejected deferred if
the DOM doesn't contains the seleted values.