From 8c9473fd78f14dea1c55765da4f3e55f8962bcc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Mattiello?= <mcm@odoo.com> Date: Tue, 3 Sep 2019 09:30:49 +0000 Subject: [PATCH] [IMP] website_slides_{*}: improve backend UI, views and user actions Purpose of this commit is to perform a back2basics on eLearning backend views. It helps users in their daily use of eLearning and improve UI. Containing * channel kanban view tweaking; * channel form view: some spacing and renaming improvements. Also set advanced field (new content email, share template) as group no one; * slide kanban view tweaking; * removed sections from kanban and list view for contents; * contents form view: various improvements, with notably * removed field website_url; * set publishded date is now readonly, tracked and in group_no_one as it is automatically set when publishing the lesson, and people should not update it manually; * removed the sum "Content" and replaced it by a stat button * reword quiz constraint error messages; * rating views improvements: * revamped the kanban view of rating that were a bit broken; * added a pivot view in Reporting/Reviews; * updated graph view in Reporting/Reviews; This commit also provides some usability fixes * prevent sending email if new content is category; * email: Prevent displaying an image if there is no image; LINKS Task 2049640 (website slides back2basics and fiximp) Task 2058595 (eLearning v13 testing) --- .../models/slide_channel.py | 3 +- .../views/slide_channel_views.xml | 3 +- addons/website_slides/data/mail_data.xml | 2 + addons/website_slides/models/slide_channel.py | 12 ++-- .../website_slides/models/slide_question.py | 6 +- addons/website_slides/models/slide_slide.py | 18 ++++-- .../static/src/js/slides_upload.js | 4 +- .../static/src/scss/rating_rating_views.scss | 4 ++ .../static/src/scss/slide_channel_views.scss | 7 -- ...category_backend.scss => slide_views.scss} | 10 ++- addons/website_slides/views/assets.xml | 3 +- .../views/rating_rating_views.xml | 64 ++++++++++++++----- .../views/slide_channel_views.xml | 46 +++++++------ .../views/slide_slide_views.xml | 44 +++++++------ .../views/slide_channel_views.xml | 4 +- 15 files changed, 141 insertions(+), 89 deletions(-) delete mode 100644 addons/website_slides/static/src/scss/slide_channel_views.scss rename addons/website_slides/static/src/scss/{category_backend.scss => slide_views.scss} (54%) diff --git a/addons/website_sale_slides/models/slide_channel.py b/addons/website_sale_slides/models/slide_channel.py index 88920f58e556..685e0af9aa03 100644 --- a/addons/website_sale_slides/models/slide_channel.py +++ b/addons/website_sale_slides/models/slide_channel.py @@ -9,9 +9,10 @@ class Channel(models.Model): enroll = fields.Selection(selection_add=[('payment', 'On payment')]) product_id = fields.Many2one('product.product', 'Product', index=True) - product_sale_revenues = fields.Float( + product_sale_revenues = fields.Monetary( string='Total revenues', compute='_compute_product_sale_revenues', groups="sales_team.group_sale_salesman") + currency_id = fields.Many2one(related='product_id.currency_id') _sql_constraints = [ ('product_id_check', "CHECK( enroll!='payment' OR product_id IS NOT NULL )", "Product is required for on payment channels.") diff --git a/addons/website_sale_slides/views/slide_channel_views.xml b/addons/website_sale_slides/views/slide_channel_views.xml index 7df803c10d9a..4099acf0ffab 100644 --- a/addons/website_sale_slides/views/slide_channel_views.xml +++ b/addons/website_sale_slides/views/slide_channel_views.xml @@ -33,7 +33,8 @@ <xpath expr="//div[@name='info_total_time']" position="after"> <div class="d-flex" attrs="{'invisible': [('enroll', '!=', 'payment')]}"> <span class="mr-auto"><label for="product_sale_revenues" class="mb0">Sales</label></span> - <field name="product_sale_revenues"/> + <field name="product_sale_revenues" widget="monetary" options="{'currency_field': 'currency_id'}"/> + <field name="currency_id" attrs="{'invisible': True}"/> </div> </xpath> <xpath expr="//a[@name='action_channel_invite']" position="attributes"> diff --git a/addons/website_slides/data/mail_data.xml b/addons/website_slides/data/mail_data.xml index 55628822d441..88c8a45cd5af 100644 --- a/addons/website_slides/data/mail_data.xml +++ b/addons/website_slides/data/mail_data.xml @@ -11,11 +11,13 @@ Hello<br/><br/> There is something new in the course <strong>${object.channel_id.name}</strong> you are following:<br/><br/> <center><strong>${object.name}</strong></center> + % if object.image_1024 <div style="margin: 16px 8px 16px 8px; text-align: center;"> <a href="${object.website_url}"> <img alt="${object.name}" src="${ctx['base_url']}/web/image/slide.slide/${object.id}/image_1024" style="height:auto; width:150px; margin: 16px;"/> </a> </div> + % endif <div style="margin: 16px 8px 16px 8px; text-align: center;"> <a href="${object.website_url}" style="background-color: #875a7b; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px;">View content</a> diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index ee846b3d0d1e..49289105cd32 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -106,7 +106,7 @@ class Channel(models.Model): ('latest', 'Latest Published'), ('most_voted', 'Most Voted'), ('most_viewed', 'Most Viewed')], - string="Featuring Policy", default='latest', required=True) + string="Featured Content", default='latest', required=True) access_token = fields.Char("Security Token", copy=False, default=_default_access_token) nbr_presentation = fields.Integer('Presentations', compute='_compute_slides_statistics', store=True) nbr_document = fields.Integer('Documents', compute='_compute_slides_statistics', store=True) @@ -130,11 +130,11 @@ class Channel(models.Model): help="Email template to send slide publication through email", default=lambda self: self.env['ir.model.data'].xmlid_to_res_id('website_slides.slide_template_published')) share_template_id = fields.Many2one( - 'mail.template', string='Shared Template', + 'mail.template', string='Share Template', help="Email template used when sharing a slide", default=lambda self: self.env['ir.model.data'].xmlid_to_res_id('website_slides.slide_template_shared')) enroll = fields.Selection([ - ('public', 'Public'), ('invite', 'Invite')], + ('public', 'Public'), ('invite', 'On Invitation')], default='public', string='Enroll Policy', required=True, help='Condition to enroll: everyone, on invite, on payment (sale bridge).') enroll_msg = fields.Html( @@ -142,7 +142,7 @@ class Channel(models.Model): default=False, translate=tools.html_translate, sanitize_attributes=False) enroll_group_ids = fields.Many2many('res.groups', string='Auto Enroll Groups', help="Members of those groups are automatically added as members of the channel.") visibility = fields.Selection([ - ('public', 'Public'), ('members', 'Members')], + ('public', 'Public'), ('members', 'Members Only')], default='public', string='Visibility', required=True, help='Applied directly as ACLs. Allow to hide channels and their content for non members.') partner_ids = fields.Many2many( @@ -154,7 +154,7 @@ class Channel(models.Model): channel_partner_ids = fields.One2many('slide.channel.partner', 'channel_id', string='Members Information', groups='website.group_website_publisher', depends=['partner_ids']) upload_group_ids = fields.Many2many( 'res.groups', 'rel_upload_groups', 'channel_id', 'group_id', string='Upload Groups', - help="Who can publish: responsible, members of upload_group_ids if defined or website publisher group members.") + help="Group of users allowed to publish contents on a documentation course.") # not stored access fields, depending on each user completed = fields.Boolean('Done', compute='_compute_user_statistics', compute_sudo=False) completion = fields.Integer('Completion', compute='_compute_user_statistics', compute_sudo=False) @@ -493,7 +493,7 @@ class Channel(models.Model): def action_view_slides(self): action = self.env.ref('website_slides.slide_slide_action').read()[0] action['context'] = {'default_channel_id': self.id} - action['domain'] = [('channel_id', "=", self.id)] + action['domain'] = [('channel_id', "=", self.id), ('is_category', '=', False)] return action def action_view_ratings(self): diff --git a/addons/website_slides/models/slide_question.py b/addons/website_slides/models/slide_question.py index 98c51585dda5..adc871c22e24 100644 --- a/addons/website_slides/models/slide_question.py +++ b/addons/website_slides/models/slide_question.py @@ -27,19 +27,19 @@ class SlideQuestion(models.Model): if answer.is_correct: good_answer_count += 1 if good_answer_count > 1: - raise ValidationError(_('A question can only have one good answer')) + raise ValidationError(_('Question "%s" can only have one good answer') % question.question) @api.constrains('answer_ids') def _check_correct_answer(self): for question in self: if not any([answer.is_correct for answer in question.answer_ids]): - raise ValidationError(_("A question must at least have one good answer")) + raise ValidationError(_('Question "%s" must at least have one good answer') % question.question) @api.constrains('answer_ids') def _check_at_least_2_answers(self): for question in self: if len(question.answer_ids) < 2: - raise ValidationError(_("A question must at least have two possible answers")) + raise ValidationError(_('Question "%s" has no valid answer, please set one') % question.question) @api.depends('slide_id') def _compute_statistics(self): diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 2a17ade329d4..9fda90951297 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -59,7 +59,7 @@ class SlideLink(models.Model): slide_id = fields.Many2one('slide.slide', required=True, ondelete='cascade') name = fields.Char('Title', required=True) - link = fields.Char('External Link', required=True) + link = fields.Char('Link', required=True) class EmbeddedSlide(models.Model): @@ -123,11 +123,11 @@ class Slide(models.Model): description = fields.Text('Description', translate=True) channel_id = fields.Many2one('slide.channel', string="Channel", required=True) tag_ids = fields.Many2many('slide.tag', 'rel_slide_tag', 'slide_id', 'tag_id', string='Tags') - is_preview = fields.Boolean('Is Preview', default=False, help="The course is accessible by anyone : the users don't need to join the channel to access the content of the course.") - completion_time = fields.Float('Completion Time', digits=(10, 4), help="The estimated completion time for this slide") + is_preview = fields.Boolean('Allow Preview', default=False, help="The course is accessible by anyone : the users don't need to join the channel to access the content of the course.") + completion_time = fields.Float('Duration', digits=(10, 4), help="The estimated completion time for this slide") # Categories is_category = fields.Boolean('Is a category', default=False) - category_id = fields.Many2one('slide.slide', string="Category", compute="_compute_category_id", store=True) + category_id = fields.Many2one('slide.slide', string="Section", compute="_compute_category_id", store=True) slide_ids = fields.One2many('slide.slide', "category_id", string="Slides") # subscribers partner_ids = fields.Many2many('res.partner', 'slide_slide_partner', 'slide_id', 'partner_id', @@ -138,6 +138,7 @@ class Slide(models.Model): help="Subscriber information for the current logged in user") # Quiz related fields question_ids = fields.One2many("slide.question", "slide_id", string="Questions") + questions_count = fields.Integer(string="Numbers of Questions", compute='_compute_questions_count') quiz_first_attempt_reward = fields.Integer("First attempt reward", default=10) quiz_second_attempt_reward = fields.Integer("Second attempt reward", default=7) quiz_third_attempt_reward = fields.Integer("Third attempt reward", default=5,) @@ -161,7 +162,7 @@ class Slide(models.Model): html_content = fields.Html("HTML Content", help="Custom HTML content for slides of type 'Web Page'.", translate=True) # website website_id = fields.Many2one(related='channel_id.website_id', readonly=True) - date_published = fields.Datetime('Publish Date') + date_published = fields.Datetime('Publish Date', readonly=True, tracking=True) likes = fields.Integer('Likes', compute='_compute_user_info', store=True, compute_sudo=False) dislikes = fields.Integer('Dislikes', compute='_compute_user_info', store=True, compute_sudo=False) user_vote = fields.Integer('User vote', compute='_compute_user_info', compute_sudo=False) @@ -214,6 +215,11 @@ class Slide(models.Model): elif slide.category_id != current_category: slide.category_id = current_category.id + @api.depends('question_ids') + def _compute_questions_count(self): + for slide in self: + slide.questions_count = len(slide.question_ids) + @api.depends('website_message_ids.res_id', 'website_message_ids.model', 'website_message_ids.message_type') def _compute_comments_count(self): for slide in self: @@ -393,7 +399,7 @@ class Slide(models.Model): slide = super(Slide, self).create(values) - if slide.is_published: + if slide.is_published and not slide.is_category: slide._post_publication() return slide diff --git a/addons/website_slides/static/src/js/slides_upload.js b/addons/website_slides/static/src/js/slides_upload.js index 0377abedeb15..37c6245d1910 100644 --- a/addons/website_slides/static/src/js/slides_upload.js +++ b/addons/website_slides/static/src/js/slides_upload.js @@ -74,13 +74,13 @@ var SlideUploadDialog = Dialog.extend({ this.$('.alert-warning').remove(); }, /** - * Category and tags management from select2 + * Section and tags management from select2 * * @private */ _bindSelect2Dropdown: function () { var self = this; - this.$('#category_id').select2(this._select2Wrapper(_t('Category'), false, + this.$('#category_id').select2(this._select2Wrapper(_t('Section'), false, function () { return self._rpc({ route: '/slides/category/search_read', diff --git a/addons/website_slides/static/src/scss/rating_rating_views.scss b/addons/website_slides/static/src/scss/rating_rating_views.scss index 49886be92f55..e86a1811c10b 100644 --- a/addons/website_slides/static/src/scss/rating_rating_views.scss +++ b/addons/website_slides/static/src/scss/rating_rating_views.scss @@ -7,5 +7,9 @@ $o-kanban-large-record-width: 350px; .o_slide_rating_kanban_left { min-width: 80px; + + .o_slide_rating_value { + font-size: 4rem; + } } } diff --git a/addons/website_slides/static/src/scss/slide_channel_views.scss b/addons/website_slides/static/src/scss/slide_channel_views.scss deleted file mode 100644 index 3bd8203c4eb0..000000000000 --- a/addons/website_slides/static/src/scss/slide_channel_views.scss +++ /dev/null @@ -1,7 +0,0 @@ -$o-kanban-large-record-width: 400px; - -.o_kanban_view.o_slide_channel_kanban { - .o_kanban_record { - width: $o-kanban-large-record-width - } -} diff --git a/addons/website_slides/static/src/scss/category_backend.scss b/addons/website_slides/static/src/scss/slide_views.scss similarity index 54% rename from addons/website_slides/static/src/scss/category_backend.scss rename to addons/website_slides/static/src/scss/slide_views.scss index 99b017738cae..1110a3f94424 100644 --- a/addons/website_slides/static/src/scss/category_backend.scss +++ b/addons/website_slides/static/src/scss/slide_views.scss @@ -1,6 +1,14 @@ +$o-kanban-large-record-width: 400px; + +.o_kanban_view.o_slide_kanban { + .o_kanban_record { + width: $o-kanban-large-record-width + } +} + table.o_section_list_view tr.o_data_row.o_is_section { font-weight: bold; background-color: #DDD; border-top: 1px solid #BBB; border-bottom: 1px solid #BBB; -} \ No newline at end of file +} diff --git a/addons/website_slides/views/assets.xml b/addons/website_slides/views/assets.xml index ed7df5ceb550..b310391042a4 100644 --- a/addons/website_slides/views/assets.xml +++ b/addons/website_slides/views/assets.xml @@ -4,8 +4,7 @@ <template id="assets_backend" inherit_id="web.assets_backend" name="Slides Backend Assets"> <xpath expr="." position="inside"> <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/rating_rating_views.scss"/> - <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/slide_channel_views.scss"/> - <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/category_backend.scss" t-ignore="true"/> + <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/slide_views.scss"/> <script type="text/javascript" src="/website_slides/static/src/js/slide_category_one2many.js"/> <script type="text/javascript" src="/website_slides/static/src/js/rating_field_backend.js"/> </xpath> diff --git a/addons/website_slides/views/rating_rating_views.xml b/addons/website_slides/views/rating_rating_views.xml index 5446fc767795..4f95b6c7c19d 100644 --- a/addons/website_slides/views/rating_rating_views.xml +++ b/addons/website_slides/views/rating_rating_views.xml @@ -18,14 +18,15 @@ <t t-set="empty_star" t-value="5 - (val_integer + Math.ceil(val_decimal))"/> <div class="oe_kanban_card oe_kanban_global_click"> <div class="d-flex flex-row"> - <div class="o_slide_rating_kanban_left"> + <div class="o_slide_rating_kanban_left mr-3"> + <h1 class="o_slide_rating_value text-center text-primary" t-esc="val_stars"/> <t t-foreach="_.range(0, val_integer)" t-as="num"> - <i class="fa fa-star" role="img" aria-label="One star" title="One star"></i> + <i class="fa fa-star" role="img"></i> </t> <t t-if="val_decimal"> - <i class="fa fa-star-half-o" role="img" aria-label="Half a star" title="Half a star"></i> + <i class="fa fa-star-half-o" role="img"></i> </t> - <t t-foreach="_.range(0, empty_star)" t-as="num" role="img" t-attf-aria-label="#{empty_star} on 5" t-attf-title="#{empty_star} on 5"> + <t t-foreach="_.range(0, empty_star)" t-as="num" role="img"> <i class="fa fa-star text-black-25"></i> </t> </div> @@ -36,14 +37,14 @@ </div> </div> <div class="o_kanban_card_content mt0 d-flex flex-column"> - <span>for + <span> + <i class="fa fa-folder mr-2"></i> <a type="object" name="action_open_rated_object" t-att-title="record.res_name.raw_value"> <field name="res_name" /> </a> </span> - <span><i class="fa fa-clock-o mr-2"/>on <field name="create_date" /></span> + <span><i class="fa fa-clock-o mr-2"/> <field name="create_date" /></span> <div class="d-flex mt-2"> - <i t-if="record.feedback.raw_value" class="fa fa-comment mr-2" t-att-title="record.feedback.raw_value" t-att-aria-label="record.feedback.raw_value" role="img"/> <span t-esc="record.feedback.raw_value"/> </div> </div> @@ -74,19 +75,32 @@ </record> <record id="rating_rating_view_graph_slide_channel" model="ir.ui.view"> - <field name="name">rating.rating.graph</field> - <field name="model">rating.rating</field> - <field name="priority">20</field> - <field name="arch" type="xml"> - <graph string="Rating Average" type="bar" stacked="False"> + <field name="name">rating.rating.view.graph.slides</field> + <field name="model">rating.rating</field> + <field name="priority">20</field> + <field name="arch" type="xml"> + <graph string="Rating Average" type="bar"> <field name="res_name" type="row"/> - <field name="rating" type="col"/> + <field name="rating" type="measure"/> </graph> </field> </record> + <record id="rating_rating_view_pivot_slide_channel" model="ir.ui.view"> + <field name="name">rating.rating.view.pivot.slides</field> + <field name="model">rating.rating</field> + <field name="priority">20</field> + <field name="arch" type="xml"> + <pivot> + <field name="res_name" type="row"/> + <field name="rating_text" type="col"/> + <field name="rating" type="measure"/> + </pivot> + </field> + </record> + <record id="rating_rating_action_slide_channel" model="ir.actions.act_window"> - <field name="name">Courses Rating</field> + <field name="name">Rating</field> <field name="res_model">rating.rating</field> <field name="view_mode">kanban,tree,graph,pivot,form</field> <field name="domain">[('consumed', '=', True), ('res_model', '=', 'slide.channel')]</field> @@ -101,17 +115,33 @@ </record> <record id="rating_rating_action_slide_channel_report" model="ir.actions.act_window"> - <field name="name">Courses Rating</field> + <field name="name">Rating</field> <field name="res_model">rating.rating</field> - <field name="view_mode">graph,tree</field> <field name="domain">[('consumed', '=', True), ('res_model', '=', 'slide.channel')]</field> <field name="context">{}</field> <field name="search_view_id" ref="rating_rating_view_search_slide_channel"/> - <field name="view_id" ref="rating_rating_view_graph_slide_channel"/> <field name="help" type="html"> <p class="o_view_nocontent_empty_folder"> There is no rating for these courses at the moment </p> </field> </record> + <record id="rating_rating_action_slide_channel_report_view_graph" model="ir.actions.act_window.view"> + <field name="act_window_id" ref="rating_rating_action_slide_channel_report"/> + <field name="sequence">1</field> + <field name="view_mode">graph</field> + <field name="view_id" ref="rating_rating_view_graph_slide_channel"/> + </record> + <record id="rating_rating_action_slide_channel_report_view_pivot" model="ir.actions.act_window.view"> + <field name="act_window_id" ref="rating_rating_action_slide_channel_report"/> + <field name="sequence">2</field> + <field name="view_mode">pivot</field> + <field name="view_id" ref="rating_rating_view_pivot_slide_channel"/> + </record> + <record id="rating_rating_action_slide_channel_report_view_tree" model="ir.actions.act_window.view"> + <field name="act_window_id" ref="rating_rating_action_slide_channel_report"/> + <field name="sequence">3</field> + <field name="view_mode">tree</field> + <field name="view_id" eval="False"/> + </record> </odoo> diff --git a/addons/website_slides/views/slide_channel_views.xml b/addons/website_slides/views/slide_channel_views.xml index 7690d6bc469a..3a037150c3f4 100644 --- a/addons/website_slides/views/slide_channel_views.xml +++ b/addons/website_slides/views/slide_channel_views.xml @@ -3,7 +3,7 @@ <data> <!-- SLIDE.CHANNEL VIEWS --> <record model="ir.ui.view" id="view_slide_channel_form"> - <field name="name">slide.channel.form</field> + <field name="name">slide.channel.view.form</field> <field name="model">slide.channel</field> <field name="arch" type="xml"> <form string="Channels"> @@ -12,6 +12,16 @@ </header> <sheet> <div class="oe_button_box" name="button_box"> + <button name="action_view_slides" + type="object" + icon="fa-files-o" + class="oe_stat_button" + groups="website.group_website_publisher"> + <div class="o_field_widget o_stat_info"> + <span class="o_stat_value"><field name="total_slides" nolabel="1"/></span> + <span name="total_slides_label" class="o_stat_text">Contents</span> + </div> + </button> <button name="action_redirect_to_done_members" type="object" icon="fa-trophy" @@ -19,7 +29,7 @@ groups="website.group_website_publisher"> <div class="o_field_widget o_stat_info"> <span class="o_stat_value"><field name="members_done_count" nolabel="1"/></span> - <span name="stat_label" class="o_stat_text">Finished</span> + <span name="members_done_count_label" class="o_stat_text">Finished</span> </div> </button> <button name="action_redirect_to_members" @@ -45,12 +55,11 @@ <label for="name" class="oe_edit_only" string="Course Title"/> <h1><field name="name" default_focus="1" placeholder="Course Title"/></h1> </div> - <group> - <group> - <field name="active" invisible="1"/> - <field name="tag_ids" widget="many2many_tags" placeholder="Tags"/> - </group> - </group> + <div> + <field name="active" invisible="1"/> + <label for="tag_ids"/> + <field name="tag_ids" widget="many2many_tags" placeholder="Tags"/> + </div> <notebook colspan="4"> <page name="content" string="Content"> <field name="slide_ids" colspan="4" nolabel="1" widget="slide_category_one2many" context="{'default_channel_id': active_id}"> @@ -61,7 +70,6 @@ <field name="completion_time" attrs="{'invisible': [('slide_type', '=', 'category')]}"/> <field name="total_views" attrs="{'invisible': [('slide_type', '=', 'category')]}"/> <field name="is_category" invisible="1"/> - <control> <create name="add_slide_section" string="Add Section" context="{'default_is_category': True}"/> <create name="add_slide_lesson" string="Add Content"/> @@ -81,15 +89,15 @@ </group> <group name="access_rights" string="Access Rights"> <field name="enroll" widget="radio" options="{'horizontal': true}"/> - <field name="upload_group_ids" string="New Content" widget="many2many_tags"/> + <field name="upload_group_ids" widget="many2many_tags" groups="base.group_no_one"/> <field name="enroll_group_ids" widget="many2many_tags" groups="base.group_no_one"/> </group> </group> <group> <group name="communication" string="Communication"> <field string="Allow Rating" name="allow_comment"/> - <field name="publish_template_id" domain="[('model','=','slide.slide')]"/> - <field name="share_template_id" domain="[('model','=','slide.slide')]"/> + <field name="publish_template_id" domain="[('model','=','slide.slide')]" groups="base.group_no_one"/> + <field name="share_template_id" domain="[('model','=','slide.slide')]" groups="base.group_no_one"/> </group> <group name="display" string="Display"> <field name="visibility" widget="radio"/> @@ -119,8 +127,6 @@ <field name="nbr_infographic"/> <field name="nbr_quiz" string="Quizzes"/> <field name="nbr_webpage"/> - <separator/> - <field name="total_slides"/> </group> <group name="view_stats"> <field name="total_views" string="Visits"/> @@ -202,7 +208,7 @@ <field name="name">slide.channel.view.kanban</field> <field name="model">slide.channel</field> <field name="arch" type="xml"> - <kanban string="eLearning Overview" class="o_emphasize_colors o_kanban_dashboard o_slide_channel_kanban breadcrumb_item active" edit="false"> + <kanban string="eLearning Overview" class="o_emphasize_colors o_kanban_dashboard o_slide_kanban breadcrumb_item active" edit="false"> <field name="color"/> <field name="website_published"/> <templates> @@ -241,23 +247,21 @@ </div> </div> <div class="container o_kanban_card_content mt0"> - <div class="row"> + <div class="row mb16"> <div class="col-6 o_kanban_primary_left"> <button class="btn btn-primary" name="open_website_url" type="object">View course</button> </div> <div class="col-6 o_kanban_primary_right"> <div class="d-flex"> - <span class="mr-auto"><label for="rating_avg" class="mb0">Rating</label></span> - <a name="action_view_ratings" type="object"> - <field name="rating_count"/><span class="ml-2">reviews</span> (<field name="rating_avg_stars"/>/5) - </a> + <a name="action_view_ratings" type="object" class="mr-auto"><field name="rating_count"/> reviews</a> + <span><field name="rating_avg_stars"/> / 5</span> </div> <div class="d-flex"> <span class="mr-auto"><label for="total_views" class="mb0">Views</label></span> <field name="total_views"/> </div> <div class="d-flex" name="info_total_time"> - <span class="mr-auto"><label for="total_time" class="mb0">Completion Time</label></span> + <span class="mr-auto"><label for="total_time" class="mb0">Duration</label></span> <field name="total_time" widget="float_time"/> </div> </div> diff --git a/addons/website_slides/views/slide_slide_views.xml b/addons/website_slides/views/slide_slide_views.xml index 46001792f8ae..a7130a21567e 100644 --- a/addons/website_slides/views/slide_slide_views.xml +++ b/addons/website_slides/views/slide_slide_views.xml @@ -50,10 +50,10 @@ /> <div class="oe_title"> <div> - <label for="name" string="Name"/> + <label for="name" string="Content Title" class="oe_edit_only"/> </div> <h1> - <field name="name" default_focus="1" placeholder="Title"/> + <field name="name" default_focus="1" placeholder="e.g. How to grow your business with Odoo?"/> <field name="is_category" invisible="1"/> </h1> <field name="tag_ids" attrs="{'invisible': [('is_category', '=', True)]}" widget="many2many_tags" placeholder="Tags..."/> @@ -63,6 +63,7 @@ <group> <group name="lesson_details"> <field name="active" invisible="1"/> + <field name="channel_id"/> <field name="slide_type"/> <field name="url" attrs="{ 'required': [('slide_type', 'in', ('video'))], @@ -74,28 +75,26 @@ </group> <group name="related_details"> <field name="user_id"/> - <field name="channel_id"/> <field name="website_id" groups="website.group_multi_website"/> - <field name="website_url"/> <field name="is_preview"/> - <label for="completion_time" string="Completion Time"/> + <label for="completion_time"/> <div> <field name="completion_time" widget="float_time" class="oe_inline"/> <span> hours</span> </div> - <field name="date_published" string="Published Date"/> + <field name="date_published" string="Published Date" attrs="{'invisible': [('date_published', '=', False)]}" groups="base.group_no_one"/> </group> </group> </page> <page name="description" string="Description"> - <field name="description"/> + <field name="description" placeholder="e.g. In this video, we'll give you the keys on how Odoo can help you to grow your business. At the end, we'll propose you a quiz to test your knowledge."/> </page> <page string="External Links" name="external_links" > <group> <field name="link_ids" widget="one2many" nolabel="1"> <tree editable="top"> <field name="name"/> - <field name="link" widget="url"/> + <field name="link" widget="url" placeholder="e.g. https://www.odoo.com"/> </tree> </field> </group> @@ -123,15 +122,15 @@ <page name="statistics" string="Statistics"> <group> <group name="view_statistics" string="Views"> - <field string="Member views" name="slide_views"/> - <field string="Public views" name="public_views" readonly="1"/> - <field string="Total views" name="total_views"/> + <field string="Member" name="slide_views"/> + <field string="Public" name="public_views" readonly="1"/> + <field string="Total" name="total_views"/> <hr attrs="{'invisible': [('channel_allow_comment', '!=', True), ('channel_type', '=', 'training')]}"/> <field name="channel_type" invisible="1" readonly="1"/> <field name="channel_allow_comment" invisible="1" readonly="1"/> <field name="likes" attrs="{'invisible': [('channel_type', '=', 'training')]}"/> <field name="dislikes" attrs="{'invisible': [('channel_type', '=', 'training')]}"/> - <field name="comments_count" attrs="{'invisible': [('channel_allow_comment', '!=', True)]}"/> + <field name="comments_count" string="Comments" attrs="{'invisible': [('channel_allow_comment', '!=', True)]}"/> </group> </group> </page> @@ -149,10 +148,11 @@ <field name="name">slide.slide.view.kanban</field> <field name="model">slide.slide</field> <field name="arch" type="xml"> - <kanban edit="false"> + <kanban edit="false" class="o_slide_kanban"> <field name="id"/> <field name="channel_id"/> <field name="slide_type"/> + <field name="user_id"/> <templates> <t t-name="kanban-box"> <div class="oe_kanban_global_click o_kanban_record_has_image_fill"> @@ -171,21 +171,23 @@ </div> <div class="oe_kanban_details d-flex flex-column"> <strong class="o_kanban_record_title oe_partner_heading"><field name="display_name"/></strong> - <div class="o_kanban_tags_section"> + <div class="text-mutex"><field name="channel_id"/></div> + <div class="o_kanban_tags_section mb-2"> <span class="oe_kanban_list_many2many"> <field name="tag_ids" widget="many2many_tags"/> </span> </div> - <span class="text-primary"><field name="channel_id"/></span> - <span class="text-primary"><field name="user_id"/></span> - <div class=" mt-auto d-flex justify-content-between"> - <span class="badge badge-pill"> + <div class="o_kanban_record_bottom mt-auto d-flex justify-content-between align-items-end"> + <span> <i class="fa fa-clock-o mr-2" aria-label="Duration" role="img" title="Duration"/><field name="completion_time" widget="float_time"/> </span> - <span class="badge badge-pill"> + <span> + <i class="fa fa-question mr-2" aria-label="Number of Questions" role="img" title="Number of Questions"/><field name="questions_count"/> + </span> + <span> <i class="fa fa-eye mr-2" aria-label="Views" role="img" title="Views"/><field name="total_views"/> </span> - <span class="badge badge-pill"> + <span> <t t-if="record.slide_type.raw_value == 'infographic'"> <i class="fa fa-file-image-o mr-2" aria-label="Infographic" role="img" title="Infographic"/> </t> @@ -201,6 +203,7 @@ <t t-else=""><i class="fa fa-file-pdf-o mr-2" aria-label="Document" role="img" title="Document"/></t> <field name="slide_type"/> </span> + <img t-att-src="kanban_image('res.users', 'image_64', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/> </div> </div> </div> @@ -265,6 +268,7 @@ <field name="res_model">slide.slide</field> <field name="view_mode">kanban,tree,form</field> <field name="context"></field> + <field name="domain">[('is_category', '=', False)]</field> <field name="help" type="html"> <p class="o_view_nocontent_smiling_face"> Add a new lesson diff --git a/addons/website_slides_survey/views/slide_channel_views.xml b/addons/website_slides_survey/views/slide_channel_views.xml index 5a7836773200..1ff9e02a5563 100644 --- a/addons/website_slides_survey/views/slide_channel_views.xml +++ b/addons/website_slides_survey/views/slide_channel_views.xml @@ -5,12 +5,12 @@ <field name="model">slide.channel</field> <field name="inherit_id" ref="website_slides.view_slide_channel_form"/> <field name="arch" type="xml"> - <xpath expr="//span[@name='stat_label']" position="replace"> + <xpath expr="//span[@name='members_done_count_label']" position="replace"> <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='nbr_webpage']" position="after"> - <field string="Certifications" name="nbr_certification"/> + <field name="nbr_certification" string="Certifications"/> </xpath> <xpath expr="//field[@name='slide_type']" position="after"> <field name="survey_id"/> -- GitLab