Commit Graph
257 Commits
Author SHA1 Message Date
std-odoo 91979b0fcf [IMP] http_routing, website_slides: redirect the user on /slides on AccessError
Purpose
=======
When a user tries to reach a course, an AccessError can occur when we
unslug the URL. Instead of the traditional error page, we want to
redirect the users to /slides, and the error will be displayed there.

Task-3477630

closes odoo/odoo#135926

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-09-25 09:38:33 +00:00
Lopes Marc (loma) a23b9089ac [IMP] website_*: improve profile view
*= forum, profile, slides, slides_survey

Purpose
=======
Give users a better experience when browsing website profiles
looking for courses, certifications, forum questions, ...

Specifications
=============
Add search bars for Questions, Answers and Upvotes, small UI changes
here and there.

Task-2676848
Based on #79372

Co-authored by: Fabio Barbero <faba@odoo.com>

Part-of: odoo/odoo#129123
2023-09-11 22:41:03 +00:00
Saurabh Choraria a85bc31c04 [FIX] website_slides: prevent traceback while accessing archived embedded slide
When user archive a slide from a course and try to access route
'/slides/embed/<int:slide_id>' of that particular slide, user get the error.

steps to reproduce:
    1. Go to Website and click on courses menu.
    2. Open a course and archive a slide in it.
    3. Then go to '/slides/embed/<int:slide_id>' route.
    4. Access that particular slide that you have archived in route.
    5. The error will occur.

Applying this commit will fix this issue.

sentry-4025579653

closes odoo/odoo#128797

X-original-commit: c097112109fb2de003242bda89e10e656236b774
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-07-18 11:42:39 +02:00
amdi-odoo 1dc8d10310 [IMP] website_slides: auto-collapse categories
Purpose
=======
Improve the behavior of the collapse/expand categories
in front-end for large courses.

Specifications
==============
In channel content view and channel fullscreen view:
- When following the course, expand the ongoing section and
collapse the other ones.
- When the section is completed, open the next one and
keep the previous one(s) opened.
- If an attendee leaves and comes back, only open the ongoing one.

Task-3284195

closes odoo/odoo#121003

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-06-16 19:30:41 +02:00
Jay Savaliya e1f1767491 [FIX] website_slides: prevent auto-marking videos complete
When user will open the video in any course, it will be marked as completed
directly which behaves like any other content(pdf, image). This behavior was
introduced when 'slide_view' was modified in https://github.com/odoo/odoo/commit/4c291fe30468dab7cef9d2e5a0377c78484f5045, but in the case of video,
it must not be marked as completed before the video is watched up until(near)
the end, as per the previous behavior.

Task-3346507

closes odoo/odoo#125128

X-original-commit: 488ce25425f71733abc3aa7b32f299d6abf48055
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-06-15 09:05:24 +02:00
Patrick Hoste 8e8f1be6a7 [FIX] website_slides: fix multiple course review bug
Before this commit, it was possible for one to post
multiple reviews when all the already posted reviews
had the 'Employee Only' state. A traceback was also
thrown when trying to update an 'Employee Only'
comment. It was also possible to edit a log note.
This commit fixes all these issues.

Task-2810085

closes odoo/odoo#121052

X-original-commit: 2e4f8ff553b11ecae444933aa2b9fab6175e64ef
Signed-off-by: Stéphane Debauche (std) <std@odoo.com>
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-05-12 09:21:52 +02:00
Noe Antoine 69277f846e [IMP] website_slides : add attendee status, improve invitations to course
RATIONALE

Improve and make easier the invitations on courses, whatever the enroll policy.
The goal is to increase the number of attendees easily

PREVIOUS BEHAVIOUR

Before this commit, the attendees of a course were always enrolled.
No distinction existed. Inviting partners meant enrolling them at once, even if
they did not want to join. Also, invitations to a 'members only'-visibility
course were a problem since the invited member could not reach the course page
if not logged in. Therefore the invitation link in invitation mail was often
not usable (403 error). The invitation link did not act as a user creation link
if the partner was not linked to any user

PURPOSE OF THIS COMMIT

After this commit, attendees to a course can either be enrolled (default behavior)
or have pending invitation, allowing to preview the course before joining it.
Also, the invitation links redirect the partner according to their (potential)
linked user, their log in status and the ACL's. All course completion and
invitation status are covered by the new member_status selection field for attendees:
- 'invited' : member with pending invitation
- 'joined' : enrolled member, not started
- 'ongoing' : enrolled member, started but never finished
- 'completed' : enrolled member who completed the course

A) INVITATIONS: ADD ATTENDEES and INVITE

The way to add and invite attendees to a course attendees in now centralized in
two options, the buttons for which being added on the course forms / kanban cards
dot menu. On the attendee list view coming from a course, only the [NEW] button
is shown (= ADD ATTENDEES). Using the buttons will open the invite wizard. (the
same one, the difference being the value of the new boolean enroll_mode)

In both cases, when sending a link to a given partner, it will contain both a hash
based on the couple (partner_id, channel_id) and the value of partner_id. This will
allow giving access to the invited partner even if not logged in and for all visibilities

    1) INVITE: copy the course link OR add partners as 'invited' + send them an email

    This new option is meant for promotional purposes. It will give a preview access
    to potential new members, but will not add them as enrolled. It will send an
    email to partners not already in the active attendees, to invite them to check
    the course

    Clicking the invitation link will lead them on the course page, where a [BANNER]
    will explicitely ask the invited partner to LOG IN or to SIGN UP depending on
    them having a user or not, and explain them that they must first be logged to
    access previews and join / buy the course. Before that, they can only see a
    [PREVIEW] of the course: browse the list of contents (i.e. categories are available),
    to allow them to see whether the course is of interest (forum / reviews are hidden
    too). If they are logged, or once they are logged, they will see the course as if
    it were public, no matter its visibility. (they can join - buy - browse previews)

        [LOG IN / SIGN UP] links (see /identify route): they will bypass the value of
        the 'Free Sign Up' setting and route will 1) check the invitation values
        (hash, partner_id), and that there exists a matching attendee for the current
        course. 2) prepare the signup / login. This prevents the invited partner from
        being locked outside of the course, not being able to join it (as not able to
        create user)

        ENROLL policies:
        -> 'on invite': inviting is considered as granting access. The partner will
            not have to ask for access again, but will be able to join in directly.
        -> 'on payment': users will NOT be able to join the course without buying it.
            The buy button on the course page will be replace by [LOG IN / SIGN UP].
            We do not want them to buy a course and potentially be locked out.
            (further work should deal with the generic case of this issue.)

    2) ADD ATTENDEES: add partners as 'joined' and send them an email

    This option is the same as what existed before: partners are added as enrolled
    attendees and invited by email. When they click on the link, they will be able
    to create an account if they do not have a user, or to log in if they have one,
    whatever the visibility, BEFORE being redirected to the course. They are enrolled,
    so they need to log in in order to use the course. 'invited' members will also be
    enrolled and upgraded to 'joined' and sent a joining email.

    3) About (archived) ATTENDEES and COMPLETION:

    (From task 2199207 on, attendees are now archived instead of deleted, in order to
    keep track of progression. Status and completion updates must be dealt with when
    using invitation / adding attendees)

    Now, [ONCE 'COMPLETED', ATTENDEES REMAIN SO], whatever slides they mark as
    uncompleted / completed or is created / archived on the course. Karma for
    finishing the course is won only once. test_attendee_course_completion_values
    is added. Even archived, we never recompute completion (remains 100) and status
    of 'completed' members. The same is true for 'invited' members, we do not make
    any update. This means that archived 'invited' members can have positive completion.

    In addition to the obvious (recompute status and completion when completing a slide
    as 'joined' or 'ongoing'), we only recompute member_status and completion when
    enrolling an attendee as 'joined', in the method _action_add_members with
    member_status = 'joined'. We explicitely recompute the values then. This happens
    on joining (possibly from an 'invited' state), on adding members as 'joined', or
    when unarchiving a record at least 'joined'.

        3.1) Archived with progress:

        When inviting an archived member with progress, we set their member_status
        to 'invited', and unarchive them. It means that completion could be > 0 for
        active (or inactive) 'invited' members. When enrolling them, we set them to
        'joined' but we need to recompute their completion to update the completion
        value (there may have been changes in the contents) and their member_status
        accordingly.

        3.2) Archived as 'invited' (no progress):

        When inviting them, we simply unarchive them. When enrolling them, they are
	unarchived and set to 'joined', status and completion being then recomputed.

	3.3) A complex and full example.

	Attendee A completed the course C, having 4 contents. member_status is
	'completed' and completion = 100. Then A leaves the course and is archived.
	Later, C gets 1 more content. The member_status and completion do not change.
        A is invited. Its member_status is now 'invited', and completion 100. 3 contents
	are archived. Again, values do not change. A clicks the link and enrolls. It
	is added as 'joined' and _recompute_completion is called. completion is set
	to 50% and status to 'ongoing'. As the completion was 100 but is not anymore,
        the karma for completing the course is lost. They see the new slide and are
	set to completion = 100 and 'completed', winning the course karma back.

B) ACCESS RIGHTS UPDATES

    1) PREVIEW:
    In order to give access to 'members only' courses even without logging in, we
    use the url parameters invite_hash and partner_id. They can access as sudo the
    course but _can_publish and _can_upload stay False. Categories can also be clicked.
    No slides are accessible, only the course page, checking the access values each time
    the channel route changes. See _get_channel_values_from_invite for all the checks on
    the direct invitation parameters invite_partner_id and invite_hash)

    The breadcrumbs and routes are updated to use channel_id instead of slug (since it
    would lead to a 403 error) The course_id routes should only be used in the context of
    an invitation. (generic or direct). Also, the main channel route now checks the access
    rights to the course and redirect to /slides if the access is not granted, useful for
    the generic invitation.

    2) ACLS
    - Slides: invited members to 'members only' courses now have the same access as
    anyone for public courses: previews and categories, once logged in.
    - Course: invited members have access to the course
    - Self-enroll: 'invited' member can self-enroll to 'on invite' courses, this is done
    with a sudo on the /join route.

    3) About ARCHIVED ATTENDEES. [FIX] (tests included)

    (*) In task 2199207, the ACL's were not updated to prevent archived members to have the
    same rights as if they were active. This is because the active value is not tested by
    default in rules. It is done by changing partner_ids into a computed field search method.

C) MODELS

    1) SLIDE.CHANNEL.PARTNER
    - new: invitation_link computed field. It generates invite_hash with course and
    partner_id and contains invite_partner_id as well, used for verifications.
    - recompute_completion will always recompute the completion %. However, member_status
    will only be updated if not currently 'invited' and currently active. One should write
    'joined' on attendees before in order to see the status of an 'invited' member updated.

    2) SLIDE.CHANNEL
    - channel_partner_ids / partner_ids keep the meaning of enrolled attendees/partners.
    partner_ids is now replaced with a compute field, and channel_partner_ids has a
    domain on member_status. search method is implemented (*)
    - new: channel_partner_all_ids / partner_all_ids also includes invited attendees /
    partners. partner_all_ids is also a computed field. search is implemented (*)
    - new: is_member / is_member_invited are computed fields to indicate the current
    user's membership status to the course

    - _action_add_member is removed and _action_add_members now centralizes the logic of
    adding an attendee. It will now return all NEW ACTIVE MEMBERS for the given status.
    The ones unarchived, the ones created, and the ones enrolling from 'invited' state
    for parameter = 'joined'. Therefore, reinvitation of 'invited' members in dealt with
    in action_invite in slide.channel.invite model as they will not be returned.

    3) RES.PARTNER
    As a rule of thumb, the fields and display are the same as before. They cover the
    courses partner is enrolled to. Changes are done to ease the search on partners:
    - slide_channel_ids keeps the same meaning: the courses the partner is enrolled to.
    It is changed to a compute field since we do not want to consider 'invited'
    members. search method is implemented
    - new slide_channel_all_ids contains all the courses: the ones the partner is
    invited to or enrolled in
    - Most compute methods are centralized in a single method and read_group is used.

D) VIEWS AND OTHER MAIN CHANGES

INVITE WIZARD
    - As a course can be only shared via its generic link, the invite wizard now has
    a [TOGGLE] 'send_email' that is visible for public courses and allow to either
    copy and share the generic link, or, if toggled, show and use the email composer.
    - if course is not published, a warning alert message is shown at the top. In
    order to have a clean UI, the form is restructured using a sheet
    - The course field is now hidden and is directly shown in the title of the wizard

ATTENDEE LIST VIEW
    - [NEW] button when coming from a course (i.e. not for reporting), acting as the
      [ADD ATTENDEES] button
    - new columns

OTHER VIEWS
    - Pivot and graph reporting views are added. A default member_status groupby too,
    on all reporting views. The % of completed slides is not used as measure on pivot
    view. However, it is on the graph view to compare completion of different members
    easily. Avg is used as an operator, as sum of percentages does not mean much here
    - Attendees kanban view update and new filters / group by's
    - Quicksearch 'Tags' and 'Responsible' on slide.channel model

MISC
    - Use 'course' instead of 'channel' in readable labels
    - Use 'attendee' instead of 'member' in readable labels
    - Error mgmt: clicking the invitation link may lead to an error, as well as
    accessing a course without the rights. The user will be redirected to the main
    /slides page with the appropriate error message
    - Add a new template similar to the one used to join a course, but for the
    invitation action
    - New template for the popup appearing when joining a course. (Login or Signup)
    - Use fstrings and t-attf when possible
    - Use native js instead of jquery
    - New placeholder if no contents on course page in the front-end
    - Markup is used when possible

E) Invitation Expiration

As the invitation could be used as a promotion tool, there may be a lot of records
created as 'invited'. In order to monitor that number, we use a garbage collector.
It will remove attendees as 'invited', active or not, with completion = 0 and invited
for the last time at least THREE MONTHS before (at least invited once). Also, an
invitation older than 3 months will become expired and will not grant access to
'invited' members.

In order to track the invitation dates, a new field last_invitation_date is added to
the slide.channel.partner model. Every time one invites an attendee, it is set to the
current date. One can reinvite attendees and send them an email more than once. This
may prevent the invitation to be collected by the GC. If not set, last_invitation_date
is considered as expired.

F) TESTS and TOURS

Extensive tests and tours are added for the different new flows coming from
this new distinction between joined and invited members, and invitation flows.
They test functionality, UI, security (access rights) and model correctness.

--- Links ---
Task-2508019
COM PR - odoo/odoo#70291
UPG PR - odoo/upgrade#2572

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-05-04 19:09:49 +02:00
Noe Antoine dc8b0011e0 [REM] website_slides : remove deprecated enroll route
Removes the route slides/channel/enroll, (slides_channel_join_http method).
The attendees are enrolled in front-end through slides/channel/join,
used in different places through the Join channel button and javascript.
The old route is not used anymore.

Task-2508019
COM PR - odoo/odoo#70291
2023-05-04 19:09:49 +02:00
Denis Ledoux e113d0dd6f [FIX] core, website_slides: incrementing public views
There was two issues regarding the slides public views counter

1. If the `public_views` is set to `NULL` in database,
`increment_fields_skiplock` wasn't properly incrementing the count.
Indeed, in SQL, doing NULL + 1 returns NULL
```sql
16.0=# SELECT NULL + 1;
 ?column?
----------

(1 row)
```
To have the result we expect, COALESCE must be used
```sql
16.0=# SELECT COALESCE(NULL, 0) + 1;
 ?column?
----------
        1
(1 row)
```

2. There is a mechanism, using the session,
supposed to prevent incrementing the public views
counter when a same user visits multiple times the same slide.
However, since 84d17e57e8
the visited slide was never actually added in the session,
because it was adding the slide id in a copy of the set
in session rather than adding in the set from the session.
Or, as this commit does, to re-assign the new set in the session.

closes odoo/odoo#119370

X-original-commit: fa5962d6f08979017842985004b3ec43416ee181
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2023-04-24 20:09:38 +02:00
Andro Gvivradze 46be6f583b [IMP] website_slides: improve quiz ux/ui
This commit improves ux/ui by adding the slide
description on top of a quiz and offering links to additional
resources if the user gets questions wrong.

task-3246366

closes odoo/odoo#117530

X-original-commit: a551f956f05bf7b6782e04a95351bf2d0a0a6610
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-04-04 13:35:32 +02:00
Thomas Josseandstd-odoo 0ffa2d64ba [IMP] gamification, website_forum, website_slides: karma tracking improvement
Purpose
=======
Some users found a way to farm karma points, so we want to be able to
track the source of the karma gain / loss.

Specifications
==============
Now, we added a reference field `origin_ref` which store the record
responsible for the karma gain / loss (e.g. a slide we just completed).

In addition to this origin, we also have a new field to store the
reason (e.g. "Slide completed") so we know exactly what happened and
how the user gains his karma.

Before, the `old_value` of the karma tracking has to be set manually,
but now it's done automatically based on the value of the previous
tracking of the same user. That way, it will simplify other part of
the code.

Add the karma reason in the website modules. Adapt those modules due
to the changes in gamification.

Task-2234179

closes odoo/odoo#76430

Related: odoo/enterprise#23702
Related: odoo/upgrade#3299
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Co-authored-by: std-odoo <std@odoo.com>
2023-03-06 17:47:09 +01:00
Benoit Socias fb9efde4f3 [FIX] *: replace werkzeug's Response by odoo's Response
*: base, http_routing, mass_mailing, web, web_editor, website_slides

In some situations `werkzeug.wrappers.Response` are used instead of
`odoo.http.Reponse` that extends it.
This is a problem because since [1] the calls to `set_cookie` expect it
to accept the `cookie_type` parameter, which is not the case in the base
werkzeug implementation.

This commit replaces the `werkzeug.wrappers.Response` by
`odoo.http.Response`.

[1]: https://github.com/odoo/odoo/commit/2cbda6c98ee947cea1d06c09880eee8c758304a8

closes odoo/odoo#112827

X-original-commit: 28da08292b7028575e628c5ad846fc05d30498f2
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-02-16 09:01:07 +01:00
Denis Ledoux 2f5ed5f4ff [IMP] website_slides: removed unused member_values variable
The `member_values` argument of `action_add_member` is no
longer used in any call of `action_add_member`. We can therefore
remove it in standard, as it's completely unused.

Besides, after grepping the code for all calls to `action_add_member`
to check `member_values` was indeed unused, I saw this method
wasn't used by any views or Javascript code, but only
through Python routes, and therefore it can be converted
to a private method by prefixing it with `_`,
as our guidelines states to make private methods which are not used
by the web client.

closes odoo/odoo#111908

Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2023-02-13 14:05:09 +01:00
Victor Feyens 1a1ce16265 [IMP] core,*: check routes decorators
When overriding an existing controller route, developers can
easily c/p the route definition and call super() in the overridden method
when the route attributes are automatically deducted by odoo from the parent route.

Removing those redefined attributes simplifies the routes definition,
clearly highlighting what's changed by the override.
Also reduces unexpected behavior when modifying the base route without
noticing/considering the redefined attributes in a overridden route,
which overrides the changes made to the base route when the sub-module is installed.

This commit adds a test to catch routes attributes redefinition, and clean existing routes.

closes odoo/odoo#108512

Related: odoo/enterprise#35176
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
2023-01-16 19:45:57 +01:00
Rémy Voet (ryv)andJulien Castiaux e967e25095 [IMP] *: remove bad usage of search_read.
Reading only 'id' with `search_read` is equivalent to use `search` but
complexify the result usage. Fix all these bad usages.

Part-of: odoo/odoo#104838
Co-authored-by: Julien Castiaux <juc@odoo.com>
2022-11-07 11:26:32 +01:00
Benoit Socias f2e20e5377 [REF] website, *: make search options inheritable
*: website_blog, website_event, website_forum, website_slides

With [1] it has been made easier for partners to extend search options.

This task introduces similar inheritable functions for blog posts,
events, forum posts, slides, pages and hybrid results.

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

task-2897924

closes odoo/odoo#97908

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-10-28 18:50:49 +02:00
xO-Txandqsm-odoo 4c2f3389aa [REM] *: remove new content controllers
*: website_event, website_event_sale, website_forum, website_sale,
   website_sale_slides, website_slides, website_slides_forum

This commit removes the remaining controllers that are no longer used
since the use of form views on website new content dialogs (following
the website in backend merge at [1] and the many iterations afterwards).

With the website in backend work, a feature was lost for the creation of
events: dummy tickets were created. This commit actually removes the
feature for good. Events default values are managed by templates.
Moreover there are links in frontend to edit the event when being
allowed to edit it (event groups), notably when there is no ticket in
registration page. So it makes no sense to create dummy tickets, without
price, for 1000 seats. Those values are random so they will have to be
edited. Better let users create real tickets if necessary, than editing
and/or removing dummy tickets.

[1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b

task-2687506

closes odoo/odoo#102928

X-original-commit: d559ce5d1518ac1293db1c4f52efb8094daf5b49
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
2022-10-10 19:03:15 +02:00
Arnaud Baes 84d17e57e8 [FIX] website_slides: Ensure viewed_slides is a set
Since 5b375d6 `viewed_slides` are now
stored in a set. This is causing issues post migrations because people
still had the list format in their sessions, and this results in a crash
when `.add()` is called on the list.

While deleting the sessions would likely solve the issues, this fix will
spare some troubles for people migrating in the future.

via p/feedback

closes odoo/odoo#99954

Signed-off-by: Florian Charlier (flch) <flch@odoo.com>
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-09-13 09:31:23 +02:00
Audric Onockx (auon) 0cc8e582ca [IMP] website_slides: create hook to update slides values
With the integration slides-knowledge,
slides can be set on the team, so that the user can be redirected
to them when searching for help.
We want to use the same view as for all slides,
but limit the records presented to the user.

With this commit, we create two distinct methods:
one that prepares the values
one that renders them.
This way, we can hook into the first one to replace the records
before rendering them, when the `/helpdesk/<team_id>/slides`
route is used.

task-2890043

closes odoo/odoo#97739

Related: odoo/enterprise#29283
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
2022-09-13 07:37:56 +02:00
Nikunj Ladava 7d66dcbf54 [IMP] website_slides: improve design of share pages in elearning
PURPOSE

Globally improve user experience when sharing content from the e-learning app.
This includes new sharing options, allowing to share to multiple emails, split
the sharing template from slide and course, etc...

SPECIFICATION

- added two more options 'WhatsApp' and 'Pinterest' to share snippets.
- we converted the email type of input for 'Share by email' to text,
  so we can enter multiple emails to share and also add validation
  in the controller for this input text input.
- We improved the design of the share modal by making sure that the full URL
  for sharing link is visible and rearranged the UI fields of
  'Share' nav-tab on non-fullscreen content (if there is
  embed code, the sharing by email and embed code will still be on
  the single row).
- Improved the share modal of the channel by adding an email field in it to
  Share the channel through the mail.
- New field name 'share_channel_template_id' for channel template
  in 'slide.channel' modal and also added _send_share_email method
  in it and email template for sharing channel through the mail, and
  also added the dedicated route for sharing the channel.
- New share button is added on the top of documents in the slide (which
  previously was in the tab below the content).

task- 2627364

Part-of: odoo/odoo#78139
2022-09-02 14:17:40 +02:00
Romain Derie 7ae60a7261 [IMP] website, *: fix wrong method naming
* website_event, website_slides

Note that `restricted_editor` is the new technical name used instead of
`publisher`

Before this commit, the `is_restricted_editor()` method was actually
checking for `designer` rights and not `restricted editor` ones.
Indeed, a restricted editor (previously publisher) never had the write
right on ir.ui.view.

Despite the method name being wrong, it was still correctly used where
we actually checked for designer rights and not publisher/restricted
editor ones.

Also, the method was checking for write access on ir.ui.view instead of
checking directly if the user had the related group.
While it wasn't really wrong, it was also including people who would
have the write right on ir.ui.view but were not part of the designer
group.
This doesn't really makes sens, as we don't want someone which received
that write right on ir.ui.view from another module (not related to the
website) to be considered as a website admin -> we don't want to show
them website admin UI and stuff like that.

The method could have simply be renamed to `is_designer()` and could
have just checked for `has_group(designer)`, but having such an helper
seems overkill, we would end up with as many utils as there is groups.

At the end, this PR:
- removes the confusing util method
- replace it by has_group checks

Part-of: odoo/odoo#98200
2022-08-31 23:50:06 +02:00
Romain Derie 5456dc499a [IMP] website, *: rename group publisher to restricted_editor
* portal, web_unsplash, website_*

This commit renames the `website.group_website_publisher` into
`website.group_website_restricted_editor`.

While the change in itself might look unuseful, it will help the dev and
tech community figuring which group is related to which feature.

Even internally when we discuss specs, we always have to remind which
group is the restricted editor: the publisher one or the designer one?

While it is probably, after all those years, now anchored in some dev
mind, there is no easy way to directly figure which of those 2 groups is
the restricted editor one.
Note that I myself always got confused about it.

Now, the "Restricted Editor" right will be reflected in its technical
name `group_website_restricted_editor`.
Same as for the "Editor & Designer" which technical name is
`group_website_designer`.

As we would like to have a fully working and ready system in v17 for the
community to be able to build themes easily, removing that dubious part
is a nice to have.

Part-of: odoo/odoo#98200
2022-08-31 23:50:06 +02:00
Florian Charlier db7c9ba7c5 [IMP] tools, website_{*}: increment multiple fields at once
* = blog, forum, slides

For performance reasons, allow to increment multiple fields of the same record
within the same query.

With python tests.

Task-2663320
Part of odoo/odoo#79615
2022-08-25 14:24:53 +02:00
Florian Charlier e3389e392e [IMP] website_slides: Improve frontend UI
The layout of slides needs a little freshening-up.

### Comments and slides

* The ratings are only showed once, and only for "documentation" contents
* Indications of why the user cannot post a comment are added (signing up,
  Karma, commenting not allowed), and the portal template is not called if
  there is no comment and commenting is not allowed (for user or course).
  In addition, the "Comment" tab is never hidden anymore, to not hide
  the available/activate-able features.
* Detailed view statistics are now shown only to selected users.
* Slide public views represent views by the public and all users that
  are not members of the course.
* When channel/slide images are not set or inaccessible, a default image
  is used (instead of plain background or unauthorized requests).
* These images are now editable on frontend.
* The 'Additional Resources' subtitle is hidden from the detailed slide view
  for invite-only courses as nothing else was shown with it.

### Misc.

*  This commit also fixes the "unresponsive" `total_views` count after public
views, by manually incrementing it too. This is required because `public_views`
is directly updated via SQL query and does not trigger model _computes.

* We also adjusted the test in survey that used a public user while in all
cases users must be logged-in (and therefore get portal privileges) before
they can participate.

Task-2663320
Part of odoo/odoo#79615
2022-08-25 14:24:52 +02:00
Romain Derie febc059807 [FIX] website_slides: fix typo on method call
Since [1], the call to the method was missing the `()`, thus always
being truthy.

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

closes odoo/odoo#98179

X-original-commit: 0ef2509d321423f8f8616790352b32da51c289ae
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-08-16 16:28:42 +02:00
Jeremy Kersten 0943722c32 [FIX] *: use request.redirect instead of werkzeug.utils.redirect
It allows to always have a OdooResponse Object and don't allow redirect
to external except when you allow it explicitly with local=False.

Always return to a local url:
    /website/add
    /slides/slide/<model("slide.slide"):slide>
    /microsoft_outlook/confirm

Allow previously external redirect without reason, now blocked
   /website/lang/<lang> -> open redirect

Allow external redirect for good reason and url is controlled by code.
   /social_facebook/redirect_to_profile/

PS: HTTP Code 303 is a better default for generic redirects. It's not
historically the default for werkzeug.utils, but it is what we want in
general. Contrary to 302, there is no browser-dependent behavior, and
no risk of asking the user whether they want to accept the redirect if
the original method wasn't GET. It's always a non-permanent GET on the
target location.

closes odoo/odoo#95019

X-original-commit: 77f8d9c5d96a9274785ffc2ad83b95ea157d26ad
Related: odoo/enterprise#29000
Signed-off-by: Olivier Dony <odo@odoo.com>
Signed-off-by: Jérémy Kersten <jke@odoo.com>
2022-07-04 14:07:45 +02:00
99b50d18e2 [REF] test_website, *: adapt tours to new client action
*: website, website_blog, website_crm, website_event, website_forum,
   website_hr_recruitment, website_mass_mailing, website_sale,
   website_sale_loyalty, website_slides

This commit adds the current website displayed view xmlid outside of the
iframe, on its container, so that the tours registered with
registerThemeHomepageTour can continue to prepend their triggers with
the view xml id.

Introduce registerEditionTour: this function will allow tour maker to
more easily register a tour that needs to start in the iframe's backend
and go in edit mode.

See merge commit for more information.

task-2687506

Co-authored-by: Benjamin Vray <bvr@odoo.com>
Co-authored-by: Younn Olivier <yol@odoo.com>
2022-06-24 10:28:07 +02:00
Younn Olivier b85c2a4cb1 [IMP] website, *: redirect to the client action when needed
*: website_blog, website_hr_recruitment, website_sale, website_slides

This commit changes the redirections from the controllers, that were
always redirecting to the frontend before.

Now, we want to open the website in its backend client action most of
the time (for example, when clicking on the "go to website" buttons on
the form views).

For that, a new get_client_action_url is introduced on the website
model.

See merge commit for more information.

task-2687506
2022-06-24 10:28:07 +02:00
Florian Charlier e5fb020839 [IMP] website_slides: fix public views counter
Changes in rules of session storage for visitors (04e97266) prevented the list
of viewed slides to be updated for public viewers, ending in possibly unlimited
counts. Fixed by touching the sessions, with a small performance improvement
"en passant".

See Odoo#86015

Task-2878900

closes odoo/odoo#93181

X-original-commit: 5b375d6c5e1f4a29add3976af7fd71600c7b4cda
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-09 14:17:49 +02:00
Julien Castiaux fc115ebdf7 [FIX] web: invalid image placeholder resizing
Access `/web/image/82303?height=16`, traceback because the placeholder
image cannot be resized to `"16"`.

closes odoo/odoo#92891

Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-03 18:34:49 +02:00
Gorash b0a2a41d78 [IMP] all/website: using lazy values and t-cache in templates
Using lazy values allows you to not do query when the content is not
displayed or if it is already cached. Adding `t-cache` only reduces
render time, but combining it with lazy values saves browses, computes
and query.
Thus for the `/shop` page the page is displayed in 60ms (before: 250ms).

Part-of: odoo/odoo#88276
2022-06-03 16:40:40 +02:00
Adrien Schoffeniels 2e0490beb5 [IMP] website_slides: improve website_slides_survey integration
SPECS

1. Change the default content of the modal opened after the installation
of a module

When the installation of a suggested module from the upload dialog is
completed, the page is reloaded and the upload dialog is opened on load.
Since the user installed the module to add content of the category related to
this module, it is more convenient to open the modal directly on this category.

2. Replace the notification displayed when the user creates a new
certification by a permanent button allowing to add questions

When a user creates a certification, he must then add questions to this
certification. Instead of showing a notification after the creation
proposing to add questions that was shown only once, a permanent button
has been added to the view of the certification so that anyone with the
sufficient access rights can add questions, at any time, from the certification
view.

Task-2727654

closes odoo/odoo#86721

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-06-01 16:26:02 +02:00
Julien Castiaux da8def8e41 [IMP] core, web: Delegate delivery of static files
Rationnals
----------

Web servers can serve some resources (e.g. static files) right away
without any interaction with the web application. The network model of
most web servers makes them capable of handling thousands of
simultaneous requests when it comes to intensive IO operations such as
streaming data from a file. The network model of Odoo is different: it
is capable of a lot of processing power but can only serve a handful of
requests at a time, i.e. Odoo (with some help from postgres) is
optimized for CPU operations, not IO.

Some users don't configure their web server, they use a basic
configuration that relay all requests to Odoo. The result is that many
Odoo HTTP Workers can be busy streaming static files instead of
processing other requests. This can lead to a worker starvation, i.e.
all workers are busy streaming files and cannot process new requests.

X-Sendfile
----------

In this work, we add the support for the [X-Sendfile] header family,
they are multiples http headers that can be used by the web application
to communicate with the web server in order to delegate the delivery of
files stored on the file system. Odoo still receives the request but it
does no more stream the file content from within its HTTP worker,
instead it skips the response body altogether and sets the `X-Sendfile`
special header with the path of the file on the filesystem. The web
server intercepts that special header, open the file and stream it.

Using those headers, we can use the best of both the web application and
the web server. The web application is still responsible to locate the
resource and verify the access rights, the web server is still
responsible of streaming the content.

Using X-Sendfile is opt-in via the `--x-sendfile` CLI flag. We set both
`X-Sendfile` (apache) and `X-Accel-Redirect` (nginx). If you are using
apache, make sure `mod_xsendfile` is enabled. If you are using NGINX
you have to add the following location block:

    location /web/filestore {  # custom path, hardcoded within Odoo
        # Prevent access from the outside world, i.e. makes this
        # route only accessible via X-Accel. MANDATORY!!!
        internal;

        # Give access to the filestore using this server's
        # permissions. Odoo is in charge of verifying the access
        # rights.
        alias /path/to/odoo/data-dir/filestore;
    }

The Odoo [deployment documentation] has been updated accordingly.

[X-Sendfile]: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
[deployment documentation]: https://www.odoo.com/documentation/master/administration/install/deploy.html#serving-static-files-and-attachments

Changes to the API
------------------

To benefit most from X-Sendfile, all APIs related to streaming content
over HTTP has to be adapted. They are: (1) `request._serve_static`,
(2) `ir.http._serve_fallback`, (3) `/web/content` and (4) `/web/image`.

Each used it own way to deliver content: (1) `_serve_static` was using
`send_file` (flask's send_file that as been vendored with odoo 10
years ago and not maintenained since then), (2) _serve_fallback was
handcrafting a `werkzeug.wrappers.Response`, (3) /web/content-image were
using the "binary server" `ir.http.binary_content` API.

I has been decided to remove all 3 APIs and to merge the code inside of
the new `http.Stream` object and the `ir.binary` helper model.

A Stream wraps what is going to be sent to the browser, it can be a path
to a file on the locale filesystem, a blob of raw data or an URL to an
external resource. The Stream also holds various metadata that are
mainly used for caching. The preferred way to create a Stream is via one
of its three factories so that all the metadata are set. The factories
are: `from_path`, `from_attachment` and `from_binary_field`. A stream
instance exposes a single method `get_response()` used to create the
corresponding HTTP response object out of the stream.

Inside of `ir.http` were a few methods that were not related to the http
routing and formed what was called the "binary server". All those
methods have been removed and the feature have been refactored inside of
the new `ir.binary` model. The removed methods are:

- `_xmlid_to_obj`
- `_get_record_and_check`
- `_binary_ir_attachment_redirect_content`
- `_binary_record_content`
- `_binary_set_headers`
- `binary_content`
- `_response_by_status`
- `_get_content_common`
- `_content_image`
- `_content_image_get_response`
- `_placeholder_image_get_response`

The new `ir.binary` abstract model exposes the following utilities:

**`_find_record`**

Find an attachment or a record with a binary-field out of an xmlid or
out of a pair record-model/record-id. Check the access rights and the
access token.

**`_get_stream_from`**

Create a Stream from an attachment or a record with a binary-field.

**`_get_image_stream_from`**

Same as `_get_stream_from` but adapted for images. It sets a sensible
ETag on the stream and has image resizing support.

**`_placeholder`**

Get the image placeholder blob.

Testing
-------

It is possible to test the web server configuration using the
`test_http` module. Install the module then run the unittest using the
`webserver` test-tag. By default it attempts to connect to a web-server
running on `http://localhost:80`, you can change this URL by setting the
`WEB_SERVER_URL` environment variable.

    odoo-bin -i test_http --stop-after-init
    WEB_SERVER_URL='http://localhost:80' odoo-bin --test-tags webserver --stop-after-init

closes odoo/odoo#88134

Task: 2801675
Related: odoo/documentation#2083
Related: odoo/enterprise#26191
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-01 02:53:59 +02:00
std-odoo e1ac0ed0a2 [IMP] website_slides: allow to mark content as "(un)done"
Purpose
=======
Allow the users to themselves mark their course as "done" or "not done"

Specifications
==============
When the course is a "Training" in fullscreen or in non-fullscreen, or
when the course is a "Documentation" in fullscreen mode, allow the user
to click on the "done" button in the sidebar.

When the course is a "Documentation" in non-fullscreen mode, add a
button "Mark Not Done" when the slide is done.

The quiz and the certification cannot be marked as done manually, the
user has to complete the questions for that.

A certification cannot be marked as "Not Done" (but a quiz can).

In the non-fullscreen view, mark content as done automatically like we
do for the fullscreen view.

Technical
=========
As the fullscreen view and the non-fullscreen view will share a lot of
code, make a common class to avoid redundancy.

Task-2604792

Part-of: odoo/odoo#75561
2022-05-19 12:27:59 +02:00
Thibault Delavallée 93b6282ed6 [FIX] various: remove unnecessary .id in domains
Even if ORM normally filters them out, no need to specify .id in domains.
This leads to better and easier to read queries / domains.

Task-2816580

closes odoo/odoo#85648

Related: odoo/enterprise#24911
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-04-12 08:21:08 +02:00
Gorash 880954ebfc [IMP] *: remove _render from ir.ui.view and simplify report
There were inconsistencies in the calls to `_render`.
* the view context could contain information that misled developers.
Indeed, the context and value of the view are not supposed to be found
in the rendering. Thus by calling `ir.qweb` with the name of the
template, we ensure that there is no unwanted information and in
addition the cache key is that of the name of the template which saves
a query.
* the context used for rendering was modified by a method on
`ir.ui.view`, except this is not information used by this model. There
is now a `_prepare_environment` method residing on `ir.qweb`. This
method allows to modify the value dictionary as well as the context in
which the rendering will be done. This preparation of the data as well
as my security check is done only once per rendering. This also saves
some queries
* Freeze options for rendering were inconsistent. It could be that
options on which rendering depends were not part of the cache key. Thus,
depending on the user who generated the generation of the rendering
function, there was or was not information in the template. For example
for automatic branding. This is no longer possible, because it is the
context that is used. The options serving as a cache key are only
recorded for information (for the profiling system for example). A
simplification of the `ir.qweb.field` models could be made.

The report rendering and call `ir.qweb` instead of `ir.ui.view`.

Part-of: odoo/odoo#85110
2022-03-29 10:56:15 +02:00
Jinjiu Liu ed9814059b [FIX] website_slides: added redirection for invalid slide URLs
Reproduction:
1. Install eLearning, delete sitemap.xml from Settings->Technical->
Database structure -> Attachment
2. Regenerate sitemap.xml by opening odoo.com(or localhost)/sitemap.xml
3. Open a URL, for example,
http://odoo14:6014/slides/slide/tools-and-methods-25
4. A ValueError is thrown

Reason: the URL generation for model slide.slide uses the default
method, which doesn’t filter out the category slides. An example of a
category is: http://odoo14:6014/slides/slide/unforgettable-tools-28 The
tools-and-methods is a category in the course content

Fix: Added a special case for category slides. If it's a category,
redirect to the channel's homepage

opw-2579913

closes odoo/odoo#87369

X-original-commit: eca5ea22624268eaccc5cf9fa7585d51cb6d16cc
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-03-29 00:09:10 +02:00
Pierre-Yves Dufays db63c03af9 [IMP] website_slides: display a user-friendly error message when accessing an
unauthorized course content

Display a user-friendly error message when a user access an unauthorized
course content.

Specifications:

When a non-authorized course content is accessed, instead of a 403 error page,
redirect to the course page with a small notification saying
"You need to join this course to access ContentName"

Technical remarks:

As the slide URL may lead to a 403 if the user has not access to the course and
we didn't want to change that route, we have decided to share URL with a
specific route when the resource is protected (is_preview = False):
slides/slide/<int:slide_id>/share

To make available that new URL in the templates and to the client, a computed
field website_share_url has been added to the channel and slide model.

Note that when checking the access rule, a MissingError can be triggered if for
example the content has been deleted. In that case the user will be redirected
to a 404 and 2 reads are performed but the code is more generic.

Task 2742087

closes odoo/odoo#83935

Related: odoo/upgrade#3280
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-03-16 09:58:42 +01:00
Nikunj Ladava 6785b7d47c [IMP] website_slides: raise UserError on 'Set Done' button
Currently, when someone adds a quiz on the slide content from front-end
and clicks on the 'Set Done' button, `werkzeug.exceptions.Forbidden`
error is raised which shows the full stack trace to the end user.

This commit improves the behavior by raising UserError instead and
thus displaying nice error instead of the full stack trace.

taskID-2380233

closes odoo/odoo#85694

X-original-commit: 5dfd5dd50fa8cd3f023ba7fa0c2fc4b52f9c5650
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
2022-03-02 23:08:20 +00:00
Munaf KhanandThibault Delavallée fa7451544d [IMP] website_slides: improve lesson design in documentation
Currently, in the documentation type of courses, card layout for the lessons
is broken because there isn't enough space to display everything.

To fix this, this commit moves the 'Completed' badge (which is in the card
footer) and other tags at the end of the card-body. It formats likes and
dislikes using a decimalized formatting (ex, 10000 will be displayed
as 10k).

But that improvement leads to another trouble. Say there are '1k' likes and
user upvotes the lesson. There is no indication whether or not the vote was
recorded. To fix this, we will now use different icons based on the user vote

  - The thumbs-up icon will be filled if user has liked the lesson and it will
    be hollow otherwise;
  - Likewise, the thumbs-down icon will be filled if user has disliked the
    lesson, and it will be hollow otherwise;

Clicking on either of the button, if the vote is recorded successfully, icon
and user vote will be toggled for better indication. Note that before this
commit, if user was performing the same action (for example upvoting again)
a warning popover used to appear, which isn't the case anymore because now
the vote will simply be toggled. The mechanism is somewhat similar to youtube
(you can also directly dislike the already liked content and visa-versa).

The same mechanism is also applied for likes/dislikes in the footer of each
lesson's page. And, on the same page under 'Statistics' tab, they are simply
formatted like everywhere else.

Apart from that, this commit makes other small UI changes listed
as below:

  - We now display three slides per category instead of four, giving the
    cards a bit more space;
  - On the lessons' page, we move the likes/dislikes right after description
    which previously was at bottom right of the page;
  - Likes / Rating is now always displayed the same in lessen view whatever
    the channel type (displaying ratings / comments / likes);

Also see odoo/upgrade#2854

Task-2607416

Part-of: odoo/odoo#74171
Co-authored-by: Munaf Bahelim <mub@odoo.com>
Co-authored-by: Thibault Delavallée <tde@odoo.com>
2022-02-28 11:07:39 +00:00
Thibault Delavallée 1bcd34ea6b [REF] website_slides: cleanup membership fields
Purpose of this commit is to finalize the cleanup of current user's membership
on a given slide.

As a followup of odoo/odoo@8b2f887c29 we remove now dead ``_compute_user_info``
method. We also introduce a shortcut to ``user_membership_id.sudo().completed``
by adding its computation directly while computing user_membership_id as well
as user_vote. It allows to remove some sudo on user_membership_id.

Task-2607416

Part-of: odoo/odoo#74171
2022-02-28 11:07:37 +00:00
Noe Antoine aead9a884e [IMP] website_slides: allow empty messages when reviewing courses
In order to reduce friction and ease the rating process for attendees,
we do not force the constraint stating that the message must contain a
message or an attachment onto the users. Instead, we allow ratings and
replace the empty message by a blank space to avoid triggering the error
message. If no stars are selected, an error message is now displayed to
the user, asking to select a rating before submission, preventing them
to post their review until then.

Since we do not really support 0 stars ratings, and do not want the user
to see that error message in case of the course, we set the default rating
to 4.0 instead of 0.0.
-> Therefore, we also remove the grey star contrast coloring on first review
   since we do not want the user to have the impression a choice has already
   be made beforehand. In that case, everything will be yellow.

Void content detection is done by extracting it in both python (portal
chatter post controller) and frontend (submission check) and relaxing it
in slides modules.

Task-2728564

Part-of: odoo/odoo#82792
2022-02-22 19:47:53 +00:00
Fabien Pinckaers 6b87526048 [IMP] Speed Imp: remove unnecessary base64 encode & decode
Avoid to base64 encode, then decode to process assets and images for a ~25% speed improvement.
Change image processing tool to work on images, rather than base64 encoded strings.

Performance is ~25% faster on assets & images:

  /web/assets/...frontend.min.css:    13ms to 7ms,  base64 enc/dec: 2 -> 0
  /web/image/XML_ID:                  10ms to 8ms,  base64 enc/dec: 3 -> 0
  /web/image/res.users/2/avatar_128:  40ms to 20ms, base64 enc/dec: 6 -> 2

closes odoo/odoo#82851

Related: odoo/enterprise#23537
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
2022-01-22 11:51:42 +00:00
Aurélien Warnon 22d1743e26 [REF] website_slides: rename 'webpage' to 'article'
This commit simply renames the 'webpage' slide_category into 'article'.

Indeed, 'webpage' was confusing because it was leading you to believe that you
would have to link external content from another website.

While this slide_category instead lets you build an 'article' with content by
using our website builder.

The changes here are just renaming the slide_category and the labels, there
should not be any functional change.

Task-2510174

Part-of: odoo/odoo#71477
2021-11-30 15:21:49 +00:00
Aurélien Warnon ffa504887d [IMP] website_slides: slightly improve various e-learning views
PURPOSE

This commit adds some small UI improvements to the e-learning views.
All those small changes are meant to improve the general user experience when
adding content to a course.

DETAILED SPECS

- Change some placeholders / labels
- Inform the end-user that he can edit his 'webpage' slide using the editor
- Inform the end-user that he can add questions to his 'quiz' slide using the
  'Quiz' tab in the backend form view
- Do not update from slide metadata if field value is already set
- Do not allow previews for certifications
- "Allow Download" of slide content is now False by default
  As it was nice to have for "Documentation" courses but does not really make
  sense for "Training" ones.
- Having a duplicate video id is now informative on the frontend and not
  blocking as before (it was allowed in the backend form anyway).
- Show the video title in the frontend preview

Task-2510174

Part-of: odoo/odoo#71477
2021-11-30 15:21:48 +00:00
Aurélien Warnon 0ece0b3263 [IMP] website_slides: add Vimeo integration
This commit adds support for the Vimeo provider in the e-learning platform.

This includes managing Vimeo video links and showing the Vimeo embedded player
in the fullscreen and non-fullscreen viewers.

But also managing video events to:
- automatically set the slide as completed when the video reaches the last 30
  seconds
- go to the next slide when the video ends (if there is one)

Task-2510174

Part-of: odoo/odoo#71477
2021-11-30 15:21:48 +00:00
Aurélien Warnon 7b5427f6d6 [REF] website_slides: refactor external content management in slide.slide
PURPOSE

Globally refactor the way we handle external content (YouTube videos,
Google Drive documents, ...) in the course slides.

This includes both technical changes (new computed fields, rename, ...) as well
as visual changes on the form views that allow introducing new content, both in
the backend (slide.slide form view) and in the frontend (course main website
page).

SPECS

TECHNICAL REFACTOR

1. Rework the "url" field

This field was used without any distinction for videos, regular documents and
images, leading to a big confusion both technically and visually.

The urls are now split in separate fields (video_url, document_google_url and
image_google_url), based on the type of slide.
Those fields are implemented as 'related' to the stored 'url' field to avoid
extra storage.

This change globally increases the readability and usability in the code, and
also allows for clear labels on the various views.

1b. Rework the "binary_content" field

The same way as for the 'url' field, the 'binary_content' field has been split
into 2 related fields ('document_binary_content' and 'image_binary_content').

This allows for more readability and also helps in the form view to limit the
file selection to the supported file types.

2. Remove the "document_id" stored field

This field did not have to be stored since it can "easily" be inferred from the
video/document URL with some regex work.

3. Remove the "mime_type" field

This field's value was only determined by an external call to the Google Drive
API. It was inconsistent because not set for manually uploaded document and was
used for some strange checks that seemed to work but did not make much sense.
(e.g: used to make the difference between a Google Drive video and a YouTube
video??).

It has been replaced by a "document_type" field, which is always 'pdf' for
local files (only type we support) and inferred from the mimeType returned by
Google Drive metadata for external documents.

This allows, for instance, to show pretty icons next to every slide based on
their type, "sheet" files (Excel, Google Sheet, ...) share the same icons, the
same principle is applied to "doc" files (Word, OpenOffice, Google Doc, ...)
and finally "slides" files (PowerPoint, Google Slides, ...).

4. Introduce several computed fields

Such as:
- video_source_type
- youtube_id
- google_drive_id

These fields are mostly inferred from the slide type and the related URL.
They are used to make clear checks in the code and ease readability, for
example when constructing the slide "embed code" to insert it in the frontend
full screen viewer.

5. Remove the "presentation" slide_type

The slide type "presentation" was some kind of very confusing type between
image and pdf. It was mostly relying on the fact that the content had a bigger
width than height ('landscape' display).

This lead to a lot of confusion both in the code base and in the various forms
allowing to introduce new content ("what should I choose? document or
presentation?").

In order to simplify everything, we completely removed the slide type
"presentation" and converted all the data that had this type and the various
code checks to the type "document" instead.

Meaning that we end up with the following slide types:
- Infographic - for images, local files + external links
- Web Page - local input only
- Document local files + external links
- Video - external only, YouTube or Google Drive links
- Quiz

FUNCTIONAL

Following the technical changes here above, we can improve the form view of the
slide.slide model as well as the website form that allows adding new content.

1. Slide form view

To make it clear where the source of the document comes from, we introduced a
"source_type" field that is either "local_file", used when uploading a file
from your computer, or "external", used when linking content from Google Drive.

The source_type selection appears when adding content of type "document" or
"infographic" and conditions the display of the file upload button or the
document_url field.

2. Adding content from the website

When adding content from the website, the user is now invited to select from
ALL the available slide type, meaning we added "Infographic" to the selection.

Before this change, if you wanted to link an image, you had to select the type
"presentation" (that has a PDF file as icon...) and then input an image file.
The JS then processed the file type to determine the slide type.

As this was slightly confusing for the end user, we decided to use the same
approach as the form view, meaning you FIRST select the type of slide you want
and THEN input the content as a local file or external link.

Since we now handle all types of documents when using an external Google Drive
link, the various screen and text helpers have been reworked accordingly.

3. Handle more types of slides with the new "slide_type" field

This commit also introduces a new "slide_type" field.
(Don't get confused, the previous "slide_type" field has been renamed to
"slide_category" in an earlier rename commit).

This slide_type is a refined slide_category:
- Videos are split into 'youtube_video' and 'google_drive_video'
- Documents are refined based on the file mime_type if it's external content
  For example, if you link a Excel file, the slide_type will be 'sheet'.
  If you link a Google Doc, the slide_type will be 'doc'
  etc...
  (Local documents are only PDFs since it's the only type we support for now)

This small change allows to include minor nice details into views, such as a
refined icon for each slide_type on the website.

LINKS

Task-2510174
UPG PR odoo/upgrade#2498

Part-of: odoo/odoo#71477
2021-11-30 15:21:48 +00:00
Aurélien Warnon ab0b36e8a5 [REF] website_slides: rename slide.slide fields
This commit simply applies the following renames in the slide.slide model:

- 'datas' is renamed into 'binary_content'
- 'slide_type' is renamed into 'slide_category'

This changes intend to ease the next bug refactoring of the website_slide
module content management.

There should be no functional changes applied in this commit.

Task-2510174

Part-of: odoo/odoo#71477
2021-11-30 15:21:47 +00:00
Aurélien Warnon 4a329da6a0 [IMP] website_slides: improve quiz error management
This commit slightly improves the quiz error management when building a quiz
directly on the website or when answering to the quiz.

When there is a validation or submission error, instead of displaying a toaster
very far from the user focus, we add the error next to the button he just
clicked.

For the question validation, this requires a small trick in the controller,
where we catch the ValidationError to return the message to the JavaScript.

Task-2678061

closes odoo/odoo#79081

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2021-11-24 13:16:45 +00:00
Aurélien Warnon 043b3385d2 [IMP] website_slides: improve slide.embed feature
Currently, the slide.embed statistics only work if a 'Referer' header is passed
in the request object.

The issue with that strategy is that it's not very reliable, indeed some modern
browsers now completely avoid passing the referer header (mostly for security
and privacy reasons).

This commit refactors the slide.embed feature to work even without a referer
header.
When the header is missing, the incremented count will be stored under a
common slide.embed record with a url field = False.

This count is still useful because the end-user will want to know if the slide
is popular externally, even if we don't know on which website it has been
embedded exactly.

In addition, we add more visibility to the slide.embed feature by introducing
a stat-button on the slide.slide form view, that redirects to the list of
slide.embeds for this slide.

Finally, we also renamed the 'embedcount_ids' field to 'embed_ids' to get a
better / clearer naming.

A few tests about embed detection were added to ensure this behavior.
(Tests are based on the work of Nathan Marotte <nama@odoo.com>).

Task-2654009

Part-of: odoo/odoo#77736
2021-11-24 10:18:17 +00:00