[MERGE] website_slides(_*): globally improve usage of eLearning, notably in backend
Purpose ======= This commit is enhancing the website_slides module. Specifications ============== It changes placeholders for certain fields, it changes helpers in some of the views. It updates some of the main views of the menus and corrects wordings inside of them. It activates the Graph and Pivot views for the reporting of Courses, Reviews and Quizzes. It cleans up some of the measures inside of the Pivot and Graph views of each menus where it is available. It also merges 2 models: slide.slide.link and slide.slide.resource into slide.slide.resource with a type Selection field. This is done in order to create a single table for the additional resources of a Content. It also improves the front-end of the module with minor changes. It fixes the problem of long names inside of breadcrumbs. It also adds a message when there is no leaderboard in /profile/users. task-2597345 closes odoo/odoo#75646 Related: odoo/upgrade#2784 Related: odoo/enterprise#20480 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
<xpath expr="//div[@name='action_channel_invite']" position="after">
|
||||
<div role="menuitem">
|
||||
<a name="action_mass_mailing_attendees" type="object"
|
||||
groups="mass_mailing.group_mass_mailing_user">
|
||||
groups="mass_mailing.group_mass_mailing_user" class="float-left pr-1">
|
||||
Contact Attendees
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ from odoo import api, fields, models
|
||||
|
||||
from odoo.modules.module import get_resource_path
|
||||
|
||||
RATING_LIMIT_SATISFIED = 5
|
||||
RATING_LIMIT_SATISFIED = 4
|
||||
RATING_LIMIT_OK = 3
|
||||
RATING_LIMIT_MIN = 1
|
||||
|
||||
|
||||
@@ -49,8 +49,11 @@
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<field name="background_image" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title" style="width: 100%;">
|
||||
<label for="title"/>
|
||||
<h1><field name="title" placeholder="e.g. Satisfaction Survey"/></h1>
|
||||
<label for="title" class="oe_edit_only" string="Survey Title" attrs="{'invisible': [('certification', '=', True)]}"/>
|
||||
<label for="title" class="oe_edit_only" string="Certification Title" attrs="{'invisible': [('certification', '=', False)]}"/>
|
||||
<h1>
|
||||
<field name="title" placeholder="e.g. Satisfaction Survey"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
@@ -297,6 +300,26 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="survey_survey_view_graph" model="ir.ui.view">
|
||||
<field name="name">survey.survey.view.graph</field>
|
||||
<field name="model">survey.survey</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph>
|
||||
<field type="measure" name="color" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="survey_survey_view_pivot" model="ir.ui.view">
|
||||
<field name="name">survey.survey.view.pivot</field>
|
||||
<field name="model">survey.survey</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot>
|
||||
<field type="measure" name="color" invisible="1"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Surveys" id="menu_survey_form" action="action_survey_form" parent="menu_surveys" sequence="1"/>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<label for="name"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="e.g. Who to do this particular thing?"/>
|
||||
<field name="name" placeholder="e.g. When should I plant my tomatoes?"/>
|
||||
</h1>
|
||||
<group>
|
||||
<group name="forum_details">
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
<form t-attf-action="/profile/users" role="search" method="get">
|
||||
<div class="input-group o_wprofile_course_nav_search ml-1 position-relative">
|
||||
<span class="input-group-prepend">
|
||||
<button class="btn btn-link text-white rounded-0 pr-1" type="submit" aria-label="Search" title="Search">
|
||||
<i class="fa fa-search"></i>
|
||||
<button class="btn btn-link text-white border-1 rounded-0 pr-1 mr-2" type="submit" aria-label="Search" title="Search">
|
||||
<i class="fa fa-search border-1"></i>
|
||||
</button>
|
||||
</span>
|
||||
<input type="text" class="form-control border-0 rounded-0 bg-transparent text-white" name="search" placeholder="Search users"/>
|
||||
<input type="text" class="form-control border-0 rounded-0 bg-transparent text-white ml-auto" name="search" placeholder="Search users"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -486,10 +486,17 @@
|
||||
-->
|
||||
<template id="users_page_main" name="Users Page">
|
||||
<t t-set="body_classname" t-value="'o_wprofile_body'"/>
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="o_wprofile_wrap mt-0 pb-5">
|
||||
<t t-call="website_profile.users_page_header"/>
|
||||
<t t-call="website_profile.users_page_content"/>
|
||||
<t t-call="website.layout">
|
||||
<div class="h-100 d-flex flex-column">
|
||||
<div id="wrap" class="o_wprofile_wrap mt-0 pb-5 ">
|
||||
<t t-call="website_profile.users_page_header"/>
|
||||
<t t-if="users">
|
||||
<t t-call="website_profile.users_page_content"/>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="not users">
|
||||
<h2 class="text-black m-auto">No Leaderboard Yet :(</h2>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
<field name="view_id" ref="sale_report_view_graph_slides"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No data yet!
|
||||
No sales data yet!
|
||||
</p>
|
||||
<p>Come back once your courses starts selling to report on your revenues.</p>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<xpath expr="//button[@name='action_redirect_to_members']" position="after">
|
||||
<button name="action_view_sales"
|
||||
type="object"
|
||||
icon="fa-signal"
|
||||
icon="fa-usd"
|
||||
class="oe_stat_button"
|
||||
attrs="{'invisible': [('enroll', '!=', 'payment')]}"
|
||||
groups="sales_team.group_sale_salesman">
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
</record>
|
||||
<!--RESOURCE-->
|
||||
<record id="slide_slide_demo_0_0_resource_0" model="slide.slide.resource">
|
||||
<field name="resource_type">file</field>
|
||||
<field name="name">Document</field>
|
||||
<field name="data" type="base64" file="website_slides/static/src/img/document.png"/>
|
||||
<field name="slide_id" ref="slide_slide_demo_0_0"/>
|
||||
@@ -186,18 +187,21 @@
|
||||
<field name="tag_ids" eval="[(4, ref('website_slides.slide_tag_demo_colorful')), (4, ref('website_slides.slide_tag_demo_theory'))]"/>
|
||||
<field name="description">Just some basics Energy Efficiency Facts.</field>
|
||||
</record>
|
||||
<record id="slide_slide_demo_1_2_link_0" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_1_2_link_0" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Energy Efficient Link 1</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_1_2"/>
|
||||
</record>
|
||||
<record id="slide_slide_demo_1_2_link_1" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_1_2_link_1" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Energy Efficient Link 2</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_1_2"/>
|
||||
</record>
|
||||
<!--RESOURCE-->
|
||||
<record id="slide_slide_demo_1_2_resource_0" model="slide.slide.resource">
|
||||
<field name="resource_type">file</field>
|
||||
<field name="name">Presentation</field>
|
||||
<field name="data" type="base64" file="website_slides/static/src/img/presentation.pdf"/>
|
||||
<field name="slide_id" ref="slide_slide_demo_1_2"/>
|
||||
@@ -263,12 +267,14 @@
|
||||
<field name="tag_ids" eval="[(4, ref('website_slides.slide_tag_demo_colorful'))]"/>
|
||||
<field name="description">We had a little chat with Harry Potted, sure he had interesting things to say !</field>
|
||||
</record>
|
||||
<record id="slide_slide_demo_1_4_link_0" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_1_4_link_0" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Know More Link 1</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_1_4"/>
|
||||
</record>
|
||||
<record id="slide_slide_demo_1_4_link_1" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_1_4_link_1" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Know More Link 2</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_1_4"/>
|
||||
@@ -389,18 +395,21 @@
|
||||
<field name="description">A summary of know-how: what are the main trees categories and how to differentiate them.</field>
|
||||
</record>
|
||||
<!-- LINKS -->
|
||||
<record id="slide_slide_demo_2_0_link_0" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_2_0_link_0" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Trees Classification Link</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_2_0"/>
|
||||
</record>
|
||||
<record id="slide_slide_demo_2_0_link_1" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_2_0_link_1" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Main types of trees Link</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_2_0"/>
|
||||
</record>
|
||||
<!--RESOURCE-->
|
||||
<record id="slide_slide_demo_2_0_resource_0" model="slide.slide.resource">
|
||||
<field name="resource_type">file</field>
|
||||
<field name="name">Tree image</field>
|
||||
<field name="data" type="base64" file="website_slides/static/src/img/slide_demo_tree_img_2.jpg"/>
|
||||
<field name="slide_id" ref="slide_slide_demo_2_0"/>
|
||||
@@ -742,12 +751,14 @@
|
||||
<field name="tag_ids" eval="[(4, ref('website_slides.slide_tag_demo_tools'))]"/>
|
||||
<field name="description">Tools you will need to complete this course.</field>
|
||||
</record>
|
||||
<record id="slide_slide_demo_5_0_link_0" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_5_0_link_0" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Example Link 1</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_5_0"/>
|
||||
</record>
|
||||
<record id="slide_slide_demo_5_0_link_1" model="slide.slide.link">
|
||||
<record id="slide_slide_demo_5_0_link_1" model="slide.slide.resource">
|
||||
<field name="resource_type">url</field>
|
||||
<field name="name">Example Link 2</field>
|
||||
<field name="link">http://www.example.com</field>
|
||||
<field name="slide_id" ref="slide_slide_demo_5_0"/>
|
||||
|
||||
@@ -7,6 +7,7 @@ from . import slide_slide
|
||||
from . import slide_question
|
||||
from . import slide_channel
|
||||
from . import slide_channel_tag
|
||||
from . import slide_slide_resource
|
||||
from . import res_config_settings
|
||||
from . import website
|
||||
from . import res_users
|
||||
|
||||
@@ -166,25 +166,21 @@ class Channel(models.Model):
|
||||
string='Tags', help='Used to categorize and filter displayed channels/courses')
|
||||
# slides: promote, statistics
|
||||
slide_ids = fields.One2many('slide.slide', 'channel_id', string="Slides and categories")
|
||||
slide_content_ids = fields.One2many('slide.slide', string='Slides', compute="_compute_category_and_slide_ids")
|
||||
slide_content_ids = fields.One2many('slide.slide', string='Content', compute="_compute_category_and_slide_ids")
|
||||
slide_category_ids = fields.One2many('slide.slide', string='Categories', compute="_compute_category_and_slide_ids")
|
||||
slide_last_update = fields.Date('Last Update', compute='_compute_slide_last_update', store=True)
|
||||
slide_partner_ids = fields.One2many(
|
||||
'slide.slide.partner', 'channel_id', string="Slide User Data",
|
||||
copy=False, groups='website_slides.group_website_slides_officer')
|
||||
promote_strategy = fields.Selection([
|
||||
('latest', 'Latest Published'),
|
||||
('latest', 'Latest Created'),
|
||||
('most_voted', 'Most Voted'),
|
||||
('most_viewed', 'Most Viewed'),
|
||||
('specific', 'Specific'),
|
||||
('specific', 'Select Manually'),
|
||||
('none', 'None')],
|
||||
string="Promoted Content", default='latest', required=False,
|
||||
help='Depending the promote strategy, a slide will appear on the top of the course\'s page :\n'
|
||||
' * Latest Published : the slide created last.\n'
|
||||
' * Most Voted : the slide which has to most votes.\n'
|
||||
' * Most Viewed ; the slide which has been viewed the most.\n'
|
||||
' * Specific : You choose the slide to appear.\n'
|
||||
' * None : No slides will be shown.\n')
|
||||
string="Featured Content", default='specific', required=False,
|
||||
help='Defines the content that will be promoted on the course home page',
|
||||
)
|
||||
promoted_slide_id = fields.Many2one('slide.slide', string='Promoted Slide')
|
||||
access_token = fields.Char("Security Token", copy=False, default=_default_access_token)
|
||||
nbr_presentation = fields.Integer('Presentations', compute='_compute_slides_statistics', store=True)
|
||||
@@ -193,7 +189,7 @@ class Channel(models.Model):
|
||||
nbr_infographic = fields.Integer('Infographics', compute='_compute_slides_statistics', store=True)
|
||||
nbr_webpage = fields.Integer("Webpages", compute='_compute_slides_statistics', store=True)
|
||||
nbr_quiz = fields.Integer("Number of Quizs", compute='_compute_slides_statistics', store=True)
|
||||
total_slides = fields.Integer('Content', compute='_compute_slides_statistics', store=True)
|
||||
total_slides = fields.Integer('Number of Contents', compute='_compute_slides_statistics', store=True)
|
||||
total_views = fields.Integer('Visits', compute='_compute_slides_statistics', store=True)
|
||||
total_votes = fields.Integer('Votes', compute='_compute_slides_statistics', store=True)
|
||||
total_time = fields.Float('Duration', compute='_compute_slides_statistics', digits=(10, 2), store=True)
|
||||
@@ -201,32 +197,32 @@ class Channel(models.Model):
|
||||
# configuration
|
||||
allow_comment = fields.Boolean(
|
||||
"Allow rating on Course", default=True,
|
||||
help="If checked it allows members to either:\n"
|
||||
" * like content and post comments on documentation course;\n"
|
||||
" * post comment and review on training course;")
|
||||
help="Allow Attendees to like and comment your content and to submit reviews on your course.")
|
||||
publish_template_id = fields.Many2one(
|
||||
'mail.template', string='New Content Email',
|
||||
help="Email attendees once a new content is published",
|
||||
default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.slide_template_published'))
|
||||
'mail.template', string='New Content Notification',
|
||||
help="Defines the email your Attendees will receive each time you upload new content.",
|
||||
default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.slide_template_published'),
|
||||
domain=[('model', '=', 'slide.slide')])
|
||||
share_template_id = fields.Many2one(
|
||||
'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'))
|
||||
completed_template_id = fields.Many2one(
|
||||
'mail.template', string='Completion Email', help="Email attendees once they've finished the course",
|
||||
default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.mail_template_channel_completed'))
|
||||
'mail.template', string='Completion Notification', help="Defines the email your Attendees will receive once they reach the end of your course.",
|
||||
default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.mail_template_channel_completed'),
|
||||
domain=[('model', '=', 'slide.channel.partner')])
|
||||
enroll = fields.Selection([
|
||||
('public', 'Public'), ('invite', 'On Invitation')],
|
||||
default='public', string='Enroll Policy', required=True,
|
||||
help='Condition to enroll: everyone, on invite, on payment (sale bridge).')
|
||||
help='Defines how people can enroll to your Course.')
|
||||
enroll_msg = fields.Html(
|
||||
'Enroll Message', help="Message explaining the enroll process",
|
||||
default=_get_default_enroll_msg, 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 Only')],
|
||||
('public', 'Open To All'), ('members', 'Members Only')],
|
||||
default='public', string='Visibility', required=True,
|
||||
help='Applied directly as ACLs. Allow to hide channels and their content for non members.')
|
||||
help='Defines who can access your courses and their content.')
|
||||
partner_ids = fields.Many2many(
|
||||
'res.partner', 'slide_channel_partner', 'channel_id', 'partner_id',
|
||||
string='Members', help="All members of the channel.", context={'active_test': False}, copy=False, depends=['channel_partner_ids'])
|
||||
@@ -531,10 +527,20 @@ class Channel(models.Model):
|
||||
""" Redirects to attendees of the course. If completed is True, a filter
|
||||
will be added in action that will display only attendees who have completed
|
||||
the course. """
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_channel_partner_action")
|
||||
action_ctx = {'active_test': False}
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_channel_partner_action")
|
||||
if completed:
|
||||
action_ctx['search_default_filter_completed'] = 1
|
||||
action['domain'] = [('channel_id', 'in', self.ids)]
|
||||
action['sample'] = 1
|
||||
if completed:
|
||||
help_message = {'header_message':_("No Attendee has completed this course yet!"), 'body_message': ""}
|
||||
else:
|
||||
help_message = {
|
||||
'header_message': _("No Attendees Yet!"),
|
||||
'body_message': _("From here you'll be able to monitor attendees and to track their progress.")
|
||||
}
|
||||
action['help'] = """<p class="o_view_nocontent_smiling_face">%(header_message)s</p><p>%(body_message)s</p>""" % help_message
|
||||
if len(self) == 1:
|
||||
action['display_name'] = _('Attendees of %s', self.name)
|
||||
action_ctx['search_default_channel_id'] = self.id
|
||||
|
||||
@@ -27,7 +27,7 @@ class SlideChannelTag(models.Model):
|
||||
|
||||
name = fields.Char('Name', required=True, translate=True)
|
||||
sequence = fields.Integer('Sequence', default=10, index=True, required=True)
|
||||
group_id = fields.Many2one('slide.channel.tag.group', string='Group', index=True, required=True)
|
||||
group_id = fields.Many2one('slide.channel.tag.group', string='Group', index=True, required=True, ondelete="cascade")
|
||||
group_sequence = fields.Integer(
|
||||
'Group sequence', related='group_id.sequence',
|
||||
index=True, readonly=True, store=True)
|
||||
|
||||
@@ -55,25 +55,6 @@ class SlidePartnerRelation(models.Model):
|
||||
('partner_id', 'in', self.partner_id.ids),
|
||||
])._recompute_completion()
|
||||
|
||||
|
||||
class SlideLink(models.Model):
|
||||
_name = 'slide.slide.link'
|
||||
_description = "External URL for a particular slide"
|
||||
|
||||
slide_id = fields.Many2one('slide.slide', required=True, ondelete='cascade')
|
||||
name = fields.Char('Title', required=True)
|
||||
link = fields.Char('Link', required=True)
|
||||
|
||||
|
||||
class SlideResource(models.Model):
|
||||
_name = 'slide.slide.resource'
|
||||
_description = "Additional resource for a particular slide"
|
||||
|
||||
slide_id = fields.Many2one('slide.slide', required=True, ondelete='cascade')
|
||||
name = fields.Char('Name', required=True)
|
||||
data = fields.Binary('Resource')
|
||||
|
||||
|
||||
class EmbeddedSlide(models.Model):
|
||||
""" Embedding in third party websites. Track view count, generate statistics. """
|
||||
_name = 'slide.embed'
|
||||
@@ -144,7 +125,7 @@ class Slide(models.Model):
|
||||
# Categories
|
||||
is_category = fields.Boolean('Is a category', default=False)
|
||||
category_id = fields.Many2one('slide.slide', string="Section", compute="_compute_category_id", store=True)
|
||||
slide_ids = fields.One2many('slide.slide', "category_id", string="Slides")
|
||||
slide_ids = fields.One2many('slide.slide', "category_id", string="Content")
|
||||
# subscribers
|
||||
partner_ids = fields.Many2many('res.partner', 'slide_slide_partner', 'slide_id', 'partner_id',
|
||||
string='Subscribers', groups='website_slides.group_website_slides_officer', copy=False)
|
||||
@@ -170,10 +151,9 @@ class Slide(models.Model):
|
||||
string='Type', 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('Content', attachment=True)
|
||||
datas = 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")
|
||||
link_ids = fields.One2many('slide.slide.link', 'slide_id', string="External URL for this slide")
|
||||
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')
|
||||
@@ -189,7 +169,7 @@ class Slide(models.Model):
|
||||
embedcount_ids = fields.One2many('slide.embed', 'slide_id', string="Embed Count")
|
||||
slide_views = fields.Integer('# of Website Views', store=True, compute="_compute_slide_views")
|
||||
public_views = fields.Integer('# of Public Views', copy=False)
|
||||
total_views = fields.Integer("Views", default="0", compute='_compute_total', store=True)
|
||||
total_views = fields.Integer("# Total Views", default="0", compute='_compute_total', store=True)
|
||||
# comments
|
||||
comments_count = fields.Integer('Number of comments', compute="_compute_comments_count")
|
||||
# channel
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class SlideResource(models.Model):
|
||||
_name = 'slide.slide.resource'
|
||||
_description = "Additional resource for a particular slide"
|
||||
|
||||
slide_id = fields.Many2one('slide.slide', required=True, ondelete='cascade')
|
||||
resource_type = fields.Selection([('file', 'File'), ('url', 'Link')], required=True)
|
||||
name = fields.Char('Name', compute="_compute_name", readonly=False, store=True)
|
||||
data = fields.Binary('Resource', compute='_compute_reset_resources', store=True, readonly=False)
|
||||
file_name = fields.Char(store=True)
|
||||
link = fields.Char('Link', compute='_compute_reset_resources', store=True, readonly=False)
|
||||
|
||||
_sql_constraints = [
|
||||
('check_url', "CHECK (resource_type != 'url' OR link IS NOT NULL)", 'A resource of type url must contain a link.'),
|
||||
('check_file_type', "CHECK (resource_type != 'file' OR link IS NULL)", 'A resource of type file cannot contain a link.'),
|
||||
]
|
||||
|
||||
@api.depends('resource_type')
|
||||
def _compute_reset_resources(self):
|
||||
for resource in self:
|
||||
if resource.resource_type == 'file':
|
||||
resource.link = False
|
||||
resource.data = resource.data
|
||||
else:
|
||||
resource.data = False
|
||||
resource.link = resource.link
|
||||
|
||||
@api.depends('file_name', 'resource_type', 'data', 'link')
|
||||
def _compute_name(self):
|
||||
for resource in self:
|
||||
to_update = not resource.name or resource.name == _("Resource")
|
||||
if to_update:
|
||||
new_name = _("Resource")
|
||||
if resource.resource_type == 'file' and (resource.data or resource.file_name):
|
||||
new_name = self.file_name
|
||||
elif resource.resource_type == 'url':
|
||||
new_name = self.link
|
||||
resource.name = new_name
|
||||
|
||||
@api.constrains('data')
|
||||
def _check_link_type(self):
|
||||
for record in self:
|
||||
if record.resource_type != 'file' and record.data:
|
||||
raise ValidationError(_("Resource %(resource_name)s is a link and should not contain a data file", resource_name=record.name))
|
||||
@@ -21,8 +21,6 @@ access_slide_channel_partners_all,slide.channel.users.all,model_slide_channel_pa
|
||||
access_slide_channel_partners_system,slide.channel.users.system,model_slide_channel_partner,website_slides.group_website_slides_officer,1,1,1,1
|
||||
access_slide_embed_all,slide.embed.all,model_slide_embed,,1,0,0,0
|
||||
access_slide_embed_user,slide.embed.user,model_slide_embed,base.group_user,1,1,1,1
|
||||
access_slide_slide_link_all,slide.slide.link.all,model_slide_slide_link,,1,0,0,0
|
||||
access_slide_slide_link_officer,slide.slide.link.officer,model_slide_slide_link,website_slides.group_website_slides_officer,1,1,1,1
|
||||
access_slide_slide_resource_all,slide.slide.resource.all,model_slide_slide_resource,,1,0,0,0
|
||||
access_slide_slide_resource_public,slide.slide.resource.public,model_slide_slide_resource,base.group_public,0,0,0,0
|
||||
access_slide_slide_resource_publisher,slide.slide.resource.publisher,model_slide_slide_resource,website_slides.group_website_slides_officer,1,1,1,1
|
||||
|
||||
|
@@ -198,5 +198,16 @@
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_slide_slide_resource_downloadable_manager" model="ir.rule">
|
||||
<field name="name">Resource: manager: crud all</field>
|
||||
<field name="model_id" ref="model_slide_slide_resource"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
<field name="groups" eval="[(4, ref('group_website_slides_manager'))]"/>
|
||||
<field name="perm_read" eval="1"/>
|
||||
<field name="perm_write" eval="1"/>
|
||||
<field name="perm_create" eval="1"/>
|
||||
<field name="perm_unlink" eval="1"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -36,7 +36,7 @@ $o-wslides-fs-side-width: 300px;
|
||||
margin-top: 10px;
|
||||
line-height: 1.8em;
|
||||
padding-left: 8px;
|
||||
padding-right: 5px;
|
||||
padding-right: 5px;
|
||||
background: #17A2B8;
|
||||
color: white;
|
||||
box-shadow: 0px 0px 3px gray;
|
||||
@@ -50,7 +50,7 @@ $o-wslides-fs-side-width: 300px;
|
||||
position: absolute;
|
||||
height: 0px;
|
||||
width: 0px;
|
||||
right: 0;
|
||||
right: 0;
|
||||
margin-right: -15px;
|
||||
border-left: 15px solid #17A2B8;
|
||||
border-bottom: 12px solid transparent;
|
||||
@@ -176,7 +176,7 @@ $o-wslides-fs-side-width: 300px;
|
||||
}
|
||||
|
||||
.o_wslides_entry_muted {
|
||||
opacity: 0.5;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
// Solve an overfow issue caused in some
|
||||
@@ -319,7 +319,15 @@ $o-wslides-fs-side-width: 300px;
|
||||
border-width: 0 1px;
|
||||
}
|
||||
|
||||
.breadcrumb-item.active a, .breadcrumb-item a:hover {
|
||||
.breadcrumb-item, .breadcrumb-item.active{
|
||||
--max-lines: 2;
|
||||
position: relative;
|
||||
max-height: calc(1.4rem * var(--max-lines));
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.breadcrumb-item.active a, .breadcrumb-item a:hover{
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<div class="form-group row">
|
||||
<label for="section_name" class="col-sm-3 col-form-label">Section name</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="name" id="section_name" required="required" placeholder="e.g. Introduction"/>
|
||||
<input type="text" autocomplete="off" class="form-control" name="name" id="section_name" required="required" placeholder="e.g. Introduction"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-form-label">Title</label>
|
||||
<input type="text" class="form-control" name="name" id="title" placeholder="Computer Science for kids" required="1"/>
|
||||
<input type="text" class="form-control" autocomplete="off" name="name" id="title" placeholder="Computer Science for kids" required="1"/>
|
||||
<p id="title-required" class="text-danger mt-1 mb-0 d-none">Please fill in this field</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<t t-name="website.slide.upload.modal.common">
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-form-label">Title</label>
|
||||
<input id="name" name="name" placeholder="Title" class="form-control" required="required"/>
|
||||
<input id="name" name="name" placeholder="Title" class="form-control" required="required" autocomplete="off"/>
|
||||
</div>
|
||||
<div t-if="!widget.defaultCategoryID" class="form-group">
|
||||
<label for="category_id" class="col-form-label">Section</label>
|
||||
@@ -73,7 +73,7 @@
|
||||
<div class="form-group">
|
||||
<label for="duration" class="col-form-label">Duration</label>
|
||||
<div class="input-group">
|
||||
<input type="number" id="duration" min="0" name="duration" placeholder="Estimated slide completion time" class="form-control"/>
|
||||
<input type="number" id="duration" min="0" name="duration" placeholder="Estimated slide completion time" class="form-control" autocomplete="off"/>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Minutes</span>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from . import common
|
||||
from . import test_karma
|
||||
from . import test_resources
|
||||
from . import test_security
|
||||
from . import test_slide_utils
|
||||
from . import test_statistics
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from psycopg2 import IntegrityError
|
||||
|
||||
from odoo.addons.website_slides.tests import common
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class TestResources(common.SlidesCase):
|
||||
|
||||
@users('user_officer')
|
||||
@mute_logger('odoo')
|
||||
def test_constraints(self):
|
||||
self.link = self.env["slide.slide.resource"].create({
|
||||
'name': 'Test Link',
|
||||
'resource_type': 'url',
|
||||
'link': 'https://www.example.com',
|
||||
'slide_id': self.slide.id,
|
||||
})
|
||||
|
||||
self.resource = self.env["slide.slide.resource"].create({
|
||||
'name': 'Test Resource',
|
||||
'resource_type': 'file',
|
||||
'data': '1111',
|
||||
'slide_id': self.slide.id,
|
||||
})
|
||||
|
||||
self.assertEqual(len(self.slide.slide_resource_ids), 2)
|
||||
with self.assertRaises(ValidationError, msg="Cannot have a type link with a file"):
|
||||
self.env["slide.slide.resource"].create({
|
||||
'name': 'Raise Error Test Resource',
|
||||
'resource_type': 'url',
|
||||
'link': '1111',
|
||||
'data': '1111',
|
||||
'slide_id': self.slide.id,
|
||||
})
|
||||
self.assertEqual(len(self.slide.slide_resource_ids), 2)
|
||||
with self.assertRaises(IntegrityError, msg="Cannot have a type file with a link"):
|
||||
self.env["slide.slide.resource"].create({
|
||||
'name': 'Raise Error Test File With Link',
|
||||
'resource_type': 'file',
|
||||
'link': '1111',
|
||||
'slide_id': self.slide.id,
|
||||
})
|
||||
with self.assertRaises(IntegrityError, msg="Cannot have an empty link"):
|
||||
self.env["slide.slide.resource"].create({
|
||||
'name': 'Raise Error Test Empty URL',
|
||||
'resource_type': 'url',
|
||||
'slide_id': self.slide.id,
|
||||
})
|
||||
@@ -64,13 +64,15 @@
|
||||
<field name="inherit_id" ref="rating.rating_rating_view_search"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='resource']" position="after">
|
||||
<xpath expr="//filter[@name='rating_text']" position="after">
|
||||
<filter string="Course" name="groupby_course" context="{'group_by': 'res_name'}"/>
|
||||
</xpath>
|
||||
<xpath expr="/search" position="inside">
|
||||
<filter string="Creation Date" name="rating_last_30_days" date="create_date" default_period="last_30_days"/>
|
||||
<separator/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='responsible']" position="replace"/>
|
||||
<xpath expr="//filter[@name='resource']" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -79,9 +81,11 @@
|
||||
<field name="model">rating.rating</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Rating Average" sample="1">
|
||||
<field name="res_name"/>
|
||||
<graph string="Reviews" type="bar" sample="1">
|
||||
<field name="res_name" invisible="1"/>
|
||||
<field name="rating" type="measure"/>
|
||||
<field name="res_id" invisible="1"/>
|
||||
<field name="parent_res_id" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -99,49 +103,104 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rating_rating_action_slide_channel" model="ir.actions.act_window">
|
||||
<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>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="rating_rating_view_search_slide_channel"/>
|
||||
<field name="view_id" ref="rating_rating_view_kanban_slide_channel"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
There are no ratings for these courses at the moment
|
||||
</p>
|
||||
<record id="rating_rating_view_tree_slide_channel" model="ir.ui.view">
|
||||
<field name="name">rating.rating.view.tree.slides</field>
|
||||
<field name="model">rating.rating</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree create="0">
|
||||
<field name="create_date" string="Review Date"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="res_name" string="Course"/>
|
||||
<field name="rating" string="Score"/>
|
||||
<field name="feedback"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rating_rating_action_slide_channel_report" model="ir.actions.act_window">
|
||||
<field name="name">Rating</field>
|
||||
<record id="rating_rating_action_slide_channel" model="ir.actions.act_window">
|
||||
<field name="name">Reviews</field>
|
||||
<field name="res_model">rating.rating</field>
|
||||
<field name="domain">[('consumed', '=', True), ('res_model', '=', 'slide.channel')]</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="view_mode">kanban,tree,graph,pivot,form</field>
|
||||
<field name="search_view_id" ref="rating_rating_view_search_slide_channel"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
There are no ratings for these courses at the moment
|
||||
No Reviews yet!
|
||||
</p>
|
||||
<p>Come back later to check the feedbacks given by your Attendees.</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"/>
|
||||
|
||||
<record id="rating_rating_view_form_slides" model="ir.ui.view">
|
||||
<field name="name">rating.rating.view.form.slides</field>
|
||||
<field name="model">rating.rating</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="active" eval="True"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Ratings" create="false">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="partner_id"/>
|
||||
<field name="resource_ref" string="Course"/>
|
||||
<field name="feedback" attrs="{'invisible': [('feedback','=',False)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="rating"/>
|
||||
<field name="create_date"/>
|
||||
<field name="is_internal"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rating_rating_view_search_slides" model="ir.ui.view">
|
||||
<field name="name">rating.rating.view.search.inherit</field>
|
||||
<field name="model">rating.rating</field>
|
||||
<field name="inherit_id" ref="rating.rating_rating_view_search" />
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='my_ratings']" position="replace"/>
|
||||
<xpath expr="//filter[@name='responsible']" position="replace"/>
|
||||
<xpath expr="//filter[@name='resource']" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rating_rating_action_slide_channel_view_kanban" model="ir.actions.act_window.view">
|
||||
<field name="act_window_id" ref="rating_rating_action_slide_channel"/>
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="rating_rating_view_kanban_slide_channel"/>
|
||||
</record>
|
||||
|
||||
<record id="rating_rating_action_slide_channel_view_graph" model="ir.actions.act_window.view">
|
||||
<field name="act_window_id" ref="rating_rating_action_slide_channel"/>
|
||||
<field name="sequence">2</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>
|
||||
<record id="rating_rating_action_slide_channel_view_pivot" model="ir.actions.act_window.view">
|
||||
<field name="act_window_id" ref="rating_rating_action_slide_channel"/>
|
||||
<field name="sequence">3</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>
|
||||
<record id="rating_rating_action_slide_channel_view_tree" model="ir.actions.act_window.view">
|
||||
<field name="act_window_id" ref="rating_rating_action_slide_channel"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="view_id" ref="rating_rating_view_tree_slide_channel"/>
|
||||
</record>
|
||||
<record id="rating_rating_action_slide_channel_view_form" model="ir.actions.act_window.view">
|
||||
<field name="act_window_id" ref="rating_rating_action_slide_channel"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="rating_rating_view_form_slides"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -30,54 +30,55 @@
|
||||
<xpath expr="//div[hasclass('settings')]" position="inside">
|
||||
<div class="app_settings_block" data-string="eLearning" string="eLearning" data-key="website_slides">
|
||||
<h2>eLearning</h2>
|
||||
<div class="row mt16 o_settings_container" id="elearning_selection_settings">
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="elearning_install_forum">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_slides_forum"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_slides_forum"/>
|
||||
<div class="text-muted">
|
||||
Create a community and let the members help each others
|
||||
<div class="row mt16 o_settings_container" id="website_slides_selection_settings">
|
||||
<group>
|
||||
<div class="o_setting_box mr-auto" id="website_slide_install_website_slides_survey">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_slides_survey"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_slides_survey"/>
|
||||
<div class="text-muted">
|
||||
Evaluate the knowledge of your Attendees and certify their skills.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6"></div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="website_slides_install_mass_mailing_slides">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_mass_mailing_slides"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_mass_mailing_slides"/>
|
||||
<div class="text-muted">
|
||||
Contact all the members of a course via mass mailing
|
||||
<div class="o_setting_box" id="website_slides_install_mass_mailing_slides">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_mass_mailing_slides"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_mass_mailing_slides"/>
|
||||
<div class="text-muted">
|
||||
Update all your Attendees at once through mass mailings.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6"></div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="elearning_install_certif">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_slides_survey"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_slides_survey"/>
|
||||
<div class="text-muted">
|
||||
Evaluate your students and certify them
|
||||
</group>
|
||||
<group>
|
||||
<div class="o_setting_box mr-auto" id="website_slide_install_website_slides_forum">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_slides_forum"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_slides_forum"/>
|
||||
<div class="text-muted mr-auto">
|
||||
Create a community and let Attendees answer each others' questions.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6"></div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="elearning_install_sell">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_sale_slides"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_sale_slides"/>
|
||||
<div class="text-muted">
|
||||
Generate revenues thanks to your courses
|
||||
<div class="o_setting_box" id="website_slides_install_sale_slides">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_sale_slides"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="module_website_sale_slides" string="Paid Courses"/>
|
||||
<div class="text-muted">
|
||||
Sell access to your courses on your website and track revenues.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<search string="Channel Member">
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="channel_id"/>
|
||||
<field name="channel_id" string="Course"/>
|
||||
<separator/>
|
||||
<filter string="Completed" name="filter_completed" domain="[('completed', '=', True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
@@ -22,7 +22,7 @@
|
||||
<field name="name">slide.channel.partner.tree</field>
|
||||
<field name="model">slide.channel.partner</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Attendees" editable="top">
|
||||
<tree string="Attendees" editable="top" sample="1">
|
||||
<field name="channel_id" string="Course Name"/>
|
||||
<field name="channel_user_id"/>
|
||||
<field name="partner_email" string="Email"/>
|
||||
@@ -79,14 +79,30 @@
|
||||
<field name="res_model">slide.channel.partner</field>
|
||||
<field name="view_mode">tree,form,kanban</field>
|
||||
<field name="search_view_id" ref="website_slides.slide_channel_partner_view_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
<strong>No Attendees Yet!</strong>
|
||||
</p>
|
||||
<p>
|
||||
From here you'll be able to monitor attendees and to track their progress.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="slide_channel_partner_action_report" model="ir.actions.act_window">
|
||||
<field name="name">Attendees</field>
|
||||
<field name="res_model">slide.channel.partner</field>
|
||||
<field name="view_mode">tree,kanban</field>
|
||||
<field name="view_mode">tree,form,kanban</field>
|
||||
<field name="search_view_id" ref="website_slides.slide_channel_partner_view_search"/>
|
||||
<field name="context">{'search_default_groupby_channel': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
<strong>No Attendees Yet!</strong>
|
||||
</p>
|
||||
<p>
|
||||
From here you'll be able to monitor attendees and to track their progress.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="slide_channel_tag_action" model="ir.actions.act_window">
|
||||
<field name="name">Course Tags</field>
|
||||
<field name="res_model">slide.channel.tag</field>
|
||||
@@ -53,6 +53,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Course Tag Groups">
|
||||
<field name="name"/>
|
||||
<filter string="Has Menu Entry" name="filter_is_published" domain="[('is_published', '=', True)]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
@@ -70,7 +71,7 @@
|
||||
<field name="is_published"/><br/>
|
||||
</div>
|
||||
<group>
|
||||
<field name="tag_ids">
|
||||
<field name="tag_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="group_sequence" invisible="1"/>
|
||||
@@ -104,6 +105,14 @@
|
||||
<field name="name">Course Groups</field>
|
||||
<field name="res_model">slide.channel.tag.group</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a Course Group
|
||||
</p>
|
||||
<p>
|
||||
Use Course Groups to classify and organize your Courses.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -12,15 +12,24 @@
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_view_slides"
|
||||
type="object"
|
||||
icon="fa-eye"
|
||||
class="oe_stat_button"
|
||||
groups="website_slides.group_website_slides_officer"
|
||||
disabled="1"
|
||||
attrs="{'invisible': [('total_views', '=', 0)]}">
|
||||
<field name="total_views" widget="statinfo" string="Visits"/>
|
||||
</button>
|
||||
<button name="action_view_slides"
|
||||
type="object"
|
||||
icon="fa-files-o"
|
||||
class="oe_stat_button"
|
||||
groups="website_slides.group_website_slides_officer">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value"><field name="total_views" nolabel="1"/> Visits</span>
|
||||
<span class="o_stat_value"><field name="total_slides" nolabel="1"/> Contents</span>
|
||||
</div>
|
||||
<span>
|
||||
<field name="total_slides" widget="statinfo" nolabel="1"/>
|
||||
Published Contents
|
||||
</span>
|
||||
</button>
|
||||
<button name="action_redirect_to_done_members"
|
||||
type="object"
|
||||
@@ -34,14 +43,14 @@
|
||||
</button>
|
||||
<button name="action_redirect_to_members"
|
||||
type="object"
|
||||
icon="fa-users"
|
||||
icon="fa-graduation-cap"
|
||||
class="oe_stat_button"
|
||||
groups="website_slides.group_website_slides_officer">
|
||||
<field name="members_count" string="Attendees" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="action_view_ratings"
|
||||
type="object"
|
||||
icon="fa-star"
|
||||
icon="fa-star-half-o"
|
||||
class="oe_stat_button"
|
||||
groups="website_slides.group_website_slides_officer"
|
||||
attrs="{'invisible': [('allow_comment', '=', False)]}">
|
||||
@@ -81,10 +90,8 @@
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="description" string="Description">
|
||||
<group>
|
||||
<field name="description" colspan="4" placeholder="Common tasks for a computer scientist is asking the right questions and answering questions. In this course, you'll study those topics with activities about mathematics, science and logic."/>
|
||||
</group>
|
||||
<page name="description" string="Description" >
|
||||
<field name="description" widget="html" nolabel="1" placeholder="Common tasks for a computer scientist is asking the right questions and answering questions. In this course, you'll study those topics with activities about mathematics, science and logic."/>
|
||||
</page>
|
||||
<page name="options" string="Options">
|
||||
<group>
|
||||
@@ -100,19 +107,20 @@
|
||||
</group>
|
||||
<group>
|
||||
<group name="communication" string="Communication">
|
||||
<field string="Allow Rating" name="allow_comment"/>
|
||||
<field name="publish_template_id" domain="[('model','=','slide.slide')]"/>
|
||||
<field string="Allow Reviews" name="allow_comment"/>
|
||||
<field name="share_template_id" domain="[('model','=','slide.slide')]" groups="base.group_no_one"/>
|
||||
<field name="completed_template_id"/>
|
||||
<field name="publish_template_id" placeholder="No Notification"/>
|
||||
<field name="completed_template_id" placeholder="No Notification"/>
|
||||
</group>
|
||||
<group name="display" string="Display">
|
||||
<field string="Display" name="channel_type" widget="radio"/>
|
||||
<field name="visibility" widget="radio"/>
|
||||
<field name="promote_strategy" widget="radio"
|
||||
attrs="{'invisible': [('channel_type', '=', 'training')]}"/>
|
||||
<field string="Type" name="channel_type" widget="radio" options="{'horizontal': true}"/>
|
||||
<field name="visibility" widget="radio" options="{'horizontal': true}"/>
|
||||
<field name="promote_strategy" widget="selection"
|
||||
attrs="{'invisible': [('channel_type', '=', 'training')]}"/>
|
||||
<field name="promoted_slide_id"
|
||||
attrs="{'invisible': ['|', ('channel_type', '=', 'training'), ('promote_strategy', '!=', 'specific')],
|
||||
'required': [('channel_type', '!=', 'training'), ('promote_strategy', '=', 'specific')]}"
|
||||
string="Content"
|
||||
domain="[('channel_id', '=', active_id), ('is_category', '=', False)]"/>
|
||||
</group>
|
||||
</group>
|
||||
@@ -174,7 +182,7 @@
|
||||
<field name="total_time" widget="float_time" />
|
||||
<field name="members_count"/>
|
||||
<field name="total_votes"/>
|
||||
<field name="rating_avg_stars"/>
|
||||
<field name="rating_avg_stars" string="Average Rating"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -197,10 +205,35 @@
|
||||
<graph string="Courses" sample="1">
|
||||
<field name="name"/>
|
||||
<field name="total_views" type="measure"/>
|
||||
<field name="karma_slide_comment" invisible="1"/>
|
||||
<field name="karma_review" invisible="1"/>
|
||||
<field name="color" invisible="1"/>
|
||||
<field name="karma_gen_channel_finish" invisible="1"/>
|
||||
<field name="karma_gen_channel_rank" invisible="1"/>
|
||||
<field name="karma_gen_slide_vote" invisible="1"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="slide_channel_view_pivot" model="ir.ui.view">
|
||||
<field name="name">slide.channel.view.pivot</field>
|
||||
<field name="model">slide.channel</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Pivot" default_order="create_date desc" sample="1">
|
||||
<field type="row" name="name" />
|
||||
<field type="measure" name="total_views"/>
|
||||
<field name="karma_slide_comment" invisible="1"/>
|
||||
<field name="karma_review" invisible="1"/>
|
||||
<field name="color" invisible="1"/>
|
||||
<field name="karma_gen_channel_finish" invisible="1"/>
|
||||
<field name="karma_gen_channel_rank" invisible="1"/>
|
||||
<field name="karma_gen_slide_vote" invisible="1"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="slide_channel_view_kanban" model="ir.ui.view">
|
||||
<field name="name">slide.channel.view.kanban</field>
|
||||
<field name="model">slide.channel</field>
|
||||
@@ -229,9 +262,6 @@
|
||||
<div role="menuitem">
|
||||
<a type="edit">Edit</a>
|
||||
</div>
|
||||
<div role="menuitem">
|
||||
<a name="action_view_slides" type="object">Lessons</a>
|
||||
</div>
|
||||
<div role="menuitem" name="action_channel_invite"
|
||||
attrs="{'invisible': [('enroll', '!=', 'invite')]}">
|
||||
<a name="action_channel_invite" type="object">Invite</a>
|
||||
@@ -258,7 +288,7 @@
|
||||
</div>
|
||||
<div class="col-6 o_kanban_primary_right">
|
||||
<div class="d-flex" t-if="record.rating_count.raw_value">
|
||||
<a name="action_view_ratings" type="object" class="mr-auto"><field name="rating_count"/> reviews</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">
|
||||
@@ -272,19 +302,19 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt3">
|
||||
<div class="col-4 border-right">
|
||||
<div class="col-5 border-right">
|
||||
<a name="action_view_slides" type="object" class="d-flex flex-column align-items-center">
|
||||
<span class="font-weight-bold"><field name="total_slides"/></span>
|
||||
<span class="text-muted">Contents</span>
|
||||
<span class="text-muted">Published Contents</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-4 border-right">
|
||||
<div class="col-3 border-right">
|
||||
<a name="action_redirect_to_members" type="object" class="d-flex flex-column align-items-center">
|
||||
<span class="font-weight-bold"><field name="members_count"/></span>
|
||||
<span class="text-muted">Attendees</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="col-3">
|
||||
<a name="action_redirect_to_done_members" type="object" class="d-flex flex-column align-items-center">
|
||||
<span class="font-weight-bold"><field name="members_done_count"/></span>
|
||||
<span name="done_members_count_label" class="text-muted">Finished</span>
|
||||
@@ -300,13 +330,17 @@
|
||||
</record>
|
||||
|
||||
<record id="slide_channel_action_overview" model="ir.actions.act_window">
|
||||
<field name="name">eLearning Overview</field>
|
||||
<field name="name">All Courses</field>
|
||||
<field name="res_model">slide.channel</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="view_id" ref="slide_channel_view_kanban"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a course
|
||||
<strong>Create a course</strong>
|
||||
</p>
|
||||
<p>
|
||||
Your eLearning platform starts here!<br/>
|
||||
Upload content, set up rewards, manage attendees...
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -314,11 +348,15 @@
|
||||
<record id="slide_channel_action_report" model="ir.actions.act_window">
|
||||
<field name="name">Courses</field>
|
||||
<field name="res_model">slide.channel</field>
|
||||
<field name="view_mode">tree,graph,form</field>
|
||||
<field name="view_mode">tree,graph,pivot,form</field>
|
||||
<field name="view_id" ref="slide_channel_view_tree_report"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a course
|
||||
<strong>Create a course</strong>
|
||||
</p>
|
||||
<p>
|
||||
Your eLearning platform starts here!<br/>
|
||||
Upload content, set up rewards, manage attendees...
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<sheet>
|
||||
<label for="question" string="Question Name"/>
|
||||
<h1>
|
||||
<field name="question" default_focus="1"/>
|
||||
<field name="question" default_focus="1" placeholder="e.g. What powers a computer ?"/>
|
||||
</h1>
|
||||
<field name="answer_ids">
|
||||
<tree editable="bottom" create="true" delete="true">
|
||||
@@ -65,14 +65,14 @@
|
||||
<field name="name">Quizzes</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">slide.question</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">tree,graph,pivot,form</field>
|
||||
<field name="view_id" ref="slide_question_view_tree_report"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
There are no quizzes
|
||||
No Quiz data yet!
|
||||
</p>
|
||||
<p>
|
||||
Add quizzes at the end of your lessons to evaluate what your students understood.
|
||||
Come back later to oversee how well your Attendees are doing.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<field name="model">slide.tag</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Tags" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="name" placeholder="e.g 'HowTo'"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -31,6 +31,14 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">slide.tag</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a Content Tag
|
||||
</p>
|
||||
<p>
|
||||
Use Content Tags to classify your Content.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- SLIDE.SLIDE -->
|
||||
@@ -40,19 +48,57 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lesson">
|
||||
<sheet>
|
||||
<field name="channel_type" invisible="1" readonly="1"/>
|
||||
<field name="channel_allow_comment" invisible="1" readonly="1"/>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="is_published" widget="website_redirect_button"
|
||||
<button disabled="1" class="mx-auto disabled oe_read_only"
|
||||
attrs="{'invisible': [('slide_views', '=', 0)]}" icon="fa-eye">
|
||||
<span class="o_stat_value">
|
||||
<field name="slide_views" widget="statinfo" nolabel="1"/> Member Views
|
||||
</span>
|
||||
</button>
|
||||
<button disabled="disabled" class="mx-auto oe_read_only" icon="fa-eye"
|
||||
attrs="{'invisible': [('public_views', '=', 0)]}">
|
||||
<span class="o_stat_value">
|
||||
<field name="public_views" widget="statinfo" nolabel="1"/> Public Views
|
||||
</span>
|
||||
</button>
|
||||
<button disabled="1" class="mx-auto oe_read_only" icon="fa-eye"
|
||||
attrs="{'invisible': [('total_views', '=', 0)]}">
|
||||
<span class="o_stat_value">
|
||||
<field name="total_views" widget="statinfo" nolabel="1"/> Total Views
|
||||
</span>
|
||||
</button>
|
||||
<button disabled="1" icon="fa-thumbs-up" class="oe_stat_button oe_read_only"
|
||||
attrs="{'invisible': ['|', ('channel_type', '=', 'training'), ('likes', '=', 0)]}">
|
||||
<span class="o_stat_value" >
|
||||
<field class="ml-1" name="likes" widget="statinfo" nolabel="1"/> Likes
|
||||
</span>
|
||||
</button>
|
||||
<button disabled="1" icon="fa-thumbs-down" class="oe_stat_button oe_read_only"
|
||||
attrs="{'invisible': ['|', ('channel_type', '=', 'training'), ('dislikes', '=', 0)]}">
|
||||
<span class="o_stat_value">
|
||||
<field class="ml-1" name="dislikes" widget="statinfo" nolabel="1"/> Dislikes
|
||||
</span>
|
||||
</button>
|
||||
<button disabled="1" icon="fa-comments" class="oe_stat_button oe_read_only"
|
||||
attrs="{'invisible': ['|', ('channel_allow_comment', '!=', True), ('comments_count','=', 0)]}">
|
||||
<span class="o_stat_value">
|
||||
<field class="ml-1" name="comments_count" widget="statinfo" nolabel="1"/> Comments
|
||||
</span>
|
||||
</button>
|
||||
<field name="is_published" class="ml-1" widget="website_redirect_button"
|
||||
attrs="{'invisible': ['|',('is_category', '=', True), ('channel_id', '=', False)]}"/>
|
||||
</div>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<field name="image_1920" widget="image" class="oe_avatar" options='{"preview_image": "image_256"}'
|
||||
attrs="{'invisible': [('is_category', '=', True)]}"/>
|
||||
<div class="oe_title">
|
||||
<div class="oe_title pr-xl-0">
|
||||
<div>
|
||||
<label for="name" string="Content Title"/>
|
||||
</div>
|
||||
<h1>
|
||||
<field name="name" default_focus="1" placeholder="e.g. How to grow your business with Odoo?"/>
|
||||
<field name="name" default_focus="1" placeholder="e.g. Setting up your computer" class="mr-0"/>
|
||||
<field name="is_category" invisible="1"/>
|
||||
</h1>
|
||||
<field name="tag_ids" attrs="{'invisible': [('is_category', '=', True)]}" widget="many2many_tags" placeholder="Tags..."/>
|
||||
@@ -63,7 +109,7 @@
|
||||
<group name="lesson_details">
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type"/>
|
||||
<field name="slide_type" string="Content Type"/>
|
||||
<field name="url" attrs="{
|
||||
'required': [('slide_type', 'in', ('video'))],
|
||||
'invisible': [('slide_type', 'not in', ('video'))]}" />
|
||||
@@ -73,7 +119,7 @@
|
||||
attrs="{'invisible': [('slide_type', 'not in', ('document', 'presentation'))]}"/>
|
||||
</group>
|
||||
<group name="related_details">
|
||||
<field name="user_id"/>
|
||||
<field name="user_id" string="Responsible" widget="many2one_avatar"/>
|
||||
<label for="completion_time"/>
|
||||
<div>
|
||||
<field name="completion_time" widget="float_time" class="oe_inline"/>
|
||||
@@ -89,58 +135,40 @@
|
||||
<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="Additional Resources" name="external_links" >
|
||||
<group string="External Links">
|
||||
<field name="link_ids" widget="one2many" nolabel="1">
|
||||
<tree editable="top">
|
||||
<field name="name"/>
|
||||
<field name="link" widget="url" placeholder="e.g. https://www.odoo.com"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<group string="Resources">
|
||||
<group>
|
||||
<field name="slide_resource_ids" widget="one2many" nolabel="1">
|
||||
<tree editable="top">
|
||||
<field name="name"/>
|
||||
<field name="data" string="Size" required="1"/>
|
||||
<field name="resource_type"/>
|
||||
<field name="name" required="1"/>
|
||||
<field name="file_name" invisible="1"/>
|
||||
<field name="data" attrs="{'readonly': [('resource_type', '=', 'url')]}" filename="file_name"/>
|
||||
<field name="link" string="Link"
|
||||
attrs="{'readonly': [('resource_type', '=', 'file')],'required': [('resource_type', '=', 'url')],}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</page>
|
||||
<page name="quiz" string="Quiz">
|
||||
<group name="quiz_details">
|
||||
<group name="quiz_rewards" string="Rewards">
|
||||
<group name="quiz_rewards" string="Points Rewards">
|
||||
<group>
|
||||
<field string="First attempt" name="quiz_first_attempt_reward"/>
|
||||
<field string="Second attempt" name="quiz_second_attempt_reward"/>
|
||||
<field string="Third attempt" name="quiz_third_attempt_reward"/>
|
||||
<field string="Fourth and more attempt" name="quiz_fourth_attempt_reward"/>
|
||||
<field string="First Try" name="quiz_first_attempt_reward"/>
|
||||
<field string="Second Try" name="quiz_second_attempt_reward"/>
|
||||
<field string="Third Try" name="quiz_third_attempt_reward"/>
|
||||
<field string="Fourth Try & More" name="quiz_fourth_attempt_reward"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="questions" string="Questions">
|
||||
<group name="questions">
|
||||
<field name="question_ids" nolabel="1">
|
||||
<tree>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="question"/>
|
||||
<field name="question" string="Question"/>
|
||||
<field name="answer_ids" string="Answers" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="statistics" string="Statistics">
|
||||
<group>
|
||||
<group name="view_statistics" string="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" string="Comments" attrs="{'invisible': [('channel_allow_comment', '!=', True)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
@@ -178,18 +206,21 @@
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type"/>
|
||||
<field name="user_id"/>
|
||||
<field name="image_128"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click o_kanban_record_has_image_fill">
|
||||
<t t-set="placeholder" t-value="'/website_slides/static/src/img/channel-training-default.jpg'"/>
|
||||
<t t-if="record.image_128.raw_value" t-set="image" t-value="kanban_image('slide.slide', 'image_128', record.id.raw_value, placeholder)"/>
|
||||
<t t-else="" t-set="image" t-value="'/website_slides/static/src/img/channel-training-default.jpg'"/>
|
||||
<div class="o_kanban_image_fill_left d-none d-md-block"
|
||||
t-attf-style="background-image:url('#{kanban_image('slide.slide', 'image_128', record.id.raw_value, placeholder)}')">
|
||||
t-attf-style="background-image:url('#{image}')">
|
||||
<img class="o_kanban_image_inner_pic"
|
||||
t-att-alt="record.channel_id.value"
|
||||
t-att-src="kanban_image('slide.channel', 'image_128', record.channel_id.raw_value)"/>
|
||||
</div>
|
||||
<div class="o_kanban_image rounded-circle d-md-none"
|
||||
t-attf-style="background-image:url('#{kanban_image('slide.slide', 'image_128', record.id.raw_value, placeholder)}')">
|
||||
t-attf-style="background-image:url('#{image}')">
|
||||
<img class="o_kanban_image_inner_pic"
|
||||
t-att-alt="record.channel_id.value"
|
||||
t-att-src="kanban_image('slide.channel', 'image_128', record.channel_id.raw_value)"/>
|
||||
@@ -203,15 +234,6 @@
|
||||
</span>
|
||||
</div>
|
||||
<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>
|
||||
<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>
|
||||
<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"/>
|
||||
@@ -228,6 +250,15 @@
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<field name="user_id" widget="many2one_avatar_user"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,6 +297,7 @@
|
||||
<field name="name"/>
|
||||
<filter name="published" string="Published" domain="[('is_published', '=', True)]"/>
|
||||
<filter name="not_published" string="Waiting for validation" domain="[('is_published', '=', False)]"/>
|
||||
<filter name="filter_user_id_uid" string="My Content" domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
@@ -285,6 +317,11 @@
|
||||
<field name="channel_id"/>
|
||||
<field name="slide_type"/>
|
||||
<field name="total_views" type="measure"/>
|
||||
<field name="quiz_first_attempt_reward" invisible="1"/>
|
||||
<field name="quiz_second_attempt_reward" invisible="1"/>
|
||||
<field name="quiz_third_attempt_reward" invisible="1"/>
|
||||
<field name="quiz_fourth_attempt_reward" invisible="1"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -304,11 +341,15 @@
|
||||
<field name="name">Contents</field>
|
||||
<field name="res_model">slide.slide</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context"></field>
|
||||
<field name="context">{'search_default_own_publications':True}</field>
|
||||
<field name="domain">[('is_category', '=', False)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new lesson
|
||||
Add Content
|
||||
</p>
|
||||
<p>
|
||||
Content are the lessons that compose a course
|
||||
<br/>and can be of different types (presentations, documents, videos, ...).
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -33,11 +33,6 @@
|
||||
parent="website_slides_menu_courses"
|
||||
sequence="2"
|
||||
action="slide_slide_action"/>
|
||||
<menuitem name="Reviews"
|
||||
id="website_slides_menu_courses_reviews"
|
||||
parent="website_slides_menu_courses"
|
||||
sequence="3"
|
||||
action="rating_rating_action_slide_channel"/>
|
||||
|
||||
<!-- Reporting sub-menu -->
|
||||
<menuitem name="Courses"
|
||||
@@ -59,7 +54,7 @@
|
||||
id="website_slides_menu_report_reviews"
|
||||
parent="website_slides_menu_report"
|
||||
sequence="10"
|
||||
action="rating_rating_action_slide_channel_report"/>
|
||||
action="rating_rating_action_slide_channel"/>
|
||||
<menuitem name="Quizzes"
|
||||
id="website_slides_menu_report_quizzes"
|
||||
parent="website_slides_menu_report"
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
<t t-else="">Join Course</t>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
||||
<div t-if="not channel.is_member and channel.enroll == 'invite'" class="text-center">
|
||||
<div t-attf-class="alert my-0 bg-100 p-2 #{'o_wslides_js_channel_enroll' if not is_public_user else ''}"
|
||||
t-att-data-channel-id="channel.id">
|
||||
@@ -484,7 +484,7 @@
|
||||
<template id="course_slides_list_slide" name="Slide template for a training channel">
|
||||
<li t-att-index="j" t-att-data-slide-id="slide.id" t-att-data-category-id="category_id" t-attf-class="o_wslides_slides_list_slide o_wslides_js_list_item bg-white-50 border-top-0 d-flex align-items-center pl-2 #{'py-1 pr-2' if not channel.can_upload else ''}">
|
||||
<div t-if="channel.can_publish" class=" o_wslides_slides_list_drag border-right p-2">
|
||||
<i class="fa fa-bars mr-2"></i>
|
||||
<i class="fa fa-sort mr-2"></i>
|
||||
</div>
|
||||
<t t-call="website_slides.slide_icon">
|
||||
<t t-set="icon_class" t-value="'py-2 mx-2'"/>
|
||||
|
||||
@@ -416,7 +416,7 @@
|
||||
<xpath expr="//div[hasclass('o_wslides_home_aside')]" position="inside">
|
||||
<div class="row o_wslides_home_aside_title">
|
||||
<div class="col">
|
||||
<a href="/profile/users" class="float-right">View all</a>
|
||||
<a t-if="users" href="/profile/users" class="float-right">View all</a>
|
||||
<h5 class="m-0">Leaderboard</h5>
|
||||
<hr class="mt-2 pt-2"/>
|
||||
</div>
|
||||
|
||||
@@ -162,10 +162,10 @@
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<ul t-if="aside_slide.link_ids or aside_slide.slide_resource_ids or aside_slide.question_ids" class="list-group px-2 mb-1 list-unstyled">
|
||||
<t t-foreach="aside_slide.link_ids" t-as="resource">
|
||||
<ul t-if="aside_slide.slide_resource_ids or aside_slide.question_ids" class="list-group px-2 mb-1 list-unstyled">
|
||||
<t t-foreach="aside_slide.slide_resource_ids" t-as="resource">
|
||||
<li class="pl-4">
|
||||
<a t-if="can_access" t-att-href="resource.link" target="new" class="text-decoration-none small">
|
||||
<a t-if="can_access and resource.link" t-att-href="resource.link" target="new" class="text-decoration-none small">
|
||||
<i class="fa fa-link mr-1"/><span t-field="resource.name"/>
|
||||
</a>
|
||||
<span t-else="" class="text-decoration-none text-muted small">
|
||||
@@ -383,6 +383,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="slide.channel_id.allow_comment and slide.channel_id.channel_type == 'documentation'"
|
||||
class="col-12 col-md d-flex align-items-start justify-content-md-start mb-2 mb-md-0">
|
||||
<span class="text-muted font-weight-bold mr-3">Rating</span>
|
||||
<div class="text-muted border-left pl-3">
|
||||
<div class="o_wslides_js_slide_like mr-2">
|
||||
<span t-attf-class="o_wslides_js_slide_like_up #{'disabled' if not slide.channel_id.can_vote else ''}" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
|
||||
<i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i>
|
||||
<span t-esc="slide.likes"/>
|
||||
</span>
|
||||
<span t-attf-class="o_wslides_js_slide_like_down ml-3 #{'disabled' if not slide.channel_id.can_vote else ''}" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
|
||||
<i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i>
|
||||
<span t-esc="slide.dislikes"/>
|
||||
</span>
|
||||
</div>
|
||||
</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'">
|
||||
<t t-if="slide.question_ids">
|
||||
@@ -394,43 +410,31 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 mb-3">
|
||||
<div class="col-12 col-md d-flex align-items-start mb-4 mb-md-0" t-if="len(slide.link_ids)">
|
||||
<span t-if="slide.link_ids" class="text-muted font-weight-bold mr-3">External sources</span>
|
||||
<t t-set="links" t-value="slide.slide_resource_ids.filtered(lambda res: res.resource_type == 'url')"/>
|
||||
<t t-set="files" t-value="slide.slide_resource_ids.filtered(lambda res: res.resource_type == 'file' and res.data)"/>
|
||||
<div class="col-12 col-md d-flex align-items-start mb-4 mb-md-0" t-if="links">
|
||||
<span class="text-muted font-weight-bold mr-3">External sources</span>
|
||||
<div class="text-muted mr-auto border-left pl-3">
|
||||
<t t-foreach="slide.link_ids" t-as="link">
|
||||
<t t-foreach="links" t-as="link">
|
||||
<a t-att-href="link.link" t-esc="link.name"/><br />
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md d-flex align-items-start mb-4 mb-md-0 o_wslides_js_course_join" t-if="len(slide.slide_resource_ids)">
|
||||
<span t-if="slide.channel_id.is_member or slide.channel_id.can_publish or slide.is_preview or slide.channel_id.enroll in ['private', 'payment']" class="text-muted font-weight-bold mr-3">
|
||||
Additional Resources
|
||||
</span>
|
||||
<div t-if="slide.channel_id.is_member or slide.channel_id.can_publish" class="text-muted mr-auto border-left pl-3">
|
||||
<t t-foreach="slide.slide_resource_ids" t-as="resource">
|
||||
<a t-attf-href="/web/content/slide.slide.resource/#{resource.id}/data?download=true" t-esc="resource.name"/><br />
|
||||
</t>
|
||||
</div>
|
||||
<div t-elif="slide.channel_id.enroll == 'public'" class="text-muted mr-auto border-left pl-3">
|
||||
<t t-call="website_slides.join_course_link"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="slide.channel_id.allow_comment and slide.channel_id.channel_type == 'documentation'"
|
||||
class="col-12 col-md d-flex align-items-start justify-content-md-end mb-2 mb-md-0">
|
||||
<span class="text-muted font-weight-bold mr-3">Rating</span>
|
||||
<div class="text-muted border-left pl-3">
|
||||
<div class="o_wslides_js_slide_like mr-2">
|
||||
<span t-att-class="('o_wslides_js_slide_like_up %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
|
||||
<i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i>
|
||||
<span t-esc="slide.likes"/>
|
||||
</span>
|
||||
<span t-att-class="('o_wslides_js_slide_like_down ml-3 %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
|
||||
<i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i>
|
||||
<span t-esc="slide.dislikes"/>
|
||||
</span>
|
||||
<group>
|
||||
<div class="col-12 col-md d-flex align-items-start mb-4 mb-md-0 o_wslides_js_course_join" t-if="files">
|
||||
<span t-if="slide.channel_id.is_member or slide.channel_id.can_publish or slide.is_preview or slide.channel_id.enroll in ['private', 'payment']" class="text-muted font-weight-bold mr-3">
|
||||
Additional Resources
|
||||
</span>
|
||||
<div t-if="slide.channel_id.is_member or slide.channel_id.can_publish" class="text-muted mr-auto border-left pl-3">
|
||||
<t t-foreach="files" t-as="resource">
|
||||
<a t-attf-href="/web/content/slide.slide.resource/#{resource.id}/data?download=true" t-esc="resource.name"/><br />
|
||||
</t>
|
||||
</div>
|
||||
<div t-elif="slide.channel_id.enroll == 'public'" class="text-muted mr-auto border-left pl-3">
|
||||
<t t-call="website_slides.join_course_link"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -135,18 +135,20 @@
|
||||
<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.link_ids or slide.slide_resource_ids or (slide.question_ids and not slide.slide_type =='quiz')" >
|
||||
<li t-if="slide.link_ids" t-foreach="slide.link_ids" t-as="link" class="pl-0 mb-1">
|
||||
<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')" >
|
||||
<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">
|
||||
<i class="fa fa-link mr-2"/><span t-esc="link.name"/>
|
||||
</a>
|
||||
<span t-else="" class="o_wslides_fs_slide_link text-600">
|
||||
<i class="fa fa-link mr-2"/><span t-esc="link.name"/>
|
||||
<i class="fa fa-link mr-2"/><span t-esc="resource.name"/>
|
||||
</span>
|
||||
</li>
|
||||
<div class="o_wslides_js_course_join pl-0" t-if="slide.slide_resource_ids">
|
||||
<t t-set="resources" t-value="slide.slide_resource_ids.filtered(lambda res: res.resource_type == 'file')"/>
|
||||
<div class="o_wslides_js_course_join pl-0" t-if="resources">
|
||||
<t t-if="is_member or slide.channel_id.can_publish">
|
||||
<li t-foreach="slide.slide_resource_ids" t-as="resource" class="mb-1">
|
||||
<li t-foreach="resources" t-as="resource" class="mb-1">
|
||||
<a class="o_wslides_fs_slide_link" t-attf-href="/web/content/slide.slide.resource/#{resource.id}/data?download=true">
|
||||
<i class="fa fa-download mr-2"/><span t-esc="resource.name"/>
|
||||
</a>
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_slides_forum_security.xml',
|
||||
'views/forum_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/slide_channel_views.xml',
|
||||
'views/website_slides_menu_views.xml',
|
||||
'views/website_slides_forum_templates.xml',
|
||||
'views/website_slides_templates.xml',
|
||||
'views/website_slides_forum_templates.xml'
|
||||
],
|
||||
'demo': [
|
||||
'data/slide_channel_demo.xml',
|
||||
|
||||
@@ -7,7 +7,7 @@ from odoo import api, fields, models
|
||||
class Channel(models.Model):
|
||||
_inherit = 'slide.channel'
|
||||
|
||||
forum_id = fields.Many2one('forum.forum', 'Course Forum')
|
||||
forum_id = fields.Many2one('forum.forum', 'Course Forum', copy=False)
|
||||
forum_total_posts = fields.Integer('Number of active forum posts', related="forum_id.total_posts")
|
||||
|
||||
_sql_constraints = [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="inherit_id" ref="website_forum.view_forum_forum_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='group_order']" position="after">
|
||||
<group string="eLearning" name="group_slides">
|
||||
<group string="eLearning" name="group_slides" attrs="{'invisible': [('slide_channel_id', '=', False)]}">
|
||||
<field name="slide_channel_id" readonly="True"/>
|
||||
</group>
|
||||
</xpath>
|
||||
@@ -23,22 +23,29 @@
|
||||
</record>
|
||||
|
||||
<record id="forum_forum_action_channel" model="ir.actions.act_window">
|
||||
<field name="name">eLearning Forums</field>
|
||||
<field name="name">Forums</field>
|
||||
<field name="res_model">forum.forum</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('slide_channel_ids', '!=', 'False')]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a Forum
|
||||
</p>
|
||||
<p>Forums allow your attendees to ask questions to your community.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="forum_post_action_channel" model="ir.actions.act_window">
|
||||
<field name="name">eLearning Forum Posts</field>
|
||||
<field name="name">Forum Posts</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">tree,graph,pivot,form</field>
|
||||
<field name="domain">[('forum_id.slide_channel_ids', '!=', 'False')]</field>
|
||||
<field name="context">{'search_default_questions': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new forum post
|
||||
No Forum Post yet!
|
||||
</p>
|
||||
<p>Come back later to monitor and moderate what is posted on your Forums.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -53,16 +60,4 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="forum_post_action_report" model="ir.actions.act_window">
|
||||
<field name="name">eLearning Forum Posts</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="forum_post_view_graph_slides"/>
|
||||
<field name="domain">[('forum_id.slide_channel_ids', '!=', 'False')]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No data yet!
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.website.slides.forum</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="website_slides.res_config_settings_view_form"/>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='website_slide_install_website_slides_forum']//div[hasclass('text-muted')]" position="after">
|
||||
<div class="mt8">
|
||||
<button type="action" name="%(website_slides_forum.forum_forum_action_channel)d" string="Manage Forums" class="btn-link" icon="fa-arrow-right"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -14,10 +14,4 @@
|
||||
parent="website_slides_menu_forum"
|
||||
sequence="2"
|
||||
action="forum_post_action_channel"/>
|
||||
|
||||
<menuitem name="Forum"
|
||||
id="website_slides_menu_report_forum"
|
||||
parent="website_slides.website_slides_menu_report"
|
||||
sequence="20"
|
||||
action="forum_post_action_report"/>
|
||||
</odoo>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
'views/website_profile.xml',
|
||||
'data/mail_template_data.xml',
|
||||
'data/gamification_data.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/survey_demo.xml',
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
|
||||
class Survey(models.Model):
|
||||
@@ -22,6 +24,14 @@ class Survey(models.Model):
|
||||
survey.slide_channel_ids = survey.slide_ids.mapped('channel_id')
|
||||
survey.slide_channel_count = len(survey.slide_channel_ids)
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_linked_to_course(self):
|
||||
slides = self.slide_ids.filtered(lambda slide: slide.slide_type == "certification").exists()
|
||||
if slides:
|
||||
raise ValidationError(_("The Certification '%(certification_name)s' cannot be deleted because it is still being used by the Course(s) '%(courses_names)s'",
|
||||
certification_name=self.title,
|
||||
courses_names=', '.join(slides.mapped('channel_id.name'))))
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Actions
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_course_certification_failure
|
||||
from . import test_course_certification_unlink
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
from odoo.addons.website_slides.tests.common import SlidesCase
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import users
|
||||
|
||||
|
||||
class TestSurvey(SlidesCase):
|
||||
def setUp(self):
|
||||
super(TestSurvey, self).setUp()
|
||||
|
||||
self.survey = self.env['survey.survey'].create({'title': 'TestSurvey'})
|
||||
self.survey2 = self.env['survey.survey'].create({'title': 'TestSurvey'})
|
||||
|
||||
@users('user_manager')
|
||||
def test_unlink(self):
|
||||
self.certification = self.env['slide.slide'].create({
|
||||
'name': 'Certification',
|
||||
'slide_type': 'certification',
|
||||
'channel_id': self.channel.id,
|
||||
'survey_id': self.survey.id,
|
||||
})
|
||||
|
||||
with self.assertRaises(ValidationError, msg="The error is unexpected"):
|
||||
self.survey.unlink()
|
||||
|
||||
self.assertTrue(self.survey.exists())
|
||||
self.certification.survey_id = self.survey2
|
||||
self.survey.unlink()
|
||||
self.assertFalse(self.survey.exists())
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.website.slides.survey</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="website_slides.res_config_settings_view_form"/>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='website_slide_install_website_slides_survey']//div[hasclass('text-muted')]" position="after">
|
||||
<div class="mt8">
|
||||
<button type="action" name="%(website_slides_survey.survey_survey_action_slides)d" string="Manage Certifications" class="btn-link" icon="fa-arrow-right"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,27 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="survey_survey_action_slides" model="ir.actions.act_window">
|
||||
<field name="name">Certifications</field>
|
||||
<field name="res_model">survey.survey</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="domain">[('certification', '=', True)]</field>
|
||||
<field name="context">{'default_certification': True, 'default_scoring_type': 'scoring_with_answers'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new certification
|
||||
</p>
|
||||
<record id="survey_survey_inherit_view_search" model="ir.ui.view">
|
||||
<field name="name">survey.survey.search.inherit.website_slides</field>
|
||||
<field name="model">survey.survey</field>
|
||||
<field name="inherit_id" ref="survey.survey_survey_view_search"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr='//filter[@name="certification"]' position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="survey_survey_action_slides_report" model="ir.actions.act_window">
|
||||
<record id="survey_survey_action_slides" model="ir.actions.act_window">
|
||||
<field name="name">Certifications</field>
|
||||
<field name="res_model">survey.survey</field>
|
||||
<field name="view_mode">tree,kanban,form,graph</field>
|
||||
<field name="view_mode">kanban,tree,pivot,graph,form</field>
|
||||
<field name="domain">[('certification', '=', True)]</field>
|
||||
<field name="search_view_id" ref="survey_survey_inherit_view_search"/>
|
||||
<field name="context">{'default_certification': True, 'default_scoring_type': 'scoring_with_answers'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new certification
|
||||
Create a Certification
|
||||
</p>
|
||||
<p>
|
||||
Assess the level of understanding of your attendees
|
||||
<br/>and send them a document if they pass the test.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,10 +5,4 @@
|
||||
parent="website_slides.website_slides_menu_courses"
|
||||
sequence="3"
|
||||
action="survey_survey_action_slides"/>
|
||||
|
||||
<menuitem name="Certifications"
|
||||
id="website_slides_menu_report_certification"
|
||||
parent="website_slides.website_slides_menu_report"
|
||||
sequence="40"
|
||||
action="survey_survey_action_slides_report"/>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user