[MERGE][IMP] website_slides: improve the frontend UI for slide_channels
PURPOSE --------------- Add small improvements to the frontend UI for slide_channels. SPECIFICATION ----------------------- Current behavior before PR: 1. We can't display all uncategorized slides of a course. 2. When you upload an image or PDF, the name field is replaced by the filename even it was filled before selecting the file. This leads to rewrite the name a second time before uploading the slide. 3. There is no way for the website designer to choose if he wants to display or hide the promoted slide of a course. Desired behavior after PR is merged: 1. Slides without a category are displayed correctly, now you have access to the link "View all" which allows the user to display all uncategorized slides with a possible pager. You have also the possibility to create a section/category with the new button "Add a section" next to the button to upload content. 2. When you upload an image or a PDF, the name field is no more replace automatically by the filename. Now, it's replaced only if the field is empty when you select the file. 3. Now, there is a new button under the Customize tab to display or hide the promoted slide on the courses. By default, the promoted slide is displayed on the course. task-2161391 closes odoo/odoo#42420 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -348,9 +348,12 @@ class WebsiteSlides(WebsiteProfile):
|
||||
'/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>',
|
||||
'/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>/page/<int:page>',
|
||||
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>',
|
||||
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>/page/<int:page>'
|
||||
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>/page/<int:page>',
|
||||
], type='http', auth="public", website=True, sitemap=sitemap_slide)
|
||||
def channel(self, channel, category=None, tag=None, page=1, slide_type=None, uncategorized=False, sorting=None, search=None, **kw):
|
||||
"""
|
||||
Will return all necessary data to display the requested slide_channel along with a possible category.
|
||||
"""
|
||||
if not channel.can_access_from_current_website():
|
||||
raise werkzeug.exceptions.NotFound()
|
||||
|
||||
@@ -376,7 +379,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
pager_url += "/tag/%s" % tag.id
|
||||
if uncategorized:
|
||||
domain += [('category_id', '=', False)]
|
||||
pager_url += "?uncategorized=1"
|
||||
pager_args['uncategorized'] = 1
|
||||
elif slide_type:
|
||||
domain += [('slide_type', '=', slide_type)]
|
||||
pager_url += "?slide_type=%s" % slide_type
|
||||
@@ -463,10 +466,18 @@ class WebsiteSlides(WebsiteProfile):
|
||||
# documentation mode may display less slides than content by category but overhead of
|
||||
# computation is reasonable
|
||||
values['slide_promoted'] = request.env['slide.slide'].sudo().search(domain, limit=1, order=order)
|
||||
|
||||
limit_category_data = False
|
||||
if channel.channel_type == 'documentation':
|
||||
if category or uncategorized:
|
||||
limit_category_data = self._slides_per_page
|
||||
else:
|
||||
limit_category_data = self._slides_per_category
|
||||
|
||||
values['category_data'] = channel._get_categorized_slides(
|
||||
domain, order,
|
||||
force_void=not category,
|
||||
limit=False if channel.channel_type != 'documentation' else self._slides_per_page if category else self._slides_per_category,
|
||||
limit=limit_category_data,
|
||||
offset=pager['offset'])
|
||||
values['channel_progress'] = self._get_channel_progress(channel, include_quiz=True)
|
||||
|
||||
|
||||
@@ -516,7 +516,9 @@ var SlideUploadDialog = Dialog.extend({
|
||||
if (!preventOnchange) {
|
||||
var input = file.name;
|
||||
var inputVal = input.substr(0, input.lastIndexOf('.')) || input;
|
||||
this._formSetFieldValue('name', inputVal);
|
||||
if (this._formGetFieldValue('name') === "") {
|
||||
this._formSetFieldValue('name', inputVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
_onChangeSlideUrl: function (ev) {
|
||||
|
||||
@@ -452,6 +452,38 @@
|
||||
</template>
|
||||
|
||||
<!-- ======= Documentation Course content: cards / categories======= -->
|
||||
<template id="course_promoted_slide" name="Documentation Course content: promoted slide">
|
||||
<div class="o_wslides_promoted_slide d-none">
|
||||
<div t-if="not search and not search_slide_type and slide_promoted" class="container py-1 mb-2">
|
||||
<div class="card flex-column flex-lg-row">
|
||||
<t t-set="image_url" t-value="website.image_url(slide_promoted, 'image_1024')"/>
|
||||
|
||||
<a t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"
|
||||
t-attf-href="/slides/slide/#{slug(slide_promoted)}#{query_string}" class="w-100 w-lg-50 flex-shrink-0 rounded">
|
||||
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
|
||||
</a>
|
||||
<div t-else="" class="w-100 w-lg-50 flex-shrink-0 rounded">
|
||||
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<a t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"
|
||||
t-attf-href="/slides/slide/#{slug(slide_promoted)}#{query_string}"
|
||||
class="h4 d-block" t-att-title="slide_promoted.name" t-field="slide_promoted.name"/>
|
||||
<h4 t-else="" class="text-muted" t-field="slide_promoted.name"/>
|
||||
|
||||
<div t-if="slide_promoted.tag_ids" class="border-top mt-2 pt-1">
|
||||
<t t-foreach="slide_promoted.tag_ids" t-as="tag">
|
||||
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide_promoted.channel_id), slug(tag))" class="badge badge-light" t-esc="tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="o_wslides_desc_truncate_10 mt-3" t-field="slide_promoted.description"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="course_slides_cards" name="Documentation Course content: cards / categories">
|
||||
<div class="o_wslides_lesson_nav mb-4 border-bottom">
|
||||
<div class="container">
|
||||
@@ -549,35 +581,15 @@
|
||||
t-att-data-can-publish="channel.can_publish">
|
||||
<i class="fa fa-cloud-upload mr-1"/>Upload new content
|
||||
</a>
|
||||
<a class="btn btn-secondary py-1 o_wslides_js_slide_section_add"
|
||||
title="Add Section" role="button"
|
||||
aria-label="Add Section" href="#"
|
||||
t-att-channel_id="channel.id">
|
||||
<i class="fa fa-folder-o mr-1"/>Add a section
|
||||
</a>
|
||||
</div>
|
||||
<!-- Featured lesson -->
|
||||
<div t-if="not search and not search_slide_type and slide_promoted" class="container py-1 mb-2">
|
||||
<div class="card flex-column flex-lg-row">
|
||||
<t t-set="image_url" t-value="website.image_url(slide_promoted, 'image_1024')"/>
|
||||
|
||||
<a t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"
|
||||
t-attf-href="/slides/slide/#{slug(slide_promoted)}#{query_string}" class="w-100 w-lg-50 flex-shrink-0 rounded">
|
||||
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
|
||||
</a>
|
||||
<div t-else="" class="w-100 w-lg-50 flex-shrink-0 rounded">
|
||||
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<a t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"
|
||||
t-attf-href="/slides/slide/#{slug(slide_promoted)}#{query_string}"
|
||||
class="h4 d-block" t-att-title="slide_promoted.name" t-field="slide_promoted.name"/>
|
||||
<h4 t-else="" class="text-muted" t-field="slide_promoted.name"/>
|
||||
|
||||
<div t-if="slide_promoted.tag_ids" class="border-top mt-2 pt-1">
|
||||
<t t-foreach="slide_promoted.tag_ids" t-as="tag">
|
||||
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide_promoted.channel_id), slug(tag))" class="badge badge-light" t-esc="tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="o_wslides_desc_truncate_10 mt-3" t-field="slide_promoted.description"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<t t-call="website_slides.course_promoted_slide"/>
|
||||
|
||||
<div class="container py-2">
|
||||
<t t-if="search">
|
||||
@@ -592,11 +604,14 @@
|
||||
|
||||
<t t-foreach="category_data" t-as="category">
|
||||
<div class="mb-2" t-if="(category['slides'] or channel.can_publish) and (search_category and search_category.id == category['id'] or not search_category)">
|
||||
<div class="d-flex align-items-center justify-content-between border-bottom pb-2 mb-3" t-if="category['name'] != 'Uncategorized'">
|
||||
<t t-set="is_empty_editable" t-value="not category['slides'] and channel.can_publish"/>
|
||||
<t t-set="is_empty_editable" t-value="not category['slides'] and channel.can_publish"/>
|
||||
<div class="d-flex align-items-center justify-content-between border-bottom pb-2 mb-3" t-if="category['id'] and query_string != '?search_uncategorized=1'">
|
||||
<h5 t-attf-class="m-0 #{'text-muted' if is_empty_editable else ''}"><t t-esc="category['name']"/></h5>
|
||||
<a t-if="category['id'] and not is_empty_editable" t-att-href="'/slides/%s/category/%s' % (slug(channel), category['slug_name'])">View all</a>
|
||||
<a t-elif="not is_empty_editable" t-att-href="'/slides/%s?uncategorized=1' % (slug(channel))">View all</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between border-bottom pb-2 mb-3" t-if="not category['id'] and len(category['slides']) > 0">
|
||||
<h5 t-if="len(category_data) > 1" t-attf-class="m-0 #{'text-muted' if is_empty_editable else ''}"><t t-esc="category['name']"/></h5>
|
||||
<a t-att-href="'/slides/%s?uncategorized=1' % (slug(channel))">View all</a>
|
||||
</div>
|
||||
<div class="row mx-n2">
|
||||
<t t-foreach="category['slides']" t-as="slide">
|
||||
@@ -609,14 +624,8 @@
|
||||
<div class="row">
|
||||
<div class="col" t-field="channel.description_html"/>
|
||||
</div>
|
||||
|
||||
<t t-if="search_category">
|
||||
<div class="form-inline justify-content-center">
|
||||
<t t-call="website_profile.pager_nobox"></t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="search_category">
|
||||
<t t-if="search_category or search_uncategorized">
|
||||
<div class="form-inline justify-content-center pb-5">
|
||||
<t t-call="website_profile.pager_nobox"></t>
|
||||
</div>
|
||||
@@ -694,4 +703,10 @@
|
||||
<i t-if="slide.slide_type == 'quiz'" t-att-class="'fa fa-question-circle %s' % icon_class"></i>
|
||||
</template>
|
||||
|
||||
<template name="Display Promoted Slide" id="display_promoted_slide" inherit_id="website_slides.course_promoted_slide" active="True" customize_show="True">
|
||||
<xpath expr="//div[hasclass('o_wslides_promoted_slide')]" position="attributes">
|
||||
<attribute name="class">o_wslides_promoted_slide</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</data></odoo>
|
||||
|
||||
Reference in New Issue
Block a user