[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
This commit is contained in:
@@ -148,7 +148,7 @@ class TestUi(TestUICommon):
|
||||
(0, 0, {
|
||||
'name': 'DIY Furniture Certification',
|
||||
'sequence': 1,
|
||||
'slide_type': 'certification',
|
||||
'slide_category': 'certification',
|
||||
'category_id': False,
|
||||
'is_published': True,
|
||||
'is_preview': False,
|
||||
|
||||
@@ -67,7 +67,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
|
||||
def _set_completed_slide(self, slide):
|
||||
# quiz use their specific mechanism to be marked as done
|
||||
if slide.slide_type == 'quiz' or slide.question_ids:
|
||||
if slide.slide_category == 'quiz' or slide.question_ids:
|
||||
raise werkzeug.exceptions.Forbidden(_("Slide with questions must be marked as done when submitting all good answers "))
|
||||
if slide.website_published and slide.channel_id.is_member:
|
||||
slide.action_set_completed()
|
||||
@@ -331,12 +331,12 @@ class WebsiteSlides(WebsiteProfile):
|
||||
return request.render('website_slides.courses_home', values)
|
||||
|
||||
@http.route(['/slides/all', '/slides/all/tag/<string:slug_tags>'], type='http', auth="public", website=True, sitemap=True)
|
||||
def slides_channel_all(self, slide_type=None, slug_tags=None, my=False, **post):
|
||||
def slides_channel_all(self, slide_category=None, slug_tags=None, my=False, **post):
|
||||
""" Home page displaying a list of courses displayed according to some
|
||||
criterion and search terms.
|
||||
|
||||
:param string slide_type: if provided, filter the course to contain at
|
||||
least one slide of type 'slide_type'. Used notably to display courses
|
||||
:param string slide_category: if provided, filter the course to contain at
|
||||
least one slide of type 'slide_category'. Used notably to display courses
|
||||
with certifications;
|
||||
:param string slug_tags: if provided, filter the slide.channels having
|
||||
the tag(s) (in comma separated slugified form);
|
||||
@@ -347,6 +347,10 @@ class WebsiteSlides(WebsiteProfile):
|
||||
* ``search``: filter on course description / name;
|
||||
"""
|
||||
|
||||
# retro-compatibility for older links, 'slide_category' field was previously named 'slide_type'
|
||||
# can be safely removed after 15.3 (I swear though, don't be afraid, remove it!)
|
||||
slide_category = slide_category or post.get('slide_type')
|
||||
|
||||
if slug_tags and request.httprequest.method == 'GET':
|
||||
# Redirect `tag-1,tag-2` to `tag-1` to disallow multi tags
|
||||
# in GET request for proper bot indexation;
|
||||
@@ -355,7 +359,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
# request and so clearly it's not SEO bot.
|
||||
tag_list = slug_tags.split(',')
|
||||
if len(tag_list) > 1 and not post.get('search'):
|
||||
url = QueryURL('/slides/all', ['tag'], tag=tag_list[0], my=my, slide_type=slide_type)()
|
||||
url = QueryURL('/slides/all', ['tag'], tag=tag_list[0], my=my, slide_category=slide_category)()
|
||||
return request.redirect(url, code=302)
|
||||
|
||||
options = {
|
||||
@@ -367,7 +371,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
'allowFuzzy': not post.get('noFuzzy'),
|
||||
'my': my,
|
||||
'tag': slug_tags or post.get('tag'),
|
||||
'slide_type': slide_type,
|
||||
'slide_category': slide_category,
|
||||
}
|
||||
search = post.get('search')
|
||||
order = self._channel_order_by_criterion.get(post.get('sorting'))
|
||||
@@ -390,7 +394,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
'tag_groups': tag_groups,
|
||||
'search_term': fuzzy_search_term or search,
|
||||
'original_search': fuzzy_search_term and search,
|
||||
'search_slide_type': slide_type,
|
||||
'search_slide_category': slide_category,
|
||||
'search_my': my,
|
||||
'search_tags': search_tags,
|
||||
'top3_users': self._get_top3_users(),
|
||||
@@ -416,15 +420,20 @@ class WebsiteSlides(WebsiteProfile):
|
||||
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>',
|
||||
'/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):
|
||||
def channel(self, channel, category=None, tag=None, page=1, slide_category=None, uncategorized=False, sorting=None, search=None, **kw):
|
||||
"""
|
||||
Will return all necessary data to display the requested slide_channel along with a possible category.
|
||||
"""
|
||||
|
||||
# retro-compatibility for older links, 'slide_category' field was previously named 'slide_type'
|
||||
# can be safely removed after 15.3 (I swear though, don't be afraid, remove it!)
|
||||
slide_category = slide_category or kw.get('slide_type')
|
||||
|
||||
domain = self._get_channel_slides_base_domain(channel)
|
||||
|
||||
pager_url = "/slides/%s" % (channel.id)
|
||||
pager_args = {}
|
||||
slide_types = dict(request.env['slide.slide']._fields['slide_type']._description_selection(request.env))
|
||||
slide_categories = dict(request.env['slide.slide']._fields['slide_category']._description_selection(request.env))
|
||||
|
||||
if search:
|
||||
domain += [
|
||||
@@ -443,9 +452,9 @@ class WebsiteSlides(WebsiteProfile):
|
||||
if uncategorized:
|
||||
domain += [('category_id', '=', False)]
|
||||
pager_args['uncategorized'] = 1
|
||||
elif slide_type:
|
||||
domain += [('slide_type', '=', slide_type)]
|
||||
pager_url += "?slide_type=%s" % slide_type
|
||||
elif slide_category:
|
||||
domain += [('slide_category', '=', slide_category)]
|
||||
pager_url += "?slide_category=%s" % slide_category
|
||||
|
||||
# sorting criterion
|
||||
if channel.channel_type == 'documentation':
|
||||
@@ -467,8 +476,8 @@ class WebsiteSlides(WebsiteProfile):
|
||||
query_string = "?search_category=%s" % category.id
|
||||
elif tag:
|
||||
query_string = "?search_tag=%s" % tag.id
|
||||
elif slide_type:
|
||||
query_string = "?search_slide_type=%s" % slide_type
|
||||
elif slide_category:
|
||||
query_string = "?search_slide_category=%s" % slide_category
|
||||
elif uncategorized:
|
||||
query_string = "?search_uncategorized=1"
|
||||
|
||||
@@ -479,10 +488,10 @@ class WebsiteSlides(WebsiteProfile):
|
||||
# search
|
||||
'search_category': category,
|
||||
'search_tag': tag,
|
||||
'search_slide_type': slide_type,
|
||||
'search_slide_category': slide_category,
|
||||
'search_uncategorized': uncategorized,
|
||||
'query_string': query_string,
|
||||
'slide_types': slide_types,
|
||||
'slide_categories': slide_categories,
|
||||
'sorting': actual_sorting,
|
||||
'search': search,
|
||||
# display data
|
||||
@@ -704,8 +713,8 @@ class WebsiteSlides(WebsiteProfile):
|
||||
values.update({
|
||||
'search_category': slide.category_id if kwargs.get('search_category') else None,
|
||||
'search_tag': request.env['slide.tag'].browse(int(kwargs.get('search_tag'))) if kwargs.get('search_tag') else None,
|
||||
'slide_types': dict(request.env['slide.slide']._fields['slide_type']._description_selection(request.env)) if kwargs.get('search_slide_type') else None,
|
||||
'search_slide_type': kwargs.get('search_slide_type'),
|
||||
'slide_categories': dict(request.env['slide.slide']._fields['slide_category']._description_selection(request.env)) if kwargs.get('search_slide_category') else None,
|
||||
'search_slide_category': kwargs.get('search_slide_category'),
|
||||
'search_uncategorized': kwargs.get('search_uncategorized')
|
||||
})
|
||||
|
||||
@@ -724,7 +733,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
type='http', auth="public", website=True, sitemap=False)
|
||||
def slide_get_pdf_content(self, slide):
|
||||
response = werkzeug.wrappers.Response()
|
||||
response.data = slide.datas and base64.b64decode(slide.datas) or b''
|
||||
response.data = slide.binary_content and base64.b64decode(slide.binary_content) or b''
|
||||
response.mimetype = 'application/pdf'
|
||||
return response
|
||||
|
||||
@@ -1064,8 +1073,8 @@ class WebsiteSlides(WebsiteProfile):
|
||||
@http.route(['/slides/add_slide'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def create_slide(self, *args, **post):
|
||||
# check the size only when we upload a file.
|
||||
if post.get('datas'):
|
||||
file_size = len(post['datas']) * 3 / 4 # base64
|
||||
if post.get('binary_content'):
|
||||
file_size = len(post['binary_content']) * 3 / 4 # base64
|
||||
if (file_size / 1024.0 / 1024.0) > 25:
|
||||
return {'error': _('File is too big. File size cannot exceed 25MB')}
|
||||
|
||||
@@ -1117,9 +1126,9 @@ class WebsiteSlides(WebsiteProfile):
|
||||
channel._resequence_slides(slide, force_category=category)
|
||||
|
||||
redirect_url = "/slides/slide/%s" % (slide.id)
|
||||
if channel.channel_type == "training" and not slide.slide_type == "webpage":
|
||||
if channel.channel_type == "training" and not slide.slide_category == "webpage":
|
||||
redirect_url = "/slides/%s" % (slug(channel))
|
||||
if slide.slide_type == 'webpage':
|
||||
if slide.slide_category == 'webpage':
|
||||
redirect_url += "?enable_editor=1"
|
||||
return {
|
||||
'url': redirect_url,
|
||||
@@ -1129,8 +1138,8 @@ class WebsiteSlides(WebsiteProfile):
|
||||
}
|
||||
|
||||
def _get_valid_slide_post_values(self):
|
||||
return ['name', 'url', 'tag_ids', 'slide_type', 'channel_id', 'is_preview',
|
||||
'mime_type', 'datas', 'description', 'image_1920', 'is_published']
|
||||
return ['name', 'url', 'tag_ids', 'slide_category', 'channel_id', 'is_preview',
|
||||
'mime_type', 'binary_content', 'description', 'image_1920', 'is_published']
|
||||
|
||||
@http.route(['/slides/tag/search_read'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def slide_tag_search_read(self, fields, domain):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<record id="slide_template_published" model="mail.template">
|
||||
<field name="name">Slide Published</field>
|
||||
<field name="model_id" ref="model_slide_slide"/>
|
||||
<field name="subject">New {{ object.slide_type }} published on {{ object.channel_id.name }}</field>
|
||||
<field name="subject">New {{ object.slide_category }} published on {{ object.channel_id.name }}</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
@@ -36,14 +36,14 @@
|
||||
<record id="slide_template_shared" model="mail.template">
|
||||
<field name="name">Slide Shared</field>
|
||||
<field name="model_id" ref="model_slide_slide"/>
|
||||
<field name="subject">{{ user.name }} shared a {{ object.slide_type }} with you!</field>
|
||||
<field name="subject">{{ user.name }} shared a {{ object.slide_category }} with you!</field>
|
||||
<field name="email_from">{{ user.email_formatted }}</field>
|
||||
<field name="email_to">{{ ctx.get('email', '') }}</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
Hello<br/><br/>
|
||||
<t t-out="user.name or ''">Mitchell Admin</t> shared the <t t-out="object.slide_type or ''">document</t> <strong t-out="object.name or ''">Trees</strong> with you!
|
||||
<t t-out="user.name or ''">Mitchell Admin</t> shared the <t t-out="object.slide_category or ''">document</t> <strong t-out="object.name or ''">Trees</strong> with you!
|
||||
<div style="margin: 16px 8px 16px 8px; text-align: center;">
|
||||
<a t-att-href="(object.website_url + '?fullscreen=1') if ctx.get('fullscreen') else object.website_url">
|
||||
<img t-att-alt="object.name" t-attf-src="{{ ctx.get('base_url') }}/web/image/slide.slide/{{ object.id }}/image_1024" style="height:auto; width:150px; margin: 16px;"/>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<record id="slide_slide_demo_0_0" model="slide.slide">
|
||||
<field name="name">Gardening: The Know-How</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/channel-training-default.jpg"/>
|
||||
<field name="slide_type">presentation</field>
|
||||
<field name="slide_category">presentation</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_0_gard_0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -29,7 +29,7 @@
|
||||
<field name="name">Home Gardening</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_gardening_1.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_0_gard_0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -43,7 +43,7 @@
|
||||
<field name="name">Mighty Carrots</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_gardening_2.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_0_gard_0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -56,9 +56,9 @@
|
||||
<record id="slide_slide_demo_0_3" model="slide.slide">
|
||||
<field name="name">How to Grow and Harvest The Best Strawberries | Basics</field>
|
||||
<field name="sequence">4</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_l0JZ25VvbwE.jpg"/>
|
||||
<field name="slide_type">document</field>
|
||||
<field name="slide_category">document</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_0_gard_0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -72,7 +72,7 @@
|
||||
<field name="name">Test your knowledge</field>
|
||||
<field name="sequence">5</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_owl.jpg"/>
|
||||
<field name="slide_type">quiz</field>
|
||||
<field name="slide_category">quiz</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_0_gard_0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -149,7 +149,7 @@
|
||||
<field name="name">Tree Infographic</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_infographic_1.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -163,7 +163,7 @@
|
||||
<field name="name">Interesting Tree Facts</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_infographic_2.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -177,7 +177,7 @@
|
||||
<field name="name">Energy Efficiency Facts</field>
|
||||
<field name="sequence">3</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_infographic_3.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -212,7 +212,7 @@
|
||||
<field name="url">https://www.youtube.com/watch?v=QYmgrw0PgLU</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_QYmgrw0PgLU.jpg"/>
|
||||
<field name="document_id">QYmgrw0PgLU</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -226,7 +226,7 @@
|
||||
<field name="name">A little chat with Harry Potted</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_img_1.jpg"/>
|
||||
<field name="slide_type">webpage</field>
|
||||
<field name="slide_category">webpage</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="html_content" type="html">
|
||||
<section class="s_cover parallax bg-black-50 pt16 pb16" data-scroll-background-ratio="0" style="background-image: none;" data-snippet="s_cover">
|
||||
@@ -327,9 +327,9 @@
|
||||
<record id="slide_slide_demo_1_5" model="slide.slide">
|
||||
<field name="name">3 Main Methodologies</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/channel-training-default.jpg"/>
|
||||
<field name="slide_type">presentation</field>
|
||||
<field name="slide_category">presentation</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -345,7 +345,7 @@
|
||||
<field name="url">https://www.youtube.com/watch?v=l0JZ25VvbwE</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_l0JZ25VvbwE.jpg"/>
|
||||
<field name="document_id">l0JZ25VvbwE</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -378,9 +378,9 @@
|
||||
<record id="slide_slide_demo_2_0" model="slide.slide">
|
||||
<field name="name">Main Trees Categories</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_img_2.jpg"/>
|
||||
<field name="slide_type">presentation</field>
|
||||
<field name="slide_category">presentation</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -464,7 +464,7 @@
|
||||
<field name="name">A Mighty Forest from Ages</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_tree_img_3.jpg"/>
|
||||
<field name="slide_type">webpage</field>
|
||||
<field name="slide_category">webpage</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
|
||||
<field name="html_content" type="html">
|
||||
<section class="s_cover parallax bg-black-50 pt16 pb16" data-scroll-background-ratio="0" style="background-image: none;" data-snippet="s_cover">
|
||||
@@ -513,7 +513,7 @@
|
||||
<field name="url">https://www.youtube.com/watch?v=ebBez6bcSEc</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_ebBez6bcSEc.jpg"/>
|
||||
<field name="document_id">ebBez6bcSEc</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -527,9 +527,9 @@
|
||||
<record id="slide_slide_demo_2_3" model="slide.slide">
|
||||
<field name="name">Wood Characteristics</field>
|
||||
<field name="sequence">5</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/channel-documentation-default.jpg"/>
|
||||
<field name="slide_type">presentation</field>
|
||||
<field name="slide_category">presentation</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -561,7 +561,7 @@
|
||||
<field name="name">Comparing Hardness of Wood Species</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_wood_infographic_1.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_3_furn0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -577,7 +577,7 @@
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_PYr1rK8pS30.jpg"/>
|
||||
<field name="url">https://www.youtube.com/watch?v=PYr1rK8pS30</field>
|
||||
<field name="document_id">PYr1rK8pS30</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_3_furn0"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -609,7 +609,7 @@
|
||||
<field name="name">Foreword</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_furniture_2.jpg"/>
|
||||
<field name="slide_type">webpage</field>
|
||||
<field name="slide_category">webpage</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
|
||||
<field name="html_content" type="html">
|
||||
<section class="s_cover parallax bg-black-50 pt16 pb16" data-scroll-background-ratio="0" style="background-image: none;" data-snippet="s_cover">
|
||||
@@ -656,7 +656,7 @@
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_bvSe6r5BpaY.jpg"/>
|
||||
<field name="url">https://www.youtube.com/watch?v=bvSe6r5BpaY</field>
|
||||
<field name="document_id">bvSe6r5BpaY</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=3)"/>
|
||||
@@ -670,7 +670,7 @@
|
||||
<field name="name">Drawing 1</field>
|
||||
<field name="sequence">11</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_furniture_img.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=4)"/>
|
||||
@@ -684,7 +684,7 @@
|
||||
<field name="name">Drawing 2</field>
|
||||
<field name="sequence">12</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_furniture_img_1.jpg"/>
|
||||
<field name="slide_type">infographic</field>
|
||||
<field name="slide_category">infographic</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=4)"/>
|
||||
@@ -697,9 +697,9 @@
|
||||
<record id="slide_slide_demo_4_12" model="slide.slide">
|
||||
<field name="name">Presentation</field>
|
||||
<field name="sequence">13</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/channel-documentation-default.jpg"/>
|
||||
<field name="slide_type">document</field>
|
||||
<field name="slide_category">document</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=4)"/>
|
||||
@@ -739,9 +739,9 @@
|
||||
<record id="slide_slide_demo_5_0" model="slide.slide">
|
||||
<field name="name">Unforgettable Tools</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="datas" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="binary_content" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/channel-training-default.jpg"/>
|
||||
<field name="slide_type">presentation</field>
|
||||
<field name="slide_category">presentation</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -769,7 +769,7 @@
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_5WMqwTnZ-qs.jpg"/>
|
||||
<field name="url">https://www.youtube.com/watch?v=5WMqwTnZ-qs</field>
|
||||
<field name="document_id">5WMqwTnZ-qs</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -784,7 +784,7 @@
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_thumb_grrXe1QZNzQ.jpg"/>
|
||||
<field name="url">https://www.youtube.com/watch?v=grrXe1QZNzQ</field>
|
||||
<field name="document_id">grrXe1QZNzQ</field>
|
||||
<field name="slide_type">video</field>
|
||||
<field name="slide_category">video</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
@@ -797,7 +797,7 @@
|
||||
<field name="name">Test your knowledge !</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_owl.jpg"/>
|
||||
<field name="slide_type">quiz</field>
|
||||
<field name="slide_category">quiz</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="date_published" eval="datetime.now() - timedelta(days=8)"/>
|
||||
|
||||
@@ -300,18 +300,18 @@ class Channel(models.Model):
|
||||
channel.slide_category_ids = channel.slide_ids.filtered(lambda slide: slide.is_category)
|
||||
channel.slide_content_ids = channel.slide_ids - channel.slide_category_ids
|
||||
|
||||
@api.depends('slide_ids.slide_type', 'slide_ids.is_published', 'slide_ids.completion_time',
|
||||
@api.depends('slide_ids.slide_category', 'slide_ids.is_published', 'slide_ids.completion_time',
|
||||
'slide_ids.likes', 'slide_ids.dislikes', 'slide_ids.total_views', 'slide_ids.is_category', 'slide_ids.active')
|
||||
def _compute_slides_statistics(self):
|
||||
default_vals = dict(total_views=0, total_votes=0, total_time=0, total_slides=0)
|
||||
keys = ['nbr_%s' % slide_type for slide_type in self.env['slide.slide']._fields['slide_type'].get_values(self.env)]
|
||||
keys = ['nbr_%s' % slide_category for slide_category in self.env['slide.slide']._fields['slide_category'].get_values(self.env)]
|
||||
default_vals.update(dict((key, 0) for key in keys))
|
||||
|
||||
result = dict((cid, dict(default_vals)) for cid in self.ids)
|
||||
read_group_res = self.env['slide.slide'].read_group(
|
||||
[('active', '=', True), ('is_published', '=', True), ('channel_id', 'in', self.ids), ('is_category', '=', False)],
|
||||
['channel_id', 'slide_type', 'likes', 'dislikes', 'total_views', 'completion_time'],
|
||||
groupby=['channel_id', 'slide_type'],
|
||||
['channel_id', 'slide_category', 'likes', 'dislikes', 'total_views', 'completion_time'],
|
||||
groupby=['channel_id', 'slide_category'],
|
||||
lazy=False)
|
||||
for res_group in read_group_res:
|
||||
cid = res_group['channel_id'][0]
|
||||
@@ -320,25 +320,25 @@ class Channel(models.Model):
|
||||
result[cid]['total_votes'] -= res_group.get('dislikes', 0)
|
||||
result[cid]['total_time'] += res_group.get('completion_time', 0)
|
||||
|
||||
type_stats = self._compute_slides_statistics_type(read_group_res)
|
||||
for cid, cdata in type_stats.items():
|
||||
category_stats = self._compute_slides_statistics_category(read_group_res)
|
||||
for cid, cdata in category_stats.items():
|
||||
result[cid].update(cdata)
|
||||
|
||||
for record in self:
|
||||
record.update(result.get(record.id, default_vals))
|
||||
|
||||
def _compute_slides_statistics_type(self, read_group_res):
|
||||
""" Compute statistics based on all existing slide types """
|
||||
slide_types = self.env['slide.slide']._fields['slide_type'].get_values(self.env)
|
||||
keys = ['nbr_%s' % slide_type for slide_type in slide_types]
|
||||
def _compute_slides_statistics_category(self, read_group_res):
|
||||
""" Compute statistics based on all existing slide categories """
|
||||
slide_categories = self.env['slide.slide']._fields['slide_category'].get_values(self.env)
|
||||
keys = ['nbr_%s' % slide_category for slide_category in slide_categories]
|
||||
result = dict((cid, dict((key, 0) for key in keys + ['total_slides'])) for cid in self.ids)
|
||||
for res_group in read_group_res:
|
||||
cid = res_group['channel_id'][0]
|
||||
slide_type = res_group.get('slide_type')
|
||||
if slide_type:
|
||||
slide_type_count = res_group.get('__count', 0)
|
||||
result[cid]['nbr_%s' % slide_type] = slide_type_count
|
||||
result[cid]['total_slides'] += slide_type_count
|
||||
slide_category = res_group.get('slide_category')
|
||||
if slide_category:
|
||||
slide_category_count = res_group.get('__count', 0)
|
||||
result[cid]['nbr_%s' % slide_category] = slide_category_count
|
||||
result[cid]['total_slides'] += slide_category_count
|
||||
return result
|
||||
|
||||
def _compute_rating_stats(self):
|
||||
@@ -847,7 +847,7 @@ class Channel(models.Model):
|
||||
with_date = options['displayDetail']
|
||||
my = options.get('my')
|
||||
search_tags = options.get('tag')
|
||||
slide_type = options.get('slide_type')
|
||||
slide_category = options.get('slide_category')
|
||||
domain = [website.website_domain()]
|
||||
if my:
|
||||
domain.append([('partner_ids', '=', self.env.user.partner_id.id)])
|
||||
@@ -865,8 +865,8 @@ class Channel(models.Model):
|
||||
# OR inside a group, AND between groups.
|
||||
for group in grouped_tags:
|
||||
domain.append([('tag_ids', 'in', [tag.id for tag in grouped_tags[group]])])
|
||||
if slide_type and 'nbr_%s' % slide_type in self:
|
||||
domain.append([('nbr_%s' % slide_type, '>', 0)])
|
||||
if slide_category and 'nbr_%s' % slide_category in self:
|
||||
domain.append([('nbr_%s' % slide_category, '>', 0)])
|
||||
search_fields = ['name']
|
||||
fetch_fields = ['name', 'website_url']
|
||||
mapping = {
|
||||
|
||||
@@ -118,23 +118,23 @@ class Slide(models.Model):
|
||||
quiz_third_attempt_reward = fields.Integer("Reward: third attempt", default=5,)
|
||||
quiz_fourth_attempt_reward = fields.Integer("Reward: every attempt after the third try", default=2)
|
||||
# content
|
||||
slide_type = fields.Selection([
|
||||
slide_category = fields.Selection([
|
||||
('infographic', 'Infographic'),
|
||||
('webpage', 'Web Page'),
|
||||
('presentation', 'Presentation'),
|
||||
('document', 'Document'),
|
||||
('video', 'Video'),
|
||||
('quiz', "Quiz")],
|
||||
string='Type', required=True,
|
||||
string='Category', required=True,
|
||||
default='document',
|
||||
help="The document type will be set automatically based on the document URL and properties (e.g. height and width for presentation and document).")
|
||||
datas = fields.Binary('File', attachment=True)
|
||||
help="The document category will be set automatically based on the document URL and properties (e.g. height and width for presentation and document).")
|
||||
binary_content = fields.Binary('File', attachment=True)
|
||||
url = fields.Char('Document URL', help="Youtube or Google Document URL")
|
||||
document_id = fields.Char('Document ID', help="Youtube or Google Document ID")
|
||||
slide_resource_ids = fields.One2many('slide.slide.resource', 'slide_id', string="Additional Resource for this slide")
|
||||
slide_resource_downloadable = fields.Boolean('Allow Download', default=True, help="Allow the user to download the content of the slide.")
|
||||
mime_type = fields.Char('Mime-type')
|
||||
html_content = fields.Html("HTML Content", help="Custom HTML content for slides of type 'Web Page'.", translate=True, sanitize_attributes=False, sanitize_form=False)
|
||||
html_content = fields.Html("HTML Content", help="Custom HTML content for slides of category 'Web Page'.", translate=True, sanitize_attributes=False, sanitize_form=False)
|
||||
# website
|
||||
website_id = fields.Many2one(related='channel_id.website_id', readonly=True)
|
||||
date_published = fields.Datetime('Publish Date', readonly=True, tracking=False)
|
||||
@@ -270,35 +270,35 @@ class Slide(models.Model):
|
||||
for slide in self:
|
||||
slide.embed_count = mapped_data.get(slide.id, 0)
|
||||
|
||||
@api.depends('slide_ids.sequence', 'slide_ids.slide_type', 'slide_ids.is_published', 'slide_ids.is_category')
|
||||
@api.depends('slide_ids.sequence', 'slide_ids.slide_category', 'slide_ids.is_published', 'slide_ids.is_category')
|
||||
def _compute_slides_statistics(self):
|
||||
# Do not use dict.fromkeys(self.ids, dict()) otherwise it will use the same dictionnary for all keys.
|
||||
# Therefore, when updating the dict of one key, it updates the dict of all keys.
|
||||
keys = ['nbr_%s' % slide_type for slide_type in self.env['slide.slide']._fields['slide_type'].get_values(self.env)]
|
||||
keys = ['nbr_%s' % slide_category for slide_category in self.env['slide.slide']._fields['slide_category'].get_values(self.env)]
|
||||
default_vals = dict((key, 0) for key in keys + ['total_slides'])
|
||||
|
||||
res = self.env['slide.slide'].read_group(
|
||||
[('is_published', '=', True), ('category_id', 'in', self.ids), ('is_category', '=', False)],
|
||||
['category_id', 'slide_type'], ['category_id', 'slide_type'],
|
||||
['category_id', 'slide_category'], ['category_id', 'slide_category'],
|
||||
lazy=False)
|
||||
|
||||
type_stats = self._compute_slides_statistics_type(res)
|
||||
category_stats = self._compute_slides_statistics_category(res)
|
||||
|
||||
for record in self:
|
||||
record.update(type_stats.get(record._origin.id, default_vals))
|
||||
record.update(category_stats.get(record._origin.id, default_vals))
|
||||
|
||||
def _compute_slides_statistics_type(self, read_group_res):
|
||||
""" Compute statistics based on all existing slide types """
|
||||
slide_types = self.env['slide.slide']._fields['slide_type'].get_values(self.env)
|
||||
keys = ['nbr_%s' % slide_type for slide_type in slide_types]
|
||||
def _compute_slides_statistics_category(self, read_group_res):
|
||||
""" Compute statistics based on all existing slide categories """
|
||||
slide_categories = self.env['slide.slide']._fields['slide_category'].get_values(self.env)
|
||||
keys = ['nbr_%s' % slide_category for slide_category in slide_categories]
|
||||
result = dict((cid, dict((key, 0) for key in keys + ['total_slides'])) for cid in self.ids)
|
||||
for res_group in read_group_res:
|
||||
cid = res_group['category_id'][0]
|
||||
slide_type = res_group.get('slide_type')
|
||||
if slide_type:
|
||||
slide_type_count = res_group.get('__count', 0)
|
||||
result[cid]['nbr_%s' % slide_type] = slide_type_count
|
||||
result[cid]['total_slides'] += slide_type_count
|
||||
slide_category = res_group.get('slide_category')
|
||||
if slide_category:
|
||||
slide_category_count = res_group.get('__count', 0)
|
||||
result[cid]['nbr_%s' % slide_category] = slide_category_count
|
||||
result[cid]['total_slides'] += slide_category_count
|
||||
return result
|
||||
|
||||
@api.depends('slide_partner_ids.partner_id')
|
||||
@@ -315,7 +315,7 @@ class Slide(models.Model):
|
||||
self.env['slide.slide.partner']
|
||||
)
|
||||
|
||||
@api.depends('document_id', 'slide_type', 'mime_type')
|
||||
@api.depends('document_id', 'slide_category', 'mime_type')
|
||||
def _compute_embed_code(self):
|
||||
base_url = request and request.httprequest.url_root
|
||||
|
||||
@@ -326,13 +326,13 @@ class Slide(models.Model):
|
||||
base_url = record.get_base_url()
|
||||
if base_url[-1] == '/':
|
||||
base_url = base_url[:-1]
|
||||
if record.datas and (not record.document_id or record.slide_type in ['document', 'presentation']):
|
||||
if record.binary_content and (not record.document_id or record.slide_category in ['document', 'presentation']):
|
||||
slide_url = base_url + url_for('/slides/embed/%s?page=1' % record.id)
|
||||
slide_url_external = base_url + url_for('/slides/embed_external/%s?page=1' % record.id)
|
||||
base_embed_code = Markup('<iframe src="%s" class="o_wslides_iframe_viewer" allowFullScreen="true" height="%s" width="%s" frameborder="0"></iframe>')
|
||||
record.embed_code = base_embed_code % (slide_url, 315, 420)
|
||||
embed_code_external = base_embed_code % (slide_url_external, 315, 420)
|
||||
elif record.slide_type == 'video' and record.document_id:
|
||||
elif record.slide_category == 'video' and record.document_id:
|
||||
if not record.mime_type:
|
||||
# embed youtube video
|
||||
query = urls.url_parse(record.url).query
|
||||
@@ -359,15 +359,15 @@ class Slide(models.Model):
|
||||
for key, value in values.items():
|
||||
self[key] = value
|
||||
|
||||
@api.onchange('datas')
|
||||
def _on_change_datas(self):
|
||||
@api.onchange('binary_content')
|
||||
def _on_change_binary_content(self):
|
||||
""" For PDFs, we assume that it takes 5 minutes to read a page.
|
||||
If the selected file is not a PDF, it is an image (You can
|
||||
only upload PDF or Image file) then the slide_type is changed
|
||||
into infographic and the uploaded dataS is transfered to the
|
||||
only upload PDF or Image file) then the slide_category is changed
|
||||
into infographic and the uploaded binary_content is transfered to the
|
||||
image field. (It avoids the infinite loading in PDF viewer)"""
|
||||
if self.datas:
|
||||
data = base64.b64decode(self.datas)
|
||||
if self.binary_content:
|
||||
data = base64.b64decode(self.binary_content)
|
||||
if data.startswith(b'%PDF-'):
|
||||
pdf = PyPDF2.PdfFileReader(io.BytesIO(data), overwriteWarnings=False, strict=False)
|
||||
try:
|
||||
@@ -376,9 +376,9 @@ class Slide(models.Model):
|
||||
return
|
||||
self.completion_time = (5 * len(pdf.pages)) / 60
|
||||
else:
|
||||
self.slide_type = 'infographic'
|
||||
self.image_1920 = self.datas
|
||||
self.datas = None
|
||||
self.slide_category = 'infographic'
|
||||
self.image_1920 = self.binary_content
|
||||
self.binary_content = None
|
||||
|
||||
@api.depends('name', 'channel_id.website_id.domain')
|
||||
def _compute_website_url(self):
|
||||
@@ -409,8 +409,8 @@ class Slide(models.Model):
|
||||
# 'website_published' is handled by mixin
|
||||
values['date_published'] = False
|
||||
|
||||
if values.get('slide_type') == 'infographic' and not values.get('image_1920'):
|
||||
values['image_1920'] = values['datas']
|
||||
if values.get('slide_category') == 'infographic' and not values.get('image_1920'):
|
||||
values['image_1920'] = values['binary_content']
|
||||
if values.get('is_category'):
|
||||
values['is_preview'] = True
|
||||
values['is_published'] = True
|
||||
@@ -794,7 +794,7 @@ class Slide(models.Model):
|
||||
if fetch_res.get('error'):
|
||||
return {'error': self._extract_google_error_message(fetch_res.get('error'))}
|
||||
|
||||
values = {'slide_type': 'video', 'document_id': document_id}
|
||||
values = {'slide_category': 'video', 'document_id': document_id}
|
||||
items = fetch_res['values'].get('items')
|
||||
if not items:
|
||||
return {'error': _('Please enter valid Youtube or Google Doc URL')}
|
||||
@@ -845,15 +845,15 @@ class Slide(models.Model):
|
||||
|
||||
@api.model
|
||||
def _parse_google_document(self, document_id, only_preview_fields):
|
||||
def get_slide_type(vals):
|
||||
def get_slide_category(vals):
|
||||
# TDE FIXME: WTF ??
|
||||
slide_type = 'presentation'
|
||||
slide_category = 'presentation'
|
||||
if vals.get('image_1920'):
|
||||
image = Image.open(io.BytesIO(base64.b64decode(vals['image_1920'])))
|
||||
width, height = image.size
|
||||
if height > width:
|
||||
return 'document'
|
||||
return slide_type
|
||||
return slide_category
|
||||
|
||||
# Google drive doesn't use a simple API key to access the data, but requires an access
|
||||
# token. However, this token is generated in module google_drive, which is not in the
|
||||
@@ -886,18 +886,18 @@ class Slide(models.Model):
|
||||
'document_id': document_id,
|
||||
}
|
||||
if google_values['mimeType'].startswith('video/'):
|
||||
values['slide_type'] = 'video'
|
||||
values['slide_category'] = 'video'
|
||||
elif google_values['mimeType'].startswith('image/'):
|
||||
values['datas'] = values['image_1920']
|
||||
values['slide_type'] = 'infographic'
|
||||
values['binary_content'] = values['image_1920']
|
||||
values['slide_category'] = 'infographic'
|
||||
elif google_values['mimeType'].startswith('application/vnd.google-apps'):
|
||||
values['slide_type'] = get_slide_type(values)
|
||||
values['slide_category'] = get_slide_category(values)
|
||||
if 'exportLinks' in google_values:
|
||||
values['datas'] = self._fetch_data(google_values['exportLinks']['application/pdf'], params, 'pdf')['values']
|
||||
values['binary_content'] = self._fetch_data(google_values['exportLinks']['application/pdf'], params, 'pdf')['values']
|
||||
elif google_values['mimeType'] == 'application/pdf':
|
||||
# TODO: Google Drive PDF document doesn't provide plain text transcript
|
||||
values['datas'] = self._fetch_data(google_values['webContentLink'], {}, 'pdf')['values']
|
||||
values['slide_type'] = get_slide_type(values)
|
||||
values['binary_content'] = self._fetch_data(google_values['webContentLink'], {}, 'pdf')['values']
|
||||
values['slide_category'] = get_slide_category(values)
|
||||
|
||||
return {'values': values}
|
||||
|
||||
@@ -942,7 +942,7 @@ class Slide(models.Model):
|
||||
}
|
||||
|
||||
def _search_render_results(self, fetch_fields, mapping, icon, limit):
|
||||
icon_per_type = {
|
||||
icon_per_category = {
|
||||
'infographic': 'fa-file-picture-o',
|
||||
'webpage': 'fa-file-text',
|
||||
'presentation': 'fa-file-pdf-o',
|
||||
@@ -953,7 +953,7 @@ class Slide(models.Model):
|
||||
}
|
||||
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
|
||||
for slide, data in zip(self, results_data):
|
||||
data['_fa'] = icon_per_type.get(slide.slide_type, 'fa-file-pdf-o')
|
||||
data['_fa'] = icon_per_category.get(slide.slide_category, 'fa-file-pdf-o')
|
||||
data['url'] = slide.website_url
|
||||
data['course'] = _('Course: %s', slide.channel_id.name)
|
||||
data['course_url'] = slide.channel_id.website_url
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* Handler called whenever the user clicks on a sub-quiz which is linked to a slide.
|
||||
* This does NOT handle the case of a slide of type "quiz".
|
||||
* This does NOT handle the case of a slide of category "quiz".
|
||||
* By going through this handler, the widget will be able to determine that it has to render
|
||||
* the associated quiz and not the main content.
|
||||
*
|
||||
@@ -455,7 +455,7 @@
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* Fetches content with an rpc call for slides of type "webpage"
|
||||
* Fetches content with an rpc call for slides of category "webpage"
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
@@ -474,14 +474,14 @@
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Fetches slide content depending on its type.
|
||||
* Fetches slide content depending on its category.
|
||||
* If the slide doesn't need to fetch any content, return a resolved deferred
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_fetchSlideContent: function (){
|
||||
var slide = this.get('slide');
|
||||
if (slide.type === 'webpage' && !slide.isQuiz) {
|
||||
if (slide.category === 'webpage' && !slide.isQuiz) {
|
||||
return this._fetchHtmlContent();
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -494,14 +494,14 @@
|
||||
},
|
||||
/**
|
||||
* Extend the slide data list to add informations about rendering method, and other
|
||||
* specific values according to their slide_type.
|
||||
* specific values according to their slide_category.
|
||||
*/
|
||||
_preprocessSlideData: function (slidesDataList) {
|
||||
slidesDataList.forEach(function (slideData, index) {
|
||||
// compute hasNext slide
|
||||
slideData.hasNext = index < slidesDataList.length-1;
|
||||
// compute embed url
|
||||
if (slideData.type === 'video') {
|
||||
if (slideData.category === 'video') {
|
||||
slideData.embedCode = $(slideData.embedCode).attr('src') || ""; // embedCode contains an iframe tag, where src attribute is the url (youtube or embed document from odoo)
|
||||
var separator = slideData.embedCode.indexOf("?") !== -1 ? "&" : "?";
|
||||
var scheme = slideData.embedCode.indexOf('//') === 0 ? 'https:' : '';
|
||||
@@ -510,16 +510,16 @@
|
||||
params.autoplay = 1;
|
||||
}
|
||||
slideData.embedUrl = slideData.embedCode ? scheme + slideData.embedCode + separator + $.param(params) : "";
|
||||
} else if (slideData.type === 'infographic') {
|
||||
} else if (slideData.category === 'infographic') {
|
||||
slideData.embedUrl = _.str.sprintf('/web/image/slide.slide/%s/image_1024', slideData.id);
|
||||
} else if (_.contains(['document', 'presentation'], slideData.type)) {
|
||||
} else if (_.contains(['document', 'presentation'], slideData.category)) {
|
||||
slideData.embedUrl = $(slideData.embedCode).attr('src');
|
||||
}
|
||||
// fill empty property to allow searching on it with _.filter(list, matcher)
|
||||
slideData.isQuiz = !!slideData.isQuiz;
|
||||
slideData.hasQuestion = !!slideData.hasQuestion;
|
||||
// technical settings for the Fullscreen to work
|
||||
slideData._autoSetDone = _.contains(['infographic', 'presentation', 'document', 'webpage'], slideData.type) && !slideData.hasQuestion;
|
||||
slideData._autoSetDone = _.contains(['infographic', 'presentation', 'document', 'webpage'], slideData.category) && !slideData.hasQuestion;
|
||||
});
|
||||
return slidesDataList;
|
||||
},
|
||||
@@ -542,7 +542,7 @@
|
||||
history.pushState(null, '', fullscreenUrl);
|
||||
},
|
||||
/**
|
||||
* Render the current slide content using specific mecanism according to slide type:
|
||||
* Render the current slide content using specific mecanism according to slide category:
|
||||
* - simply append content (for webpage)
|
||||
* - template rendering (for image, document, ....)
|
||||
* - using a sub widget (quiz and video)
|
||||
@@ -556,19 +556,19 @@
|
||||
$content.empty();
|
||||
|
||||
// display quiz slide, or quiz attached to a slide
|
||||
if (slide.type === 'quiz' || slide.isQuiz) {
|
||||
if (slide.category === 'quiz' || slide.isQuiz) {
|
||||
$content.addClass('bg-white');
|
||||
var QuizWidget = new Quiz(this, slide, this.channel);
|
||||
return QuizWidget.appendTo($content);
|
||||
}
|
||||
|
||||
// render slide content
|
||||
if (_.contains(['document', 'presentation', 'infographic'], slide.type)) {
|
||||
if (_.contains(['document', 'presentation', 'infographic'], slide.category)) {
|
||||
$content.html(QWeb.render('website.slides.fullscreen.content', {widget: this}));
|
||||
} else if (slide.type === 'video') {
|
||||
} else if (slide.category === 'video') {
|
||||
this.videoPlayer = new VideoPlayer(this, slide);
|
||||
return this.videoPlayer.appendTo($content);
|
||||
} else if (slide.type === 'webpage'){
|
||||
} else if (slide.category === 'webpage'){
|
||||
var $wpContainer = $('<div>').addClass('o_wslide_fs_webpage_content bg-white block w-100 overflow-auto');
|
||||
$(slide.htmlContent).appendTo($wpContainer);
|
||||
$content.append($wpContainer);
|
||||
@@ -608,7 +608,7 @@
|
||||
* Triggered whenever the user changes slides.
|
||||
* When the current slide is changed, widget will be automatically updated
|
||||
* and allowed to: fetch the content if needed, render it, update the url,
|
||||
* and set slide as "completed" according to its type requirements. In
|
||||
* and set slide as "completed" according to its category requirements. In
|
||||
* mobile case (i.e. limited screensize), sidebar will be toggled since
|
||||
* sidebar will block most or all of new slide visibility.
|
||||
*
|
||||
@@ -627,7 +627,7 @@
|
||||
return self._renderSlide();
|
||||
}).then(function() {
|
||||
if (slide._autoSetDone && !session.is_website_user) { // no useless RPC call
|
||||
if (['document', 'presentation'].includes(slide.type)) {
|
||||
if (['document', 'presentation'].includes(slide.category)) {
|
||||
// only set the slide as completed after iFrame is loaded to avoid concurrent execution with 'embedUrl' controller
|
||||
self.el.querySelector('iframe.o_wslides_iframe_viewer').addEventListener('load', () => self._setCompleted(slide.id));
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* This widget is responsible of displaying quiz questions and propositions. Submitting the quiz will fetch the
|
||||
* correction and decorate the answers according to the result. Error message or modal can be displayed.
|
||||
*
|
||||
* This widget can be attached to DOM rendered server-side by `website_slides.slide_type_quiz` or
|
||||
* This widget can be attached to DOM rendered server-side by `website_slides.slide_category_quiz` or
|
||||
* used client side (Fullscreen).
|
||||
*
|
||||
* Triggered events are :
|
||||
|
||||
@@ -10,7 +10,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
template: 'website.slide.upload.modal',
|
||||
events: _.extend({}, Dialog.prototype.events, {
|
||||
'click .o_wslides_js_upload_install_button': '_onClickInstallModule',
|
||||
'click .o_wslides_select_type': '_onClickSlideTypeIcon',
|
||||
'click .o_wslides_select_category': '_onClickSlideCategoryIcon',
|
||||
'change input#upload': '_onChangeSlideUpload',
|
||||
'change input#url': '_onChangeSlideUrl',
|
||||
}),
|
||||
@@ -120,7 +120,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
return form[0].checkValidity() && this.isValidUrl;
|
||||
},
|
||||
/**
|
||||
* Extract values to submit from form, force the slide_type according to
|
||||
* Extract values to submit from form, force the slide_category according to
|
||||
* filled values.
|
||||
*
|
||||
* @private
|
||||
@@ -136,30 +136,30 @@ var SlideUploadDialog = Dialog.extend({
|
||||
'is_published': forcePublished,
|
||||
}, this._getSelect2DropdownValues()); // add tags and category
|
||||
|
||||
// default slide_type (for webpage for instance)
|
||||
if (_.contains(this.slide_type_data), this.get('state')) {
|
||||
values['slide_type'] = this.get('state');
|
||||
// default slide_category (for webpage for instance)
|
||||
if (_.contains(this.slide_category_data), this.get('state')) {
|
||||
values['slide_category'] = this.get('state');
|
||||
}
|
||||
|
||||
if (this.file.type === 'application/pdf') {
|
||||
_.extend(values, {
|
||||
'image_1920': canvas.toDataURL().split(',')[1],
|
||||
'slide_type': canvas.height > canvas.width ? 'document' : 'presentation',
|
||||
'slide_category': canvas.height > canvas.width ? 'document' : 'presentation',
|
||||
'mime_type': this.file.type,
|
||||
'datas': this.file.data
|
||||
'binary_content': this.file.data
|
||||
});
|
||||
} else if (values['slide_type'] === 'webpage') {
|
||||
} else if (values['slide_category'] === 'webpage') {
|
||||
_.extend(values, {
|
||||
'mime_type': 'text/html',
|
||||
'image_1920': this.file.type === 'image/svg+xml' ? await this._svgToPNG() : this.file.data,
|
||||
});
|
||||
} else if (/^image\/.*/.test(this.file.type)) {
|
||||
const fileData = this.file.type === 'image/svg+xml' ? await this._svgToPNG() : this.file.data;
|
||||
if (values['slide_type'] === 'presentation') {
|
||||
if (values['slide_category'] === 'presentation') {
|
||||
_.extend(values, {
|
||||
'slide_type': 'infographic',
|
||||
'slide_category': 'infographic',
|
||||
'mime_type': this.file.type === 'image/svg+xml' ? 'image/png' : this.file.type,
|
||||
'datas': fileData,
|
||||
'binary_content': fileData,
|
||||
});
|
||||
} else {
|
||||
_.extend(values, {
|
||||
@@ -321,12 +321,12 @@ var SlideUploadDialog = Dialog.extend({
|
||||
return values;
|
||||
},
|
||||
/**
|
||||
* Init the data relative to the support slide type to upload
|
||||
* Init the data relative to the support slide category to upload
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setup: function () {
|
||||
this.slide_type_data = {
|
||||
this.slide_category_data = {
|
||||
presentation: {
|
||||
icon: 'fa-file-pdf-o',
|
||||
label: _t('Presentation'),
|
||||
@@ -393,7 +393,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
} else if (currentType === '_import') {
|
||||
tmpl = 'website.slide.upload.modal.import';
|
||||
} else {
|
||||
tmpl = this.slide_type_data[currentType]['template'];
|
||||
tmpl = this.slide_category_data[currentType]['template'];
|
||||
this.$modal.find('.modal-dialog').addClass('modal-lg');
|
||||
}
|
||||
this.$('.o_w_slide_upload_modal_container').empty();
|
||||
@@ -623,10 +623,10 @@ var SlideUploadDialog = Dialog.extend({
|
||||
}
|
||||
},
|
||||
|
||||
_onClickSlideTypeIcon: function (ev) {
|
||||
_onClickSlideCategoryIcon: function (ev) {
|
||||
var $elem = this.$(ev.currentTarget);
|
||||
var slideType = $elem.data('slideType');
|
||||
this.set('state', slideType);
|
||||
var slideCategory = $elem.data('slideCategory');
|
||||
this.set('state', slideCategory);
|
||||
|
||||
this._bindSelect2Dropdown(); // rebind select2 at each modal body rendering
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ tour.register('slides_tour', {
|
||||
content: Markup(_t("Your first section is created, now it's time to add lessons to your course. Click on <b>Add Content</b> to upload a document, create a web page or link a video.")),
|
||||
position: 'bottom',
|
||||
}, {
|
||||
trigger: 'a[data-slide-type="presentation"]',
|
||||
trigger: 'a[data-slide-category="presentation"]',
|
||||
content: Markup(_t("First, let's add a <b>Presentation</b>. It can be a .pdf or an image.")),
|
||||
position: 'bottom',
|
||||
}, {
|
||||
|
||||
@@ -29,7 +29,7 @@ var addVideoToSection = function (sectionName, saveAsDraft) {
|
||||
trigger: 'div.o_wslides_slide_list_category_header:contains("' + sectionName + '") a:contains("Add Content")',
|
||||
}, {
|
||||
content: 'eLearning: click on video',
|
||||
trigger: 'a[data-slide-type=video]',
|
||||
trigger: 'a[data-slide-category=video]',
|
||||
}, {
|
||||
content: 'eLearning: fill video link',
|
||||
trigger: 'input[name=url]',
|
||||
@@ -63,7 +63,7 @@ var addWebPageToSection = function (sectionName, pageName) {
|
||||
trigger: 'div.o_wslides_slide_list_category_header:contains("' + sectionName + '") a:contains("Add Content")',
|
||||
}, {
|
||||
content: 'eLearning: click on webpage',
|
||||
trigger: 'a[data-slide-type=webpage]',
|
||||
trigger: 'a[data-slide-category=webpage]',
|
||||
}, {
|
||||
content: 'eLearning: fill webpage title',
|
||||
trigger: 'input[name=name]',
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="website.slides.fullscreen.content">
|
||||
<t t-if="_.contains(['document', 'presentation'], widget.get('slide').type)">
|
||||
<t t-if="_.contains(['document', 'presentation'], widget.get('slide').category)">
|
||||
<div class="embed-responsive h-100">
|
||||
<iframe t-att-src="widget.get('slide').embedUrl" class="o_wslides_iframe_viewer" allowFullScreen="true" frameborder="0"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="widget.get('slide').type === 'infographic'">
|
||||
<t t-if="widget.get('slide').category === 'infographic'">
|
||||
<div class="o_wslides_fs_player w-100 h-100 overflow-auto d-flex align-items-start justify-content-center">
|
||||
<img t-att-src="'/web/image/slide.slide/'+ widget.get('slide').id +'/image_1024'" class="img-fluid position-relative m-auto" alt="Slide image"/>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</form>
|
||||
</div>
|
||||
<div t-if="widget.session.is_website_user" class="alert alert-info d-inline-block">
|
||||
<p class="mb-0">Please <a t-attf-href="/web?redirect=#{window.location.href}" class="font-weight-bold"> login </a> to share this <t t-esc="widget.slide.type"/> by email.</p>
|
||||
<p class="mb-0">Please <a t-attf-href="/web?redirect=#{window.location.href}" class="font-weight-bold"> login </a> to share this <t t-esc="widget.slide.category"/> by email.</p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -10,17 +10,17 @@
|
||||
</t>
|
||||
|
||||
<!--
|
||||
Slide Type Selection template
|
||||
Slide Category Selection template
|
||||
-->
|
||||
<t t-name="website.slide.upload.modal.select">
|
||||
<div class="row p-1 mt-4 mb-2">
|
||||
<div t-foreach="widget.slide_type_data" t-as="slide_type" class="col-6 col-md-3">
|
||||
<t t-set="type_data" t-value="widget.slide_type_data[slide_type]"/>
|
||||
<div t-foreach="widget.slide_category_data" t-as="slide_category" class="col-6 col-md-3">
|
||||
<t t-set="category_data" t-value="widget.slide_category_data[slide_category]"/>
|
||||
|
||||
<a href="#" t-att-data-slide-type="slide_type"
|
||||
class="content-type d-flex flex-column align-items-center mb-4 o_wslides_select_type btn rounded border text-600 p-3">
|
||||
<i t-attf-class="fa #{type_data['icon']} mb-2 fa-3x"/>
|
||||
<t t-esc="type_data['label']"/>
|
||||
<a href="#" t-att-data-slide-category="slide_category"
|
||||
class="content-type d-flex flex-column align-items-center mb-4 o_wslides_select_category btn rounded border text-600 p-3">
|
||||
<i t-attf-class="fa #{category_data['icon']} mb-2 fa-3x"/>
|
||||
<t t-esc="category_data['label']"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +55,7 @@
|
||||
</t>
|
||||
|
||||
<!--
|
||||
Slide Type common form part template
|
||||
Slide Category common form part template
|
||||
-->
|
||||
<t t-name="website.slide.upload.modal.common">
|
||||
<div class="form-group">
|
||||
@@ -82,7 +82,7 @@
|
||||
</t>
|
||||
|
||||
<!--
|
||||
Slide Type templates
|
||||
Slide Category templates
|
||||
-->
|
||||
<t t-name="website.slide.upload.modal.presentation">
|
||||
<div>
|
||||
|
||||
@@ -55,7 +55,7 @@ class SlidesCase(common.TransactionCase):
|
||||
cls.slide = cls.env['slide.slide'].with_user(cls.user_officer).create({
|
||||
'name': 'How To Cook Humans',
|
||||
'channel_id': cls.channel.id,
|
||||
'slide_type': 'presentation',
|
||||
'slide_category': 'presentation',
|
||||
'is_published': True,
|
||||
'completion_time': 2.0,
|
||||
'sequence': 1,
|
||||
@@ -70,7 +70,7 @@ class SlidesCase(common.TransactionCase):
|
||||
cls.slide_2 = cls.env['slide.slide'].with_user(cls.user_officer).create({
|
||||
'name': 'How To Cook For Humans',
|
||||
'channel_id': cls.channel.id,
|
||||
'slide_type': 'presentation',
|
||||
'slide_category': 'presentation',
|
||||
'is_published': True,
|
||||
'completion_time': 3.0,
|
||||
'sequence': 3,
|
||||
@@ -78,7 +78,7 @@ class SlidesCase(common.TransactionCase):
|
||||
cls.slide_3 = cls.env['slide.slide'].with_user(cls.user_officer).create({
|
||||
'name': 'How To Cook Humans For Humans',
|
||||
'channel_id': cls.channel.id,
|
||||
'slide_type': 'document',
|
||||
'slide_category': 'document',
|
||||
'is_published': True,
|
||||
'completion_time': 1.5,
|
||||
'sequence': 4,
|
||||
|
||||
@@ -28,14 +28,14 @@ class TestKarmaGain(common.SlidesCase):
|
||||
self.slide_2_0 = self.env['slide.slide'].with_user(self.user_officer).create({
|
||||
'name': 'How to travel through space and time',
|
||||
'channel_id': self.channel_2.id,
|
||||
'slide_type': 'presentation',
|
||||
'slide_category': 'presentation',
|
||||
'is_published': True,
|
||||
'completion_time': 2.0,
|
||||
})
|
||||
self.slide_2_1 = self.env['slide.slide'].with_user(self.user_officer).create({
|
||||
'name': 'How to duplicate yourself',
|
||||
'channel_id': self.channel_2.id,
|
||||
'slide_type': 'presentation',
|
||||
'slide_category': 'presentation',
|
||||
'is_published': True,
|
||||
'completion_time': 2.0,
|
||||
})
|
||||
|
||||
@@ -39,12 +39,12 @@ class TestChannelStatistics(common.SlidesCase):
|
||||
@mute_logger('odoo.models')
|
||||
def test_channel_statistics(self):
|
||||
channel_publisher = self.channel.with_user(self.user_officer)
|
||||
# slide type computation
|
||||
# slide category computation
|
||||
self.assertEqual(channel_publisher.total_slides, len(channel_publisher.slide_content_ids))
|
||||
self.assertEqual(channel_publisher.nbr_infographic, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_type == 'infographic')))
|
||||
self.assertEqual(channel_publisher.nbr_presentation, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_type == 'presentation')))
|
||||
self.assertEqual(channel_publisher.nbr_document, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_type == 'document')))
|
||||
self.assertEqual(channel_publisher.nbr_video, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_type == 'video')))
|
||||
self.assertEqual(channel_publisher.nbr_infographic, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'infographic')))
|
||||
self.assertEqual(channel_publisher.nbr_presentation, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'presentation')))
|
||||
self.assertEqual(channel_publisher.nbr_document, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'document')))
|
||||
self.assertEqual(channel_publisher.nbr_video, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'video')))
|
||||
# slide statistics computation
|
||||
self.assertEqual(float_compare(channel_publisher.total_time, sum(s.completion_time for s in channel_publisher.slide_content_ids), 3), 0)
|
||||
# members computation
|
||||
@@ -156,14 +156,14 @@ class TestSlideStatistics(common.SlidesCase):
|
||||
self.assertEqual(slide_emp.total_views, 5)
|
||||
|
||||
@users('user_officer')
|
||||
def test_slide_statistics_types(self):
|
||||
def test_slide_statistics_categories(self):
|
||||
category = self.category.with_user(self.env.user)
|
||||
self.assertEqual(
|
||||
category.nbr_presentation,
|
||||
len(category.channel_id.slide_ids.filtered(lambda s: s.category_id == category and s.slide_type == 'presentation')))
|
||||
len(category.channel_id.slide_ids.filtered(lambda s: s.category_id == category and s.slide_category == 'presentation')))
|
||||
self.assertEqual(
|
||||
category.nbr_document,
|
||||
len(category.channel_id.slide_ids.filtered(lambda s: s.category_id == category and s.slide_type == 'document')))
|
||||
len(category.channel_id.slide_ids.filtered(lambda s: s.category_id == category and s.slide_category == 'document')))
|
||||
|
||||
self.assertEqual(self.channel.total_slides, 3, 'The channel should contain 3 slides')
|
||||
self.assertEqual(category.total_slides, 2, 'The first category should contain 2 slides')
|
||||
|
||||
@@ -33,32 +33,32 @@ class TestUICommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal):
|
||||
(0, 0, {
|
||||
'name': 'Gardening: The Know-How',
|
||||
'sequence': 1,
|
||||
'datas': pdf_content,
|
||||
'slide_type': 'presentation',
|
||||
'binary_content': pdf_content,
|
||||
'slide_category': 'presentation',
|
||||
'is_published': True,
|
||||
'is_preview': True,
|
||||
}), (0, 0, {
|
||||
'name': 'Home Gardening',
|
||||
'sequence': 2,
|
||||
'image_1920': img_content,
|
||||
'slide_type': 'infographic',
|
||||
'slide_category': 'infographic',
|
||||
'is_published': True,
|
||||
}), (0, 0, {
|
||||
'name': 'Mighty Carrots',
|
||||
'sequence': 3,
|
||||
'image_1920': img_content,
|
||||
'slide_type': 'infographic',
|
||||
'slide_category': 'infographic',
|
||||
'is_published': True,
|
||||
}), (0, 0, {
|
||||
'name': 'How to Grow and Harvest The Best Strawberries | Basics',
|
||||
'sequence': 4,
|
||||
'datas': pdf_content,
|
||||
'slide_type': 'document',
|
||||
'binary_content': pdf_content,
|
||||
'slide_category': 'document',
|
||||
'is_published': True,
|
||||
}), (0, 0, {
|
||||
'name': 'Test your knowledge',
|
||||
'sequence': 5,
|
||||
'slide_type': 'quiz',
|
||||
'slide_category': 'quiz',
|
||||
'is_published': True,
|
||||
'question_ids': [
|
||||
(0, 0, {
|
||||
|
||||
@@ -77,9 +77,9 @@
|
||||
<tree decoration-bf="is_category" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="slide_type" attrs="{'invisible': [('slide_type', '=', 'category')]}"/>
|
||||
<field name="completion_time" attrs="{'invisible': [('slide_type', '=', 'category')]}" string="Duration" widget="float_time"/>
|
||||
<field name="total_views" attrs="{'invisible': [('slide_type', '=', 'category')]}"/>
|
||||
<field name="slide_category" attrs="{'invisible': [('slide_category', '=', 'category')]}"/>
|
||||
<field name="completion_time" attrs="{'invisible': [('slide_category', '=', 'category')]}" string="Duration" widget="float_time"/>
|
||||
<field name="total_views" attrs="{'invisible': [('slide_category', '=', 'category')]}"/>
|
||||
<field name="is_preview" string="Preview"/>
|
||||
<field name="is_published" string="Published"/>
|
||||
<field name="is_category" invisible="1"/>
|
||||
|
||||
@@ -116,14 +116,14 @@
|
||||
<group name="lesson_details">
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type" string="Content Type"/>
|
||||
<field name="slide_category" string="Content Type"/>
|
||||
<field name="url" attrs="{
|
||||
'required': [('slide_type', 'in', ('video'))],
|
||||
'invisible': [('slide_type', 'not in', ('video'))]}" />
|
||||
'required': [('slide_category', 'in', ('video'))],
|
||||
'invisible': [('slide_category', 'not in', ('video'))]}" />
|
||||
<field name="document_id" invisible="1"/>
|
||||
<field name="mime_type" force_save="1" readonly="1" groups="base.group_no_one"/>
|
||||
<field name="datas" string="Attachment"
|
||||
attrs="{'invisible': [('slide_type', 'not in', ('document', 'presentation'))]}"/>
|
||||
<field name="binary_content" string="Attachment"
|
||||
attrs="{'invisible': [('slide_category', 'not in', ('document', 'presentation'))]}"/>
|
||||
</group>
|
||||
<group name="related_details">
|
||||
<field name="user_id" string="Responsible" widget="many2one_avatar"/>
|
||||
@@ -133,7 +133,7 @@
|
||||
<span> hours</span>
|
||||
</div>
|
||||
<field name="is_preview"/>
|
||||
<field name="slide_resource_downloadable" attrs="{'invisible': [('slide_type', 'not in', ['presentation', 'document'])]}"/>
|
||||
<field name="slide_resource_downloadable" attrs="{'invisible': [('slide_category', 'not in', ['presentation', 'document'])]}"/>
|
||||
<field name="date_published" string="Published Date" attrs="{'invisible': [('date_published', '=', False)]}" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
@@ -211,7 +211,7 @@
|
||||
sample="1">
|
||||
<field name="id"/>
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type"/>
|
||||
<field name="slide_category"/>
|
||||
<field name="user_id"/>
|
||||
<field name="image_128"/>
|
||||
<templates>
|
||||
@@ -242,20 +242,20 @@
|
||||
</div>
|
||||
<div class="o_kanban_record_bottom mt-auto d-flex justify-content-between align-items-end">
|
||||
<span>
|
||||
<t t-if="record.slide_type.raw_value == 'infographic'">
|
||||
<t t-if="record.slide_category.raw_value == 'infographic'">
|
||||
<i class="fa fa-file-image-o mr-2" aria-label="Infographic" role="img" title="Infographic"/>
|
||||
</t>
|
||||
<t t-elif="record.slide_type.raw_value == 'webpage'">
|
||||
<t t-elif="record.slide_category.raw_value == 'webpage'">
|
||||
<i class="fa fa-file-code-o mr-2" aria-label="Webpage" role="img" title="Webpage"/>
|
||||
</t>
|
||||
<t t-elif="record.slide_type.raw_value == 'video'">
|
||||
<t t-elif="record.slide_category.raw_value == 'video'">
|
||||
<i class="fa fa-file-video-o mr-2" aria-label="Video" role="img" title="Video"/>
|
||||
</t>
|
||||
<t t-elif="record.slide_type.raw_value == 'quiz'">
|
||||
<t t-elif="record.slide_category.raw_value == 'quiz'">
|
||||
<i class="fa fa-flag mr-2" aria-label="Quiz" role="img" title="Quiz"/>
|
||||
</t>
|
||||
<t t-else=""><i class="fa fa-file-pdf-o mr-2" aria-label="Document" role="img" title="Document"/></t>
|
||||
<field name="slide_type"/>
|
||||
<field name="slide_category"/>
|
||||
</span>
|
||||
<span>
|
||||
<i class="fa fa-clock-o mr-2" aria-label="Duration" role="img" title="Duration"/><field name="completion_time" widget="float_time"/>
|
||||
@@ -324,7 +324,7 @@
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Course" name="groupby_channel" domain="[]" context="{'group_by': 'channel_id'}"/>
|
||||
<filter string="Category" name="groupby_category" domain="[]" context="{'group_by': 'category_id'}"/>
|
||||
<filter string="Type" name="groupby_type" domain="[]" context="{'group_by': 'slide_type'}"/>
|
||||
<filter string="Type" name="groupby_type" domain="[]" context="{'group_by': 'slide_category'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -336,7 +336,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Graph of Contents" stacked="0" sample="1">
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type"/>
|
||||
<field name="slide_category"/>
|
||||
<field name="total_views" type="measure"/>
|
||||
<field name="quiz_first_attempt_reward" invisible="1"/>
|
||||
<field name="quiz_second_attempt_reward" invisible="1"/>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<a href="/slides">Courses</a>
|
||||
</li>
|
||||
<t t-set="breadcrumb_class" t-value="'breadcrumb-item %s' % ('active' if not slide else '')" />
|
||||
<li t-att-class="'breadcrumb-item %s' % ('active' if not search_category and not search_tag and not search_slide_type and not slide else '')">
|
||||
<li t-att-class="'breadcrumb-item %s' % ('active' if not search_category and not search_tag and not search_slide_category and not slide else '')">
|
||||
<a t-att-href="'/slides/%s' % slug(channel)"><span t-esc="channel.name"/></a>
|
||||
</li>
|
||||
<li t-att-class="breadcrumb_class" t-att-aria-current="'page' and search_category" t-if="search_category">
|
||||
@@ -25,8 +25,8 @@
|
||||
<li t-att-class="breadcrumb_class" t-att-aria-current="'page' and search_uncategorized" t-if="search_uncategorized">
|
||||
<a t-att-href="'/slides/%s?search_uncategorized=1' % (slug(channel))">Uncategorized</a>
|
||||
</li>
|
||||
<li t-att-class="breadcrumb_class" t-att-aria-current="'page' and search_slide_type" t-if="search_slide_type">
|
||||
<a t-att-href="'/slides/%s?slide_type=%s' % (slug(channel), search_slide_type)"><span t-esc="slide_types[search_slide_type]"/></a>
|
||||
<li t-att-class="breadcrumb_class" t-att-aria-current="'page' and search_slide_category" t-if="search_slide_category">
|
||||
<a t-att-href="'/slides/%s?slide_category=%s' % (slug(channel), search_slide_category)"><span t-esc="slide_categories[search_slide_category]"/></a>
|
||||
</li>
|
||||
<li t-if="slide" class="breadcrumb-item active">
|
||||
<a t-att-href="'/slides/slide/%s' % slug(slide)"><span t-esc="slide.name"/></a>
|
||||
@@ -58,7 +58,7 @@
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/slides">Home</a>
|
||||
<t t-set="dropdown_class" t-value="'dropdown-item %s' % ('active' if not slide else '')"/>
|
||||
<a t-att-class="'dropdown-item %s' % ('active' if not search_category and not search_tag and not search_slide_type else '')" t-att-href="'/slides/%s' % slug(channel)">
|
||||
<a t-att-class="'dropdown-item %s' % ('active' if not search_category and not search_tag and not search_slide_category else '')" t-att-href="'/slides/%s' % slug(channel)">
|
||||
└<span class="ml-1" t-esc="channel.name"/>
|
||||
</a>
|
||||
<a t-att-class="dropdown_class" t-att-aria-current="'page' and search_category" t-if="search_category" t-att-href="'/slides/%s/category/%s' % (slug(channel), slug(search_category))">
|
||||
@@ -70,8 +70,8 @@
|
||||
<a t-att-class="dropdown_class" t-att-aria-current="'page' and search_uncategorized" t-if="search_uncategorized" t-att-href="'/slides/%s?search_uncategorized=1' % (slug(channel))">
|
||||
└<span class="ml-1">Uncategorized</span>
|
||||
</a>
|
||||
<a t-att-class="dropdown_class" t-att-aria-current="'page' and search_slide_type" t-if="search_slide_type" t-att-href="'/slides/%s?slide_type=%s' % (slug(channel), search_slide_type)">
|
||||
└<span class="ml-1" t-esc="slide_types[search_slide_type]"/>
|
||||
<a t-att-class="dropdown_class" t-att-aria-current="'page' and search_slide_category" t-if="search_slide_category" t-att-href="'/slides/%s?slide_category=%s' % (slug(channel), search_slide_category)">
|
||||
└<span class="ml-1" t-esc="slide_categories[search_slide_category]"/>
|
||||
</a>
|
||||
<a t-if="slide" class="dropdown-item active" t-att-href="'/slides/slide/%s' % (slug(slide))">
|
||||
└<span class="ml-1" t-esc="slide.name"/>
|
||||
@@ -526,7 +526,7 @@
|
||||
<i t-else="" class="check-done text-success fa fa-check-circle px-2"></i>
|
||||
</t>
|
||||
<span t-if="channel.can_publish" class="d-none d-md-flex">
|
||||
<a t-if="slide.slide_type == 'webpage'" class="px-2 o_text_link text-primary" target="_blank" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><span class="fa fa-pencil"/></a>
|
||||
<a t-if="slide.slide_category == 'webpage'" class="px-2 o_text_link text-primary" target="_blank" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><span class="fa fa-pencil"/></a>
|
||||
<a t-else="" class="px-2 o_text_link text-primary" target="_blank" t-attf-href="/web#id=#{slide.id}&action=#{slide_action}&model=slide.slide&view_type=form" title="Edit in backend"><span class="fa fa-pencil"/></a>
|
||||
<a href="#" t-att-data-slide-id="slide.id" class="o_text_link text-danger px-2 o_wslides_js_slide_archive"><span class="fa fa-trash"/></a>
|
||||
</span>
|
||||
@@ -537,7 +537,7 @@
|
||||
<!-- ======= Documentation Course content: cards / categories======= -->
|
||||
<template id="course_promoted_slide" name="Documentation Course content: promoted slide">
|
||||
<div class="o_wslides_promoted_slide">
|
||||
<div t-if="not search and not search_slide_type and slide_promoted" class="container py-1 mb-2">
|
||||
<div t-if="not search and not search_slide_category 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')"/>
|
||||
|
||||
@@ -574,7 +574,7 @@
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-transparent col">
|
||||
<a class="navbar-brand d-lg-none" href="#">Filter & order</a>
|
||||
|
||||
<div class="form-inline ml-auto d-lg-none" t-if="search_slide_type or search">
|
||||
<div class="form-inline ml-auto d-lg-none" t-if="search_slide_category or search">
|
||||
<a t-att-href="'/slides/%s' % (slug(channel))" class="btn btn-info mr-3">
|
||||
<i class="fa fa-eraser mr-1"/>Clear filters
|
||||
</a>
|
||||
@@ -588,23 +588,23 @@
|
||||
<div class="col-12">
|
||||
<ul class="navbar-nav mr-lg-auto align-items-lg-center">
|
||||
|
||||
<t t-set="slide_type_keys" t-value="slide_types.keys()"/>
|
||||
<t t-foreach="slide_type_keys" t-as="slide_type_key">
|
||||
<t t-set="slide_category_keys" t-value="slide_categories.keys()"/>
|
||||
<t t-foreach="slide_category_keys" t-as="slide_category_key">
|
||||
<t t-if="search_category">
|
||||
<li t-if="search_category['nbr_%s' % slide_type_key] > 0" class="nav-item">
|
||||
<a t-att-href="'/slides/%s/category/%s?%s' % (slug(channel), slug(search_category), keep_query(slide_type=slide_type_key))"
|
||||
t-att-class="'nav-link d-flex align-items-center justify-content-between mr-1 %s' % ('active' if search_slide_type == slide_type_key else '')">
|
||||
<t t-esc="slide_types[slide_type_key]"/>
|
||||
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_type == slide_type_key else 'bg-400'}" t-esc="search_category['nbr_%s' % slide_type_key]"/>
|
||||
<li t-if="search_category['nbr_%s' % slide_category_key] > 0" class="nav-item">
|
||||
<a t-att-href="'/slides/%s/category/%s?%s' % (slug(channel), slug(search_category), keep_query(slide_category=slide_category_key))"
|
||||
t-att-class="'nav-link d-flex align-items-center justify-content-between mr-1 %s' % ('active' if search_slide_category == slide_category_key else '')">
|
||||
<t t-esc="slide_categories[slide_category_key]"/>
|
||||
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_category == slide_category_key else 'bg-400'}" t-esc="search_category['nbr_%s' % slide_category_key]"/>
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<li t-if="channel['nbr_%s' % slide_type_key] > 0" class="nav-item">
|
||||
<a t-att-href="'/slides/%s?%s' % (slug(channel), keep_query(slide_type=slide_type_key))"
|
||||
t-att-class="'nav-link d-flex align-items-center justify-content-between mr-1 %s' % ('active' if search_slide_type == slide_type_key else '')">
|
||||
<t t-esc="slide_types[slide_type_key]"/>
|
||||
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_type == slide_type_key else 'bg-400'}" t-esc="channel['nbr_%s' % slide_type_key]"/>
|
||||
<li t-if="channel['nbr_%s' % slide_category_key] > 0" class="nav-item">
|
||||
<a t-att-href="'/slides/%s?%s' % (slug(channel), keep_query(slide_category=slide_category_key))"
|
||||
t-att-class="'nav-link d-flex align-items-center justify-content-between mr-1 %s' % ('active' if search_slide_category == slide_category_key else '')">
|
||||
<t t-esc="slide_categories[slide_category_key]"/>
|
||||
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_category == slide_category_key else 'bg-400'}" t-esc="channel['nbr_%s' % slide_category_key]"/>
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
@@ -626,18 +626,18 @@
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="slidesChannelDropdownSort" role="menu">
|
||||
<h6 class="dropdown-header">Sort by</h6>
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_type', sorting='latest'))"
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_category', sorting='latest'))"
|
||||
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'latest' else '')">Newest</a>
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_type', sorting='most_voted'))"
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_category', sorting='most_voted'))"
|
||||
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_voted' else '')">Most Voted</a>
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_type', sorting='most_viewed'))"
|
||||
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('slide_category', sorting='most_viewed'))"
|
||||
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_viewed' else '')">Most Viewed</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="form-inline mr-3 d-none d-lg-inline-block">
|
||||
<a t-if="search_slide_type or search" t-att-href="'/slides/%s' % (slug(channel))" class="btn btn-sm btn-info ml-1">
|
||||
<a t-if="search_slide_category or search" t-att-href="'/slides/%s' % (slug(channel))" class="btn btn-sm btn-info ml-1">
|
||||
<i class="fa fa-eraser mr-1"/>Clear filters
|
||||
</a>
|
||||
</div>
|
||||
@@ -805,13 +805,13 @@
|
||||
|
||||
<template id="slide_icon">
|
||||
<t t-set="icon_class" t-value="icon_class if icon_class else 'mr-2 text-muted'"/>
|
||||
<i t-if="slide.slide_type == 'document'" t-att-class="'fa fa-file-pdf-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'presentation'" t-att-class="'fa fa-file-pdf-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'infographic'" t-att-class="'fa fa-file-picture-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'video'" t-att-class="'fa fa-play-circle %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'link'" t-att-class="'fa fa-file-code-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'webpage'" t-att-class="'fa fa-file-text %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_type == 'quiz'" t-att-class="'fa fa-question-circle %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'document'" t-att-class="'fa fa-file-pdf-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'presentation'" t-att-class="'fa fa-file-pdf-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'infographic'" t-att-class="'fa fa-file-picture-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'video'" t-att-class="'fa fa-play-circle %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'link'" t-att-class="'fa fa-file-code-o %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'webpage'" t-att-class="'fa fa-file-text %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'quiz'" t-att-class="'fa fa-question-circle %s' % icon_class"></i>
|
||||
</template>
|
||||
|
||||
</data></odoo>
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
<section class="s_banner bg-900" style="background-image: url("/website_slides/static/src/img/banner_default_all.svg"); background-size: cover; background-position: 80% 20%" data-snippet="s_banner">
|
||||
<div class="container py-5">
|
||||
<h1 t-if="search_my" class="display-3 mb-0">My Courses</h1>
|
||||
<h1 t-elif="search_slide_type=='certification'" class="display-3 mb-0">Certifications</h1>
|
||||
<h1 t-elif="search_slide_category=='certification'" class="display-3 mb-0">Certifications</h1>
|
||||
<h1 t-else="" class="display-3 mb-0">All Courses</h1>
|
||||
</div>
|
||||
</section>
|
||||
@@ -184,7 +184,7 @@
|
||||
<a class="nav-link nav-item px-3" href="/slides"><i class="fa fa-chevron-left"/></a>
|
||||
</div>
|
||||
<!-- Clear filtering (mobile)-->
|
||||
<div class="form-inline text-nowrap ml-auto d-md-none" t-if="search_slide_type or search_my or search_tags">
|
||||
<div class="form-inline text-nowrap ml-auto d-md-none" t-if="search_slide_category or search_my or search_tags">
|
||||
<a href="/slides/all" class="btn btn-info mr-2" role="button" title="Clear filters">
|
||||
<i class="fa fa-eraser"/> Clear filters
|
||||
</a>
|
||||
@@ -199,7 +199,7 @@
|
||||
<t t-set="placeholder">Search courses</t>
|
||||
<t t-set="search" t-value="original_search or search_term"/>
|
||||
<input t-if="search_my" type="hidden" name="my" t-att-value="1"/>
|
||||
<input t-if="search_slide_type" type="hidden" name="slide_type" t-att-value="search_slide_type" />
|
||||
<input t-if="search_slide_category" type="hidden" name="slide_category" t-att-value="search_slide_category" />
|
||||
</t>
|
||||
<button class="navbar-toggler px-1" type="button"
|
||||
data-toggle="collapse" data-target="#navbarTagGroups"
|
||||
@@ -221,7 +221,7 @@
|
||||
<div class="dropdown-menu" t-att-id="'navToogleTagGroup%s' % tag_group.id">
|
||||
<t t-foreach="group_frontend_tags" t-as="tag">
|
||||
<a rel="nofollow" t-att-class="'dropdown-item post_link %s' % ('active' if tag in search_tags else '')"
|
||||
t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_type=search_slide_type)"
|
||||
t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_category=search_slide_category)"
|
||||
t-esc="tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
@@ -229,7 +229,7 @@
|
||||
</t>
|
||||
</ul>
|
||||
<!-- Clear filtering (desktop)-->
|
||||
<div class="form-inline ml-auto d-none d-md-flex" t-if="search_slide_type or search_my or search_tags">
|
||||
<div class="form-inline ml-auto d-none d-md-flex" t-if="search_slide_category or search_my or search_tags">
|
||||
<a href="/slides/all" class="btn btn-info text-nowrap mr-2" role="button" title="Clear filters">
|
||||
<i class="fa fa-eraser"/> Clear filters
|
||||
</a>
|
||||
@@ -244,7 +244,7 @@
|
||||
<t t-set="placeholder">Search courses</t>
|
||||
<t t-set="search" t-value="original_search or search_term"/>
|
||||
<input t-if="search_my" type="hidden" name="my" t-att-value="1"/>
|
||||
<input t-if="search_slide_type" type="hidden" name="slide_type" t-att-value="search_slide_type" />
|
||||
<input t-if="search_slide_category" type="hidden" name="slide_category" t-att-value="search_slide_category" />
|
||||
</t>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -267,19 +267,19 @@
|
||||
<span class="align-items-baseline border d-inline-flex pl-2 rounded mb-2">
|
||||
<i class="fa fa-tag mr-2 text-muted"/>
|
||||
<t t-esc="search_term"/>
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids), my=search_my, slide_type=search_slide_type)" class="btn border-0 py-1 post_link" t-att-rel="search_tags and 'nofollow'">×</a>
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids), my=search_my, slide_category=search_slide_category)" class="btn border-0 py-1 post_link" t-att-rel="search_tags and 'nofollow'">×</a>
|
||||
</span>
|
||||
</t>
|
||||
<t t-foreach="search_tags" t-as="tag">
|
||||
<span class="align-items-baseline border d-inline-flex pl-2 rounded mb-2">
|
||||
<i class="fa fa-tag mr-2 text-muted"/>
|
||||
<t t-esc="tag.display_name"/>
|
||||
<a t-att-href='slide_query_url(tag=slugify_tags(search_tags.ids, tag.id), my=search_my, search=search_term, slide_type=search_slide_type)' class="btn border-0 py-1 post_link" t-att-rel="search_tags and 'nofollow'">×</a>
|
||||
<a t-att-href='slide_query_url(tag=slugify_tags(search_tags.ids, tag.id), my=search_my, search=search_term, slide_category=search_slide_category)' class="btn border-0 py-1 post_link" t-att-rel="search_tags and 'nofollow'">×</a>
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
<div class="container o_wslides_home_main pb-5">
|
||||
<div t-if="not channels and not search_term and not search_slide_type and not search_my and not search_tags">
|
||||
<div t-if="not channels and not search_term and not search_slide_category and not search_my and not search_tags">
|
||||
<p class="h2">No Course created yet.</p>
|
||||
<p groups="website_slides.group_website_slides_officer">Click on "New" in the top-right corner to write your first course.</p>
|
||||
</div>
|
||||
@@ -333,10 +333,10 @@
|
||||
<div t-if="channel_frontend_tags" class="mt-2 pt-1 o_wslides_desc_truncate_2">
|
||||
<t t-foreach="channel_frontend_tags" t-as="tag">
|
||||
<t t-if="search_tags">
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_type=search_slide_type)" t-attf-class="badge post_link #{'badge-primary' if tag in search_tags else 'o_wslides_channel_tag o_tag_color_0'}" t-att-rel="search_tags and 'nofollow'" t-esc="tag.name"/>
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_category=search_slide_category)" t-attf-class="badge post_link #{'badge-primary' if tag in search_tags else 'o_wslides_channel_tag o_tag_color_0'}" t-att-rel="search_tags and 'nofollow'" t-esc="tag.name"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_type=search_slide_type)" t-attf-class="badge post_link o_wslides_channel_tag #{'o_tag_color_'+str(tag.color)}" t-att-rel="search_tags and 'nofollow'" t-esc="tag.name"/>
|
||||
<a t-att-href="slide_query_url(tag=slugify_tags(search_tags.ids, toggle_tag_id=tag.id), my=search_my, search=search_term, slide_category=search_slide_category)" t-attf-class="badge post_link o_wslides_channel_tag #{'o_tag_color_'+str(tag.color)}" t-att-rel="search_tags and 'nofollow'" t-esc="tag.name"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
@@ -187,10 +187,10 @@
|
||||
</li>
|
||||
</div>
|
||||
<li class="pl-4">
|
||||
<a t-if="can_access and aside_slide.question_ids and aside_slide.slide_type != 'quiz'" t-att-href="'/slides/slide/%s#lessonQuiz' % (slug(aside_slide))" class="o_wslides_lesson_aside_list_link text-decoration-none small text-600">
|
||||
<a t-if="can_access and aside_slide.question_ids and aside_slide.slide_category != 'quiz'" t-att-href="'/slides/slide/%s#lessonQuiz' % (slug(aside_slide))" class="o_wslides_lesson_aside_list_link text-decoration-none small text-600">
|
||||
<i class="fa fa-flag text-warning"/> Quiz
|
||||
</a>
|
||||
<span t-elif="not can_access and aside_slide.question_ids and aside_slide.slide_type != 'quiz'"
|
||||
<span t-elif="not can_access and aside_slide.question_ids and aside_slide.slide_category != 'quiz'"
|
||||
class="o_wslides_lesson_aside_list_link text-decoration-none small text-600 text-muted">
|
||||
<i class="fa fa-flag text-warning"/> Quiz
|
||||
</span>
|
||||
@@ -231,7 +231,7 @@
|
||||
t-att-href="'/slides/slide/%s' % (slug(previous_slide)) if previous_slide else '#'">
|
||||
<i class="fa fa-chevron-left mr-2"></i> <span class="d-none d-sm-inline-block">Prev</span>
|
||||
</a>
|
||||
<t t-set="allow_done_btn" t-value="slide.slide_type in ['infographic', 'presentation', 'document', 'webpage', 'video'] and not slide.question_ids and not channel_progress[slide.id].get('completed') and slide.channel_id.is_member"/>
|
||||
<t t-set="allow_done_btn" t-value="slide.slide_category in ['infographic', 'presentation', 'document', 'webpage', 'video'] and not slide.question_ids and not channel_progress[slide.id].get('completed') and slide.channel_id.is_member"/>
|
||||
<a t-att-class="'btn btn-primary border text-white %s' % ('disabled' if not allow_done_btn else '')"
|
||||
role="button" t-att-aria-disabled="'true' if not allow_done_btn else None"
|
||||
t-att-href="'/slides/slide/%s/set_completed?%s' % (slide.id, 'next_slide_id=%s' % (next_slide.id) if next_slide else '') if allow_done_btn else '#'">
|
||||
@@ -255,15 +255,15 @@
|
||||
</t>
|
||||
</div>
|
||||
<div class="o_wslides_lesson_content_type">
|
||||
<img t-if="slide.slide_type == 'infographic'"
|
||||
<img t-if="slide.slide_category == 'infographic'"
|
||||
t-att-src="website.image_url(slide, 'image_1024')" class="img-fluid" style="width:100%" t-att-alt="slide.name"/>
|
||||
<div t-if="slide.slide_type in ('presentation', 'document')" class="embed-responsive embed-responsive-4by3 embed-responsive-item mb8" style="height: 600px;">
|
||||
<div t-if="slide.slide_category in ('presentation', 'document')" class="embed-responsive embed-responsive-4by3 embed-responsive-item mb8" style="height: 600px;">
|
||||
<t t-out="slide.embed_code"/>
|
||||
</div>
|
||||
<div t-if="slide.slide_type == 'video' and slide.document_id" class="embed-responsive embed-responsive-16by9 embed-responsive-item mb8">
|
||||
<div t-if="slide.slide_category == 'video' and slide.document_id" class="embed-responsive embed-responsive-16by9 embed-responsive-item mb8">
|
||||
<t t-out="slide.embed_code"/>
|
||||
</div>
|
||||
<div t-if="slide.slide_type == 'webpage'" class="bg-white p-3">
|
||||
<div t-if="slide.slide_category == 'webpage'" class="bg-white p-3">
|
||||
<div t-field="slide.html_content"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -400,7 +400,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_wslides_js_quiz_container" t-att-data-slide-id="slide.id">
|
||||
<div class="row" t-if="slide.slide_type != 'certification'">
|
||||
<div class="row" t-if="slide.slide_category != 'certification'">
|
||||
<t t-if="slide.question_ids">
|
||||
<t t-call="website_slides.lesson_content_quiz"/>
|
||||
</t>
|
||||
@@ -444,7 +444,7 @@
|
||||
<div class="o_wslides_js_lesson_quiz col" id="lessonQuiz"
|
||||
t-att-data-id="slide.id"
|
||||
t-att-data-name="slide.name"
|
||||
t-att-data-slide-type="slide.slide_type"
|
||||
t-att-data-slide-category="slide.slide_category"
|
||||
t-att-data-is-member="slide.channel_id.is_member"
|
||||
t-att-data-completed="1 if slide_completed else 0"
|
||||
t-att-data-quiz-attempts-count="quiz_attempts_count"
|
||||
@@ -543,7 +543,7 @@
|
||||
</form>
|
||||
</div>
|
||||
<div t-if="is_public_user" class="alert alert-info d-inline-block">
|
||||
<p class="mb-0">Please <a t-attf-href="/web?redirect=#{request.httprequest.url}" class="font-weight-bold"> login </a> to share this <t t-esc="slide.slide_type"/> by email.</p>
|
||||
<p class="mb-0">Please <a t-attf-href="/web?redirect=#{request.httprequest.url}" class="font-weight-bold"> login </a> to share this <t t-esc="slide.slide_category"/> by email.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -557,7 +557,7 @@
|
||||
<t t-esc="slide.embed_code_external"/>
|
||||
</textarea>
|
||||
</div>
|
||||
<div t-if="slide.slide_type in ('presentation', 'document') and not embed_hide_starting_page" class="form-group d-flex">
|
||||
<div t-if="slide.slide_category in ('presentation', 'document') and not embed_hide_starting_page" class="form-group d-flex">
|
||||
<div class="form-text p-0 col-xs-5 col-sm-5 col-md-5 col-lg-5">Select page to start with</div>
|
||||
<div class="input-group col-xs-3 col-sm-2 col-md-2 col-lg-3">
|
||||
<input type="number" value="1" class="form-control"/>
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="slide.slide_type in ('presentation', 'document')">
|
||||
<t t-if="slide.slide_category in ('presentation', 'document')">
|
||||
<div id="PDFViewerLoader" class="oe_slides_loader mt-3 mx-2 w-100">
|
||||
<div class="toast show mx-auto">
|
||||
<div class="toast-header">
|
||||
@@ -84,12 +84,12 @@
|
||||
</div>
|
||||
<canvas id="PDFViewerCanvas" class="mx-auto" style="display: none;"></canvas>
|
||||
</t>
|
||||
<t t-if="slide.slide_type == 'infographic'">
|
||||
<t t-if="slide.slide_category == 'infographic'">
|
||||
<img t-att-src="website.image_url(slide, 'image_1024')" class="img-fluid" style="width: 100%" alt="Slide image"/>
|
||||
</t>
|
||||
</div>
|
||||
<!-- Fixed bottom navbar -->
|
||||
<div id="PDFViewerNav" class="pt-2 pb-2 bg-light text-white" role="navigation" t-if="slide.slide_type in ('presentation', 'document')">
|
||||
<div id="PDFViewerNav" class="pt-2 pb-2 bg-light text-white" role="navigation" t-if="slide.slide_category in ('presentation', 'document')">
|
||||
<div class="container-fluid oe_slides_panel_footer">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-3 d-flex align-items-center">
|
||||
@@ -111,7 +111,7 @@
|
||||
<span id="previous" class="mx-1 mx-sm-2" title="Previous slide" aria-label="Previous slide" role="button"><i class="fa fa-arrow-circle-left"/></span>
|
||||
<span id="next" class="mx-1 mx-sm-2" title="Next slide" aria-label="Next slide" role="button"><i class="fa fa-arrow-circle-right"/></span>
|
||||
<span id="last" class="mx-1 mx-sm-2" title="Last slide" aria-label="Last slide" role="button"><i class="fa fa-step-forward"/></span>
|
||||
<a t-if="slide.slide_resource_downloadable" id="download" t-attf-href="/web/content/slide.slide/#{slide.id}/datas?download=true"
|
||||
<a t-if="slide.slide_resource_downloadable" id="download" t-attf-href="/web/content/slide.slide/#{slide.id}/binary_content?download=true"
|
||||
class="ml-1 ml-sm-2" title="Download Content" aria-label="Download" role="button">
|
||||
<i class="fa fa-download" />
|
||||
</a>
|
||||
|
||||
@@ -109,12 +109,12 @@
|
||||
t-att-data-id="slide.id"
|
||||
t-att-data-can-access="can_access"
|
||||
t-att-data-name="slide.name"
|
||||
t-att-data-type="slide.slide_type"
|
||||
t-att-data-category="slide.slide_category"
|
||||
t-att-data-slug="slug(slide)"
|
||||
t-att-data-has-question="1 if slide.question_ids else 0"
|
||||
t-att-data-is-quiz="0"
|
||||
t-att-data-completed="1 if slide_completed else 0"
|
||||
t-att-data-embed-code="slide.embed_code if slide.slide_type in ['video', 'document', 'presentation', 'infographic'] else False"
|
||||
t-att-data-embed-code="slide.embed_code if slide.slide_category in ['video', 'document', 'presentation', 'infographic'] else False"
|
||||
t-att-data-is-member="is_member"
|
||||
t-att-data-session-answers="session_answers">
|
||||
<span class="ml-3">
|
||||
@@ -135,7 +135,7 @@
|
||||
<div class="o_wslides_fs_slide_name text-600" t-esc="slide.name"/>
|
||||
</div>
|
||||
</span>
|
||||
<ul class="list-unstyled w-100 pt-2 small" t-if="slide.slide_resource_ids or (slide.question_ids and not slide.slide_type =='quiz')" >
|
||||
<ul class="list-unstyled w-100 pt-2 small" t-if="slide.slide_resource_ids or (slide.question_ids and not slide.slide_category =='quiz')" >
|
||||
<t t-set="links" t-value="slide.slide_resource_ids.filtered(lambda res: res.resource_type == 'url')"/>
|
||||
<li t-if="links" t-foreach="links" t-as="link" class="pl-0 mb-1">
|
||||
<a t-if="can_access" class="o_wslides_fs_slide_link" t-att-href="link.link" target="_blank">
|
||||
@@ -159,11 +159,11 @@
|
||||
<t t-call="website_slides.join_course_link"/>
|
||||
</li>
|
||||
</div>
|
||||
<li class="o_wslides_fs_sidebar_list_item pl-0 mb-1" t-if="slide.question_ids and not slide.slide_type == 'quiz'"
|
||||
<li class="o_wslides_fs_sidebar_list_item pl-0 mb-1" t-if="slide.question_ids and not slide.slide_category == 'quiz'"
|
||||
t-att-data-id="slide.id"
|
||||
t-att-data-can-access="can_access"
|
||||
t-att-data-name="slide.name"
|
||||
t-att-data-type="slide.slide_type"
|
||||
t-att-data-category="slide.slide_category"
|
||||
t-att-data-slug="slug(slide)"
|
||||
t-att-data-has-question="1 if slide.question_ids else 0"
|
||||
t-att-data-is-quiz="1"
|
||||
|
||||
@@ -43,7 +43,7 @@ class WebsiteSlidesSurvey(WebsiteSlides):
|
||||
|
||||
@http.route(['/slides/add_slide'], type='json', auth='user', methods=['POST'], website=True)
|
||||
def create_slide(self, *args, **post):
|
||||
create_new_survey = post['slide_type'] == "certification" and post.get('survey') and not post['survey']['id']
|
||||
create_new_survey = post['slide_category'] == "certification" and post.get('survey') and not post['survey']['id']
|
||||
linked_survey_id = int(post.get('survey', {}).get('id') or 0)
|
||||
|
||||
if create_new_survey:
|
||||
@@ -87,7 +87,7 @@ class WebsiteSlidesSurvey(WebsiteSlides):
|
||||
# Utils
|
||||
# ---------------------------------------------------
|
||||
def _set_completed_slide(self, slide):
|
||||
if slide.slide_type == 'certification':
|
||||
if slide.slide_category == 'certification':
|
||||
raise werkzeug.exceptions.Forbidden(_("Certification slides are completed when the survey is succeeded."))
|
||||
return super(WebsiteSlidesSurvey, self)._set_completed_slide(slide)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<record id="website_slides.badge_data_certification_goal" model="gamification.goal.definition">
|
||||
<field name="domain">[
|
||||
('survey_scoring_success', '=', True),
|
||||
('slide_id.slide_type', '=', 'certification')
|
||||
('slide_id.slide_category', '=', 'certification')
|
||||
]</field>
|
||||
</record>
|
||||
</data></odoo>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<field name="name">Furniture Creation Certification</field>
|
||||
<field name="sequence">7</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_furniture.jpg"/>
|
||||
<field name="slide_type">certification</field>
|
||||
<field name="slide_category">certification</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
|
||||
<field name="category_id" ref="website_slides.slide_category_demo_5_0"/>
|
||||
<field name="survey_id" ref="website_slides_survey.furniture_certification"/>
|
||||
@@ -23,7 +23,7 @@
|
||||
<field name="name">DIY Furniture Certification</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="image_1920" type="base64" file="website_slides/static/src/img/slide_demo_furniture.jpg"/>
|
||||
<field name="slide_type">certification</field>
|
||||
<field name="slide_category">certification</field>
|
||||
<field name="channel_id" ref="website_slides.slide_channel_demo_6_furn3"/>
|
||||
<field name="category_id" eval="False"/>
|
||||
<field name="survey_id" ref="website_slides_survey.furniture_certification"/>
|
||||
|
||||
@@ -30,27 +30,27 @@ class SlidePartnerRelation(models.Model):
|
||||
class Slide(models.Model):
|
||||
_inherit = 'slide.slide'
|
||||
|
||||
slide_type = fields.Selection(selection_add=[
|
||||
slide_category = fields.Selection(selection_add=[
|
||||
('certification', 'Certification')
|
||||
], ondelete={'certification': 'set default'})
|
||||
survey_id = fields.Many2one('survey.survey', 'Certification')
|
||||
nbr_certification = fields.Integer("Number of Certifications", compute='_compute_slides_statistics', store=True)
|
||||
|
||||
_sql_constraints = [
|
||||
('check_survey_id', "CHECK(slide_type != 'certification' OR survey_id IS NOT NULL)", "A slide of type 'certification' requires a certification."),
|
||||
('check_certification_preview', "CHECK(slide_type != 'certification' OR is_preview = False)", "A slide of type certification cannot be previewed."),
|
||||
('check_survey_id', "CHECK(slide_category != 'certification' OR survey_id IS NOT NULL)", "A slide of type 'certification' requires a certification."),
|
||||
('check_certification_preview', "CHECK(slide_category != 'certification' OR is_preview = False)", "A slide of type certification cannot be previewed."),
|
||||
]
|
||||
|
||||
@api.onchange('survey_id')
|
||||
def _on_change_survey_id(self):
|
||||
if self.survey_id:
|
||||
self.slide_type = 'certification'
|
||||
self.slide_category = 'certification'
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
rec = super(Slide, self).create(values)
|
||||
if rec.survey_id:
|
||||
rec.slide_type = 'certification'
|
||||
rec.slide_category = 'certification'
|
||||
if 'survey_id' in values:
|
||||
rec._ensure_challenge_category()
|
||||
return rec
|
||||
@@ -90,7 +90,7 @@ class Slide(models.Model):
|
||||
course can be enrolled multiple times.
|
||||
"""
|
||||
certification_urls = {}
|
||||
for slide in self.filtered(lambda slide: slide.slide_type == 'certification' and slide.survey_id):
|
||||
for slide in self.filtered(lambda slide: slide.slide_category == 'certification' and slide.survey_id):
|
||||
if slide.channel_id.is_member:
|
||||
user_membership_id_sudo = slide.user_membership_id.sudo()
|
||||
if user_membership_id_sudo.user_input_ids:
|
||||
|
||||
@@ -11,7 +11,7 @@ Fullscreen.include({
|
||||
),
|
||||
|
||||
/**
|
||||
* Extend the _renderSlide method so that slides of type "certification"
|
||||
* Extend the _renderSlide method so that slides of category "certification"
|
||||
* are also taken into account and rendered correctly
|
||||
*
|
||||
* @private
|
||||
@@ -20,7 +20,7 @@ Fullscreen.include({
|
||||
_renderSlide: function (){
|
||||
var def = this._super.apply(this, arguments);
|
||||
var $content = this.$('.o_wslides_fs_content');
|
||||
if (this.get('slide').type === "certification"){
|
||||
if (this.get('slide').category === "certification"){
|
||||
$content.html(QWeb.render('website.slides.fullscreen.certification',{widget: this}));
|
||||
}
|
||||
return Promise.all([def]);
|
||||
|
||||
@@ -7,7 +7,7 @@ var sessionStorage = window.sessionStorage;
|
||||
var SlidesUpload = require('@website_slides/js/slides_upload')[Symbol.for("default")];
|
||||
|
||||
/**
|
||||
* Management of the new 'certification' slide_type
|
||||
* Management of the new 'certification' slide_category
|
||||
*/
|
||||
SlidesUpload.SlideUploadDialog.include({
|
||||
events: _.extend({}, SlidesUpload.SlideUploadDialog.prototype.events || {}, {
|
||||
@@ -32,14 +32,14 @@ SlidesUpload.SlideUploadDialog.include({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Overridden to add the "certification" slide type
|
||||
* Overridden to add the "certification" slide category
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_setup: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.slide_type_data['certification'] = {
|
||||
this.slide_category_data['certification'] = {
|
||||
icon: 'fa-trophy',
|
||||
label: _t('Certification'),
|
||||
template: 'website.slide.upload.modal.certification',
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
<t t-name="website.slides.fullscreen.certification">
|
||||
<div class="justify-content-center align-self-center">
|
||||
<div t-if="widget.get('slide').type === 'certification' && !widget.get('slide').completed" class="">
|
||||
<div t-if="widget.get('slide').category === 'certification' && !widget.get('slide').completed" class="">
|
||||
<a class="btn btn-primary" t-att-href="'/slides_survey/slide/get_certification_url?slide_id=' + widget.get('slide').id" target="_blank">
|
||||
<i class="fa fa-trophy"/>
|
||||
<span t-if="widget.get('slide').isMember"> Pass Certification</span>
|
||||
<span t-else="">Test Certification</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="" t-if="widget.get('slide').type === 'certification' && widget.get('slide').completed">
|
||||
<div class="" t-if="widget.get('slide').category === 'certification' && widget.get('slide').completed">
|
||||
<a role="button" class="btn btn-primary" t-att-href="'/survey/' + widget.get('slide').certificationId + '/get_certification'">
|
||||
<i class="fa fa-fw fa-trophy" role="img" aria-label="Download certification" title="Download certification"/> Download certification
|
||||
</a>
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<t t-extend="website.slides.fullscreen.title">
|
||||
<t t-jquery=".o_wslides_fs_slide_title_span" t-operation="before">
|
||||
<i t-if="widget.get('slide').type === 'certification'" class="fa fa-trophy mr-2 text"></i>
|
||||
<i t-if="widget.get('slide').category === 'certification'" class="fa fa-trophy mr-2 text"></i>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -47,11 +47,11 @@ class TestCourseCertificationFailureFlow(TestSurveyCommon):
|
||||
'is_published': True,
|
||||
})
|
||||
|
||||
# Step 2: link the certification to a slide of type 'certification'
|
||||
# Step 2: link the certification to a slide of category 'certification'
|
||||
self.slide_certification = self.env['slide.slide'].sudo().create({
|
||||
'name': 'Certification slide',
|
||||
'channel_id': self.channel.id,
|
||||
'slide_type': 'certification',
|
||||
'slide_category': 'certification',
|
||||
'survey_id': certification.id,
|
||||
'is_published': True,
|
||||
})
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
<span class="o_stat_text" attrs="{'invisible': [('nbr_certification', '>', 0)]}">Finished</span>
|
||||
<span class="o_stat_text" attrs="{'invisible': [('nbr_certification', '=', 0)]}">Certified</span>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='slide_type']" position="after">
|
||||
<xpath expr="//field[@name='slide_category']" position="after">
|
||||
<field name="survey_id"/>
|
||||
</xpath>
|
||||
<xpath expr="//create[@name='add_slide_lesson']" position="after">
|
||||
<create name="add_slide_certificate" string="Add Certification" groups="survey.group_survey_user" context="{'default_slide_type': 'certification'}"/>
|
||||
<create name="add_slide_certificate" string="Add Certification" groups="survey.group_survey_user" context="{'default_slide_category': 'certification'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<field name="model">slide.slide</field>
|
||||
<field name="inherit_id" ref="website_slides.view_slide_slide_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='slide_type']" position="after">
|
||||
<xpath expr="//field[@name='slide_category']" position="after">
|
||||
<field name="survey_id"
|
||||
attrs="{'invisible': [('slide_type', '!=', 'certification')], 'required': [('slide_type', '=', 'certification')]}"
|
||||
attrs="{'invisible': [('slide_category', '!=', 'certification')], 'required': [('slide_category', '=', 'certification')]}"
|
||||
domain="[('certification', '=', True)]" context="{'default_certification': True, 'default_scoring_type': 'scoring_without_answers'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
@@ -17,8 +17,8 @@
|
||||
<field name="name">Certifications</field>
|
||||
<field name="res_model">slide.slide</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="domain">[('slide_type', '=', 'certification')]</field>
|
||||
<field name="context">{'default_slide_type': 'certification'}</field>
|
||||
<field name="domain">[('slide_category', '=', 'certification')]</field>
|
||||
<field name="context">{'default_slide_category': 'certification'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new certification
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<div class="text-muted d-inline-block">No certifications yet!</div>
|
||||
</t>
|
||||
<div class="text-right d-inline-block pull-right">
|
||||
<a href="/slides/all?slide_type=certification" class="btn btn-link btn-sm"><i class="fa fa-arrow-right mr-1"/>All Certifications</a>
|
||||
<a href="/slides/all?slide_category=certification" class="btn btn-link btn-sm"><i class="fa fa-arrow-right mr-1"/>All Certifications</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div t-if="channel.nbr_certification > 0 and channel.is_member and channel.completion == 0" class="alert alert-success d-flex align-items-center justify-content-between flex-wrap">
|
||||
<div>Begin your <b>certification</b> today!</div>
|
||||
|
||||
<a t-attf-href="#{'/slides_survey/slide/get_certification_url?slide_id=%s' %(first_slide.id) if first_slide.slide_type == 'certification' and channel.total_slides == 1 else '/slides/slide/%s?fullscreen=1' %(slug(first_slide))}" class="btn btn-success mt-2 mt-sm-0">
|
||||
<a t-attf-href="#{'/slides_survey/slide/get_certification_url?slide_id=%s' %(first_slide.id) if first_slide.slide_category == 'certification' and channel.total_slides == 1 else '/slides/slide/%s?fullscreen=1' %(slug(first_slide))}" class="btn btn-success mt-2 mt-sm-0">
|
||||
<span>Start Now</span><i class="fa fa-chevron-right ml-2 align-middle"/>
|
||||
</a>
|
||||
</div>
|
||||
@@ -20,16 +20,16 @@
|
||||
|
||||
<template id="slide_icon_inherit_survey" inherit_id="website_slides.slide_icon">
|
||||
<xpath expr="//i[last()]" position="after">
|
||||
<i t-if="slide.slide_type == 'certification'" t-att-class="'fa fa-trophy %s' % icon_class"></i>
|
||||
<i t-if="slide.slide_category == 'certification'" t-att-class="'fa fa-trophy %s' % icon_class"></i>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="course_slides_list_slide_inherit_survey" inherit_id="website_slides.course_slides_list_slide">
|
||||
<xpath expr="//a[hasclass('o_wslides_js_slides_list_slide_link')]" position="attributes">
|
||||
<attribute name="t-attf-href">#{'/slides_survey/slide/get_certification_url?slide_id=%s' %(slide.id) if slide.slide_type == 'certification' and slide.channel_id.total_slides == 1 else '/slides/slide/%s' %(slug(slide))}</attribute>
|
||||
<attribute name="t-attf-href">#{'/slides_survey/slide/get_certification_url?slide_id=%s' %(slide.id) if slide.slide_category == 'certification' and slide.channel_id.total_slides == 1 else '/slides/slide/%s' %(slug(slide))}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//a[@name='o_wslides_list_slide_add_quizz']" position="attributes">
|
||||
<attribute name="t-if">channel.can_upload and not slide.question_ids and slide.slide_type != 'certification'</attribute>
|
||||
<attribute name="t-if">channel.can_upload and not slide.question_ids and slide.slide_category != 'certification'</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//a[@t-if='channel.can_upload']" position="attributes">
|
||||
<attribute name="t-attf-class">#{'d-none' if slide.slide_type == 'certification' else ''}</attribute>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<data>
|
||||
<template id="courses_home_inherit_survey" inherit_id="website_slides.courses_home">
|
||||
<xpath expr="//a[hasclass('o_wslides_home_all_slides')]" position="after">
|
||||
<a class="nav-link nav-link d-flex" href="/slides/all?slide_type=certification">
|
||||
<a class="nav-link nav-link d-flex" href="/slides/all?slide_category=certification">
|
||||
<t t-call="website_slides_survey.o_wss_certification_icon"/>
|
||||
<span class="ml-1">Certifications</span>
|
||||
</a>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<data>
|
||||
<template id="slide_content_detailed" inherit_id="website_slides.slide_content_detailed">
|
||||
<xpath expr="//div[hasclass('o_wslides_lesson_content_type')]" position="inside">
|
||||
<div t-if="slide.slide_type == 'certification' and not channel_progress[slide.id].get('completed')" class="col mt32 mb8 d-flex justify-content-center">
|
||||
<div t-if="slide.slide_category == 'certification' and not channel_progress[slide.id].get('completed')" class="col mt32 mb8 d-flex justify-content-center">
|
||||
<a role="button"
|
||||
class="btn btn-primary btn-lg"
|
||||
t-att-href="'/slides_survey/slide/get_certification_url?slide_id=%s' %(slide.id)">
|
||||
@@ -12,7 +12,7 @@
|
||||
<t t-else="">Test Certification</t>
|
||||
</a>
|
||||
</div>
|
||||
<div t-if="slide.slide_type == 'certification' and channel_progress[slide.id].get('completed')" class="col mt32 mb8 d-flex justify-content-center">
|
||||
<div t-if="slide.slide_category == 'certification' and channel_progress[slide.id].get('completed')" class="col mt32 mb8 d-flex justify-content-center">
|
||||
<a role="button" class="btn btn-primary btn-lg" t-att-href="'/survey/%s/get_certification' % slide.survey_id.id">
|
||||
<i class="fa fa-fw fa-trophy" role="img" aria-label="Download certification" title="Download certification"/> Download certification
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user